From f233e995b529eade772733392e0a9cf7948d57d6 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Tue, 15 Aug 2023 16:51:01 +0930 Subject: [PATCH 01/14] added arm32 support --- .gitignore | 1 + CMakeLists.txt | 19 + bindings/python/py_arch.cpp | 1 + src/arch/arch_ARM32.cpp | 126 + src/arch/lifter.cpp | 12 + src/arch/register_aliases.cpp | 57 +- src/engine/engine.cpp | 43 + src/include/maat/arch.hpp | 73 + src/include/maat/engine.hpp | 2 + src/include/maat/loader.hpp | 2 +- src/include/maat/sleigh_interface.hpp | 1 + src/loader/loader_lief.cpp | 4 +- src/loader/loader_lief_elf.cpp | 44 +- .../sleigh/native/reg_translator.cpp | 50 + .../sleigh/native/sleigh_interface.cpp | 9 + .../processors/ARM/data/languages/ARM.cspec | 247 + .../processors/ARM/data/languages/ARM.dwarf | 12 + .../processors/ARM/data/languages/ARM.gdis | 41 + .../processors/ARM/data/languages/ARM.ldefs | 377 + .../processors/ARM/data/languages/ARM.opinion | 59 + .../processors/ARM/data/languages/ARM.sinc | 303 + .../ARM/data/languages/ARM4_be.slaspec | 5 + .../ARM/data/languages/ARM4_le.slaspec | 5 + .../ARM/data/languages/ARM4t_be.slaspec | 6 + .../ARM/data/languages/ARM4t_le.slaspec | 6 + .../ARM/data/languages/ARM5_be.slaspec | 7 + .../ARM/data/languages/ARM5_le.slaspec | 7 + .../ARM/data/languages/ARM5t_be.slaspec | 9 + .../ARM/data/languages/ARM5t_le.slaspec | 8 + .../ARM/data/languages/ARM6_be.slaspec | 12 + .../ARM/data/languages/ARM6_le.slaspec | 12 + .../ARM/data/languages/ARM7_be.slaspec | 15 + .../ARM/data/languages/ARM7_le.slaspec | 15 + .../ARM/data/languages/ARM8_be.slaspec | 16 + .../ARM/data/languages/ARM8_le.slaspec | 16 + .../ARM/data/languages/ARMCortex.pspec | 43 + .../data/languages/ARMTHUMBinstructions.sinc | 5294 ++++++++++++++ .../ARM/data/languages/ARM_v45.cspec | 209 + .../ARM/data/languages/ARM_v45.pspec | 39 + .../ARM/data/languages/ARM_win.cspec | 131 + .../ARM/data/languages/ARMinstructions.sinc | 6441 ++++++++++++++++ .../ARM/data/languages/ARMneon.dwarf | 14 + .../ARM/data/languages/ARMneon.sinc | 4717 ++++++++++++ .../processors/ARM/data/languages/ARMt.pspec | 63 + .../ARM/data/languages/ARMtTHUMB.pspec | 64 + .../ARM/data/languages/ARMt_v45.pspec | 42 + .../ARM/data/languages/ARMt_v6.pspec | 43 + .../processors/ARM/data/languages/ARMv8.sinc | 1443 ++++ .../ARM/data/languages/old/ARMv5.lang | 62 + .../ARM/data/languages/old/ARMv5.trans | 6 + .../ARM/data/languages/old/THUMBv2.lang | 55 + .../ARM/data/languages/old/THUMBv2.trans | 11 + .../processors/ARM/data/manuals/ARM.idx | 6461 +++++++++++++++++ .../ARM/data/patterns/ARM_BE_patterns.xml | 201 + .../ARM/data/patterns/ARM_LE_patterns.xml | 322 + .../ARM/data/patterns/patternconstraints.xml | 13 + tests/CMakeLists.txt | 1 + tests/unit-tests/test_all.cpp | 4 + tests/unit-tests/test_archARM32.cpp | 394 + 59 files changed, 27673 insertions(+), 22 deletions(-) create mode 100644 src/arch/arch_ARM32.cpp create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.cspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.dwarf create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.gdis create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.ldefs create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.opinion create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM.sinc create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM4_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM4_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM4t_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM4t_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM5_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM5_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM5t_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM5t_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM6_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM6_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM7_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM7_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM8_be.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM8_le.slaspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMCortex.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMTHUMBinstructions.sinc create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.cspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARM_win.cspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMinstructions.sinc create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMneon.dwarf create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMneon.sinc create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMt.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMtTHUMB.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMt_v45.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMt_v6.pspec create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/ARMv8.sinc create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.lang create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.trans create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.lang create mode 100644 src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.trans create mode 100644 src/third-party/sleigh/processors/ARM/data/manuals/ARM.idx create mode 100644 src/third-party/sleigh/processors/ARM/data/patterns/ARM_BE_patterns.xml create mode 100644 src/third-party/sleigh/processors/ARM/data/patterns/ARM_LE_patterns.xml create mode 100644 src/third-party/sleigh/processors/ARM/data/patterns/patternconstraints.xml create mode 100644 tests/unit-tests/test_archARM32.cpp diff --git a/.gitignore b/.gitignore index 7a55dead..85116d72 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ prefix/ CMakeLists.txt.user CMakeUserPresets.json maat_state_* +bashbuild diff --git a/CMakeLists.txt b/CMakeLists.txt index c7be0169..2f516cf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ include(cmake/variables.cmake) add_library(maat_maat src/arch/arch_EVM.cpp src/arch/arch_X86.cpp + src/arch/arch_ARM32.cpp src/arch/lifter.cpp src/arch/register_aliases.cpp src/engine/callother.cpp @@ -180,15 +181,33 @@ macro(maat_sleigh_compile ARCH_DIR ARCH) configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${ARCH}.pspec" "${spec_out_dir}/${ARCH}.pspec") endmacro() +macro(maat_sleigh_compile_files ARCH_DIR ARCH SLASPEC PSPEC) + # ARCH_DIR is the directory that appears in Ghidra's source code hierarchy + # ARCH appears in the name of the '.slaspec' and '.pspec' file (they should be the same) + # Creates a target maat_sleigh_spec_${ARCH} + sleigh_compile( + TARGET maat_sleigh_spec_${ARCH} + COMPILER "${maat_SLEIGH_COMPILER}" + SLASPEC "${spec_dir}/${ARCH_DIR}/data/languages/${SLASPEC}.slaspec" + LOG_FILE "${PROJECT_BINARY_DIR}/sleigh-log/${ARCH}.log" + OUT_FILE "${spec_out_dir}/${SLASPEC}.sla" + ) + configure_file("${spec_dir}/${ARCH_DIR}/data/languages/${PSPEC}.pspec" "${spec_out_dir}/${PSPEC}.pspec") +endmacro() + maat_sleigh_compile(x86 x86-64) maat_sleigh_compile(x86 x86) maat_sleigh_compile(EVM EVM) +maat_sleigh_compile_files(ARM ARM32 ARM7_le ARMt) +maat_sleigh_compile_files(ARM THUMB32 ARM7_le ARMtTHUMB) # All of the sla spec targets are combined into this one add_custom_target(maat_all_sla_specs DEPENDS maat_sleigh_spec_x86-64 maat_sleigh_spec_x86 maat_sleigh_spec_EVM + maat_sleigh_spec_ARM32 + maat_sleigh_spec_THUMB32 ) # Add sla specs as dependencies to our targets diff --git a/bindings/python/py_arch.cpp b/bindings/python/py_arch.cpp index 6961fe14..4c6ee925 100644 --- a/bindings/python/py_arch.cpp +++ b/bindings/python/py_arch.cpp @@ -11,6 +11,7 @@ void init_arch(PyObject* module) PyDict_SetItemString(arch_enum, "X86", PyLong_FromLong((int)Arch::Type::X86)); PyDict_SetItemString(arch_enum, "X64", PyLong_FromLong((int)Arch::Type::X64)); PyDict_SetItemString(arch_enum, "EVM", PyLong_FromLong((int)Arch::Type::EVM)); + PyDict_SetItemString(arch_enum, "ARM32", PyLong_FromLong((int)Arch::Type::ARM32)); PyObject* arch_class = create_class(PyUnicode_FromString("ARCH"), PyTuple_New(0), arch_enum); PyModule_AddObject(module, "ARCH", arch_class); diff --git a/src/arch/arch_ARM32.cpp b/src/arch/arch_ARM32.cpp new file mode 100644 index 00000000..f5bd5b43 --- /dev/null +++ b/src/arch/arch_ARM32.cpp @@ -0,0 +1,126 @@ +#include "maat/arch.hpp" +#include "maat/exception.hpp" +#include "maat/cpu.hpp" + +namespace maat +{ +namespace ARM32 +{ + ArchARM32::ArchARM32(): Arch(Arch::Type::ARM32, 32, ARM32::NB_REGS) + { + available_modes = {CPUMode::A32,CPUMode::T32}; + reg_map = + { + {"r0", R0}, + {"r1", R1}, + {"r2", R2}, + {"r3", R3}, + {"r4", R4}, + {"r5", R5}, + {"r6", R6}, + {"r7", R7}, + {"r8", R8}, + {"r9", R9}, + {"r10", R10}, + {"r11", R11}, + {"r12", R12}, + {"r13", R13}, + {"r14", R14}, + {"r15", R15}, + + {"fp", FP}, + {"ip", IP}, + {"sp", SP}, + {"lr", LR}, + {"pc", PC}, + + {"cpsr", CPSR}, + + {"nf", NF}, + {"zf", ZF}, + {"cf", CF}, + {"vf", VF}, + {"qf", QF}, + + {"jf", JF}, + {"ge1", GE1}, + {"ge2", GE2}, + {"ge3", GE3}, + {"ge4", GE4}, + {"tf", TF}, + + {"tmpNG", tmpNG}, + {"tmpZR", tmpZR}, + {"tmpCY", tmpCY}, + {"tmpOV", tmpOV}, + {"sc", SC}, //shift_carry + {"ISAModeSwitch", ISAModeSwitch} + }; + } + + size_t ArchARM32::reg_size(reg_t reg_num) const + { + switch (reg_num) { + case R0: + case R1: + case R2: + case R3: + case R4: + case R5: + case R6: + case R7: + case R8: + case R9: + case R10: + case R11: + case R12: + case R13: + case R14: + case R15: + case CPSR: + case mult_addr: + return 32; + case mult_dat8: + return 64; + case mult_dat16: + return 128; + case NF: + case ZF: + case CF: + case VF: + case QF: + case JF: + case GE1: + case GE2: + case GE3: + case GE4: + case TF: + case tmpNG: + case tmpZR: + case tmpCY: + case tmpOV: + case SC: + case ISAModeSwitch: + return 8; + + default: + throw runtime_exception("ArchARM32::reg_size(): got unsupported reg num"); + } + } + + reg_t ArchARM32::sp() const + { + return ARM32::SP; + } + + reg_t ArchARM32::pc() const + { + return ARM32::PC; + } + + reg_t ArchARM32::tsc() const + { + throw runtime_exception("ArchARM32::tsc(): method not available"); + } +} // namespace ARM32 +} // namespace maat diff --git a/src/arch/lifter.cpp b/src/arch/lifter.cpp index 2cb4cebe..3b4dacd5 100644 --- a/src/arch/lifter.cpp +++ b/src/arch/lifter.cpp @@ -38,6 +38,18 @@ Lifter::Lifter(CPUMode m): mode(m) pspecfile = config.find_sleigh_file("EVM.pspec"); arch = Arch::Type::EVM; } + else if (mode == CPUMode::A32) + { + slafile = config.find_sleigh_file("ARM7_le.sla"); + pspecfile = config.find_sleigh_file("ARMt.pspec"); + arch = Arch::Type::ARM32; + } + else if (mode == CPUMode::T32) + { + slafile = config.find_sleigh_file("ARM7_le.sla"); + pspecfile = config.find_sleigh_file("ARMtTHUMB.pspec"); + arch = Arch::Type::ARM32; + } else { throw lifter_exception("Lifter: this CPU mode is not supported"); diff --git a/src/arch/register_aliases.cpp b/src/arch/register_aliases.cpp index 607eb608..69a9c4f7 100644 --- a/src/arch/register_aliases.cpp +++ b/src/arch/register_aliases.cpp @@ -136,6 +136,55 @@ Value x64_alias_getter(CPUContext& ctx, ir::reg_t reg) std::set x64_aliases{X64::RFLAGS}; +void arm32_alias_setter(CPUContext& ctx, ir::reg_t reg, const Value& val) +{ + if (reg == ARM32::CPSR) + { + _set_flag_from_bit(ctx, ARM32::TF, val, 5); + _set_flag_from_bit(ctx, ARM32::GE1, val, 16); + _set_flag_from_bit(ctx, ARM32::GE2, val, 17); + _set_flag_from_bit(ctx, ARM32::GE3, val, 18); + _set_flag_from_bit(ctx, ARM32::GE4, val, 19); + _set_flag_from_bit(ctx, ARM32::JF, val, 24); + _set_flag_from_bit(ctx, ARM32::QF, val, 27); + _set_flag_from_bit(ctx, ARM32::VF, val, 28); + _set_flag_from_bit(ctx, ARM32::CF, val, 29); + _set_flag_from_bit(ctx, ARM32::ZF, val, 30); + _set_flag_from_bit(ctx, ARM32::NF, val, 31); + } + else + throw runtime_exception("arm32_alias_setter: got unsupported register"); +} + +Value arm32_alias_getter(CPUContext& ctx, ir::reg_t reg) +{ + Value res; + if (reg == ARM32::CPSR) + { + + res = Value(5,0); + res.set_concat(extract(ctx.get(ARM32::TF),0,0), res); + res.set_concat(Value(10,0), res); + res.set_concat(extract(ctx.get(ARM32::GE1),0,0), res); + res.set_concat(extract(ctx.get(ARM32::GE2),0,0), res); + res.set_concat(extract(ctx.get(ARM32::GE3),0,0), res); + res.set_concat(extract(ctx.get(ARM32::GE4),0,0), res); + res.set_concat(Value(4,0), res); + res.set_concat(extract(ctx.get(ARM32::JF),0,0), res); + res.set_concat(Value(2,0), res); + res.set_concat(extract(ctx.get(ARM32::QF),0,0), res); + res.set_concat(extract(ctx.get(ARM32::VF),0,0), res); + res.set_concat(extract(ctx.get(ARM32::CF),0,0), res); + res.set_concat(extract(ctx.get(ARM32::ZF),0,0), res); + res.set_concat(extract(ctx.get(ARM32::NF),0,0), res); + } + else + throw runtime_exception("arm32_alias_getter: got unsupported register"); + return res; +} + +std::set arm32_aliases{ARM32::CPSR}; + void CPUContext::init_alias_getset(Arch::Type arch) { if (arch == Arch::Type::X86) @@ -150,7 +199,13 @@ void CPUContext::init_alias_getset(Arch::Type arch) alias_getter = x64_alias_getter; aliased_regs = x64_aliases; } + else if (arch == Arch::Type::ARM32) + { + alias_setter = arm32_alias_setter; + alias_getter = arm32_alias_getter; + aliased_regs = arm32_aliases; + } } } // namespace ir -} // namespace maat \ No newline at end of file +} // namespace maat diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 36965036..b19ff231 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -32,6 +32,11 @@ MaatEngine::MaatEngine(Arch::Type _arch, env::OS os): env(nullptr), _uid(++_uid_ env = std::make_shared(); endianness = Endian::BIG; break; + case Arch::Type::ARM32: + arch = std::make_shared(); + lifters[CPUMode::A32] = std::make_shared(CPUMode::A32); + _current_cpu_mode = CPUMode::A32; + break; case Arch::Type::NONE: arch = std::make_shared(); _current_cpu_mode = CPUMode::NONE; @@ -74,6 +79,25 @@ MaatEngine::MaatEngine(Arch::Type _arch, env::OS os): env(nullptr), _uid(++_uid_ #endif } +void MaatEngine::change_modes(CPUMode _arch) +{ + CPUMode tempMode; + switch (_arch) + { + case CPUMode::A32: + // switch current_CPU_Mode + lifters[CPUMode::A32] = std::make_shared(CPUMode::A32); + _current_cpu_mode = CPUMode::A32; + break; + case CPUMode::T32: + lifters[CPUMode::T32] = std::make_shared(CPUMode::T32); + _current_cpu_mode = CPUMode::T32; + break; + default: + throw runtime_exception("MaatEngine(): Can't swap modes for this architecture"); + } +} + MaatEngine::MaatEngine( const MaatEngine& other, std::set& duplicate, @@ -282,6 +306,25 @@ info::Stop MaatEngine::run(int max_inst) } _previous_halt_before_exec = -1; + // If Arch == ARM then check if mode needs to change + if ( arch->type == Arch::Type::ARM32) + { + // check the TF bit and change modes + switch (cpu.ctx().get(ARM32::TF).as_uint()) + { + case 0: + if (_current_cpu_mode != CPUMode::A32){ + change_modes(CPUMode::A32); + } + break; + case 1: + if (_current_cpu_mode != CPUMode::T32){ + change_modes(CPUMode::T32); + } + break; + } + + } // TODO: periodically increment tsc() ? // Get the PCODE IR diff --git a/src/include/maat/arch.hpp b/src/include/maat/arch.hpp index ddb96ef3..644c1faf 100644 --- a/src/include/maat/arch.hpp +++ b/src/include/maat/arch.hpp @@ -424,6 +424,79 @@ namespace ARM64 /** \} */ // Arch doxygen group +namespace ARM32 +{ + static constexpr reg_t R0 = 0; + static constexpr reg_t R1 = 1; + static constexpr reg_t R2 = 2; + static constexpr reg_t R3 = 3; + static constexpr reg_t R4 = 4; + static constexpr reg_t R5 = 5; + static constexpr reg_t R6 = 6; + static constexpr reg_t R7 = 7; + static constexpr reg_t R8 = 8; + static constexpr reg_t R9 = 9; + static constexpr reg_t R10 = 10; + static constexpr reg_t R11 = 11; + static constexpr reg_t FP = 11; // Same as R11 + static constexpr reg_t R12 = 12; + static constexpr reg_t IP = 12; // Same as R12 + static constexpr reg_t R13 = 13; + static constexpr reg_t SP = 13; // Same as R13 + static constexpr reg_t R14 = 14; + static constexpr reg_t LR = 14; // Same as R14 + static constexpr reg_t R15 = 15; + static constexpr reg_t PC = 15; // Same as R15 + + static constexpr reg_t CPSR = 16; // Current Program Status Register + + // CPSR bits; TODO: add other flags + static constexpr reg_t NF = 17; + static constexpr reg_t ZF = 18; + static constexpr reg_t CF = 19; + static constexpr reg_t VF = 20; + static constexpr reg_t QF = 21; + + static constexpr reg_t JF = 22; + static constexpr reg_t GE1 = 23; + static constexpr reg_t GE2 = 24; + static constexpr reg_t GE3 = 25; + static constexpr reg_t GE4 = 26; + static constexpr reg_t TF = 27; //thumb-bit (TB) + + static constexpr reg_t tmpNG = 28; + static constexpr reg_t tmpZR = 29; + static constexpr reg_t tmpCY = 30; + static constexpr reg_t tmpOV = 31; + static constexpr reg_t SC = 32; //shift_carry + + // nathan added register (clean up after) + static constexpr reg_t ISAModeSwitch = 33; + static constexpr reg_t mult_addr = 34; // Special internal register for dealing with multiple stores/loads 32 bits + static constexpr reg_t mult_dat8 = 35; // Special internal register for dealing with multiple stores/loads 64 bits + static constexpr reg_t mult_dat16 = 36; // Special internal register for dealing with multiple stores/loads 128 bits + + + static constexpr reg_t NB_REGS = 37; + + /** \addtogroup arch + * \{ */ + class ArchARM32: public Arch + { + public: + ArchARM32(); + virtual ~ArchARM32() = default; + const std::string& reg_name(reg_t num) const; + reg_t reg_num(const std::string& name) const; + size_t reg_size(reg_t reg_num) const; + reg_t sp() const; + reg_t pc() const; + reg_t tsc() const; + }; + /** \} */ // Arch doxygen group + +} // namespace ARM32 + } // namespace maat #endif diff --git a/src/include/maat/engine.hpp b/src/include/maat/engine.hpp index ced6ab0a..805669d2 100644 --- a/src/include/maat/engine.hpp +++ b/src/include/maat/engine.hpp @@ -91,6 +91,8 @@ class MaatEngine: public serial::Serializable info::Info info; /// Engine's tweakable settings and options Settings settings; + // Change CPU modes on the fly Nathan's code + void change_modes(maat::CPUMode _arch); /// Logger Logger log; public: diff --git a/src/include/maat/loader.hpp b/src/include/maat/loader.hpp index 2f9fe3d8..ebadd180 100644 --- a/src/include/maat/loader.hpp +++ b/src/include/maat/loader.hpp @@ -144,7 +144,7 @@ class LoaderLIEF : public Loader private: void parse_binary(const std::string& binary, loader::Format type); void get_arch_special_registers( - const Arch& arch, reg_t& pc, reg_t& sp, reg_t& bp, reg_t& gs, reg_t& fs + const Arch& arch, std::optional& pc, std::optional& sp, std::optional& bp, std::optional& gs, std::optional& fs ); void map_elf_segments(MaatEngine*engine, addr_t base_address); void load_elf_dependencies( diff --git a/src/include/maat/sleigh_interface.hpp b/src/include/maat/sleigh_interface.hpp index d2884524..605c52ef 100644 --- a/src/include/maat/sleigh_interface.hpp +++ b/src/include/maat/sleigh_interface.hpp @@ -40,6 +40,7 @@ namespace maat inline maat::ir::Param sleigh_reg_translate_X86(const std::string& reg_name); inline maat::ir::Param sleigh_reg_translate_X64(const std::string& reg_name); inline maat::ir::Param sleigh_reg_translate_EVM(const std::string& reg_name); + inline maat::ir::Param sleigh_reg_translate_ARM32(const std::string& reg_name); } diff --git a/src/loader/loader_lief.cpp b/src/loader/loader_lief.cpp index 012eac5b..9f692c03 100644 --- a/src/loader/loader_lief.cpp +++ b/src/loader/loader_lief.cpp @@ -85,7 +85,7 @@ void LoaderLIEF::parse_binary(const std::string& binary, Format type) } void LoaderLIEF::get_arch_special_registers( - const Arch& arch, reg_t& pc, reg_t& sp, reg_t& bp, reg_t& gs, reg_t& fs + const Arch& arch, std::optional& pc, std::optional& sp, std::optional& bp, std::optional& gs, std::optional& fs ) { pc = arch.pc(); @@ -102,6 +102,8 @@ void LoaderLIEF::get_arch_special_registers( gs = X64::GS; fs = X64::FS; break; + case Arch::Type::ARM32: + break; default: throw loader_exception( Fmt() << "LoaderLIEF::get_arch_special_registers(): Unsupported architecture!" diff --git a/src/loader/loader_lief_elf.cpp b/src/loader/loader_lief_elf.cpp index 97d94e3e..c02286be 100644 --- a/src/loader/loader_lief_elf.cpp +++ b/src/loader/loader_lief_elf.cpp @@ -212,11 +212,11 @@ void LoaderLIEF::load_elf_using_interpreter( const std::string& interp_path ) { - reg_t reg_sp = -1; - reg_t reg_bp = -1; - reg_t reg_gs = -1; - reg_t reg_fs = -1; - reg_t reg_pc = -1; + std::optional reg_sp = std::nullopt; + std::optional reg_bp = std::nullopt; + std::optional reg_gs = std::nullopt; + std::optional reg_fs = std::nullopt; + std::optional reg_pc = std::nullopt; addr_t stack_base, stack_size, stack_top; // Get particular registers @@ -242,8 +242,10 @@ void LoaderLIEF::load_elf_using_interpreter( stack_size = 0x00200000; stack_top = engine->arch->bits() == 32 ? 0x0c000000 : 0x80000000000; stack_base = alloc_segment(engine, stack_top-stack_size, stack_size, maat::mem_flag_rw, "Stack"); - engine->cpu.ctx().set(reg_sp, stack_base+stack_size-0x400); // - 0x400 to leave some space in memory - engine->cpu.ctx().set(reg_bp, stack_base+stack_size-0x400); + engine->cpu.ctx().set(reg_sp.value(), stack_base+stack_size-0x400); // - 0x400 to leave some space in memory + if (reg_bp) { + engine->cpu.ctx().set(*reg_bp, stack_base+stack_size-0x400); + } // Load interpreter load_elf_interpreter(engine, interp_path, *this); @@ -255,7 +257,7 @@ void LoaderLIEF::load_elf_using_interpreter( add_elf_dependencies_to_emulated_fs(engine, libdirs, ignore_libs, virtual_fs); // Point PC to interpreter entrypoint - engine->cpu.ctx().set(reg_pc, interpreter_entry.value()); + engine->cpu.ctx().set(reg_pc.value(), interpreter_entry.value()); } void LoaderLIEF::load_elf_binary( @@ -272,11 +274,11 @@ void LoaderLIEF::load_elf_binary( addr_t stack_base, stack_top, stack_size, heap_base, heap_size; addr_t gs, fs; std::list loaded_libs; - reg_t reg_sp = -1; - reg_t reg_bp = -1; - reg_t reg_gs = -1; - reg_t reg_fs = -1; - reg_t reg_pc = -1; + std::optional reg_sp = std::nullopt; + std::optional reg_bp = std::nullopt; + std::optional reg_gs = std::nullopt; + std::optional reg_fs = std::nullopt; + std::optional reg_pc = std::nullopt; int arch_bytes = engine->arch->octets(); // Get particular registers @@ -292,8 +294,10 @@ void LoaderLIEF::load_elf_binary( stack_size = 0x00200000; stack_top = engine->arch->bits() == 32 ? 0x0c000000 : 0x80000000000; stack_base = alloc_segment(engine, stack_top-stack_size, stack_size, maat::mem_flag_rw, "Stack"); - engine->cpu.ctx().set(reg_sp, stack_base+stack_size-0x400); // - 0x400 to leave some space in memory - engine->cpu.ctx().set(reg_bp, stack_base+stack_size-0x400); + engine->cpu.ctx().set(reg_sp.value(), stack_base+stack_size-0x400); // - 0x400 to leave some space in memory + if (reg_bp) { + engine->cpu.ctx().set(*reg_bp, stack_base+stack_size-0x400); + } // Setup heap heap_base = end_of_segment(*engine->mem, binary_name); @@ -306,12 +310,12 @@ void LoaderLIEF::load_elf_binary( ); // Allocate some segments for GS and FS segment selectors (stack canary stuff) - if (reg_gs != -1) + if (reg_gs && reg_fs) { gs = alloc_segment(engine, 0x00aa0000, 0x1000, maat::mem_flag_rw, "Fake GS: segment"); fs = alloc_segment(engine, 0x00aa0000, 0x1000, maat::mem_flag_rw, "Fake FS: segment"); - engine->cpu.ctx().set(reg_gs, gs); - engine->cpu.ctx().set(reg_fs, fs); + engine->cpu.ctx().set(*reg_gs, gs); + engine->cpu.ctx().set(*reg_fs, fs); } // Preload emulated libraries. We do it before loading dependencies @@ -333,7 +337,7 @@ void LoaderLIEF::load_elf_binary( elf_setup_stack(engine, base, args, envp); // Point PC to program entrypoint - engine->cpu.ctx().set(reg_pc, _elf->entrypoint() + base); + engine->cpu.ctx().set(reg_pc.value(), _elf->entrypoint() + base); } void LoaderLIEF::force_relocation(MaatEngine* engine, addr_t base, const std::string& rel_name, addr_t value) @@ -728,6 +732,8 @@ std::vector> LoaderLIEF::generate_aux_vector( platform = "x86_64"; else if (engine->arch->type == Arch::Type::ARM64) platform = "arm64"; + else if (engine->arch->type == Arch::Type::ARM32) + platform = "arm32"; else throw loader_exception("LIEFLoader::_generate_aux_vector(): got unsupported architecture"); diff --git a/src/third-party/sleigh/native/reg_translator.cpp b/src/third-party/sleigh/native/reg_translator.cpp index bc39c700..360d7b6f 100644 --- a/src/third-party/sleigh/native/reg_translator.cpp +++ b/src/third-party/sleigh/native/reg_translator.cpp @@ -1320,4 +1320,54 @@ maat::ir::Param sleigh_reg_translate_EVM(const std::string& reg_name) ); } +maat::ir::Param sleigh_reg_translate_ARM32(const std::string& reg_name) { + if (reg_name == "r0") return maat::ir::Reg(maat::ARM32::R0, 32); + if (reg_name == "r1") return maat::ir::Reg(maat::ARM32::R1, 32); + if (reg_name == "r2") return maat::ir::Reg(maat::ARM32::R2, 32); + if (reg_name == "r3") return maat::ir::Reg(maat::ARM32::R3, 32); + if (reg_name == "r4") return maat::ir::Reg(maat::ARM32::R4, 32); + if (reg_name == "r5") return maat::ir::Reg(maat::ARM32::R5, 32); + if (reg_name == "r6") return maat::ir::Reg(maat::ARM32::R6, 32); + if (reg_name == "r7") return maat::ir::Reg(maat::ARM32::R7, 32); + if (reg_name == "r8") return maat::ir::Reg(maat::ARM32::R8, 32); + if (reg_name == "r9") return maat::ir::Reg(maat::ARM32::R9, 32); + if (reg_name == "r10") return maat::ir::Reg(maat::ARM32::R10, 32); + if (reg_name == "r11") return maat::ir::Reg(maat::ARM32::R11, 32); + if (reg_name == "r12") return maat::ir::Reg(maat::ARM32::R12, 32); + + if (reg_name == "sp") return maat::ir::Reg(maat::ARM32::SP, 32); + if (reg_name == "lr") return maat::ir::Reg(maat::ARM32::LR, 32); + if (reg_name == "pc") return maat::ir::Reg(maat::ARM32::PC, 32); + + if (reg_name == "cpsr") return maat::ir::Reg(maat::ARM32::CPSR, 32); + + if (reg_name == "mult_addr") return maat::ir::Reg(maat::ARM32::mult_addr, 32); + if (reg_name == "mult_dat8") return maat::ir::Reg(maat::ARM32::mult_addr, 64); + if (reg_name == "mult_dat16") return maat::ir::Reg(maat::ARM32::mult_addr, 128); + + if (reg_name == "NG") return maat::ir::Reg(maat::ARM32::NF, 8); + if (reg_name == "ZR") return maat::ir::Reg(maat::ARM32::ZF, 8); + if (reg_name == "CY") return maat::ir::Reg(maat::ARM32::CF, 8); + if (reg_name == "OV") return maat::ir::Reg(maat::ARM32::VF, 8); + if (reg_name == "Q") return maat::ir::Reg(maat::ARM32::QF, 8); + // if (reg_name == "JF") return maat::ir::Reg(maat::ARM32::JF, 8); + if (reg_name == "GE1") return maat::ir::Reg(maat::ARM32::GE1, 8); + if (reg_name == "GE2") return maat::ir::Reg(maat::ARM32::GE2, 8); + if (reg_name == "GE3") return maat::ir::Reg(maat::ARM32::GE3, 8); + if (reg_name == "GE4") return maat::ir::Reg(maat::ARM32::GE4, 8); + if (reg_name == "TB") return maat::ir::Reg(maat::ARM32::TF, 8); + if (reg_name == "tmpNG") return maat::ir::Reg(maat::ARM32::tmpNG, 8); + if (reg_name == "tmpZR") return maat::ir::Reg(maat::ARM32::tmpZR, 8); + if (reg_name == "tmpCY") return maat::ir::Reg(maat::ARM32::tmpCY, 8); + if (reg_name == "tmpOV") return maat::ir::Reg(maat::ARM32::tmpOV, 8); + if (reg_name == "shift_carry") return maat::ir::Reg(maat::ARM32::SC, 8); + if (reg_name == "ISAModeSwitch") return maat::ir::Reg(maat::ARM32::ISAModeSwitch, 8); + + throw maat::runtime_exception(maat::Fmt() + << "ARM32: Register translation from SLEIGH to MAAT missing for register " + << reg_name + >> maat::Fmt::to_str + ); +} + } // namespace maat \ No newline at end of file diff --git a/src/third-party/sleigh/native/sleigh_interface.cpp b/src/third-party/sleigh/native/sleigh_interface.cpp index e31b5702..44a0fa79 100644 --- a/src/third-party/sleigh/native/sleigh_interface.cpp +++ b/src/third-party/sleigh/native/sleigh_interface.cpp @@ -399,6 +399,13 @@ class TranslationContext // TODO - is this useful ? will this hinder performance ? // Needs to be here apparently but maybe we could tweak setData so we don't need to reset... m_sleigh->reset(&m_loader, &m_context_internal); + // If arch is arm32 bit then don't allow contextSet() (fixes low level error in ghidra) + if (arch == Arch::Type::ARM32) + { + // disable context setting for ARMv7 32-bit architecture + m_sleigh->allowContextSet(false); + } + m_sleigh->initialize(m_document_storage); // setData doesn't affect performance for a big num_bytes :) m_loader.setData(address, bytes, num_bytes); @@ -630,6 +637,8 @@ maat::ir::Param reg_name_to_maat_reg(maat::Arch::Type arch, const std::string& r return sleigh_reg_translate_X64(reg_name); else if (arch == Arch::Type::EVM) return sleigh_reg_translate_EVM(reg_name); + else if (arch == Arch::Type::ARM32) + return sleigh_reg_translate_ARM32(reg_name); else throw maat::runtime_exception("Register translation from SLEIGH to MAAT not implemented for this architecture!"); } diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.cspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM.cspec new file mode 100644 index 00000000..4137ca1d --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.cspec @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ; + offset = *:1 (lr + r3); + r3 = zext(offset); + + + if (inbounds) goto ; + offset = *:1 (lr + r12); + r3 = zext(offset); + + + r3 = r3 * 2; + + r12 = lr + r3; + + ISAModeSwitch = (r12 & 1) != 1; + TB = ISAModeSwitch; + pc = r12 & 0xfffffffe; + goto [pc]; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.dwarf b/src/third-party/sleigh/processors/ARM/data/languages/ARM.dwarf new file mode 100644 index 00000000..0444463e --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.dwarf @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.gdis b/src/third-party/sleigh/processors/ARM/data/languages/ARM.gdis new file mode 100644 index 00000000..33429f85 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.gdis @@ -0,0 +1,41 @@ + + + + TMode + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.ldefs b/src/third-party/sleigh/processors/ARM/data/languages/ARM.ldefs new file mode 100644 index 00000000..ee1a245b --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.ldefs @@ -0,0 +1,377 @@ + + + + + Generic ARM/Thumb v8 little endian + + + + + + + + + + + + + + + + Generic ARM/Thumb v8 little endian (Thumb is default) + + + + + + + + + + + Generic ARM/Thumb v8 little endian instructions and big endian data + + + + + + + Generic ARM/Thumb v8 big endian + + + + + + + + + + + + + + + Generic ARM/Thumb v8 big endian (Thumb is default) + + + + + + + + + Generic ARM/Thumb v7 little endian + + + + + + + + + + + Generic ARM/Thumb v7 little endian instructions and big endian data + + + + + + + Generic ARM/Thumb v7 big endian + + + + + + + + + + ARM Cortex / Thumb little endian + + + + + + + + + + + + ARM Cortex / Thumb big endian + + + + + + + + + + + Generic ARM/Thumb v6 little endian + + + + + + + + + + + + Generic ARM/Thumb v6 big endian + + + + + + + + + + + + Generic ARM/Thumb v5 little endian (T-variant) + + + + + + + + + + Generic ARM/Thumb v5 big endian (T-variant) + + + + + + + + + + Generic ARM v5 little endian + + + + + + + + Generic ARM v5 big endian + + + + + + + + Generic ARM/Thumb v4 little endian (T-variant) + + + + + + + + + Generic ARM/Thumb v4 big endian (T-variant) + + + + + + + + + Generic ARM v4 little endian + + + + + + + + + + + + Generic ARM v4 big endian + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.opinion b/src/third-party/sleigh/processors/ARM/data/languages/ARM.opinion new file mode 100644 index 00000000..64634f11 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.opinion @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM.sinc b/src/third-party/sleigh/processors/ARM/data/languages/ARM.sinc new file mode 100644 index 00000000..5869bfe2 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM.sinc @@ -0,0 +1,303 @@ +# Specification for the ARM Version 4, 4T, 5, 5T, 5E +# The following boolean defines control specific support: T_VARIANT, VERSION_5, VERSION_5E + +define endian=$(ENDIAN); +define alignment=2; + +define space ram type=ram_space size=4 default; +define space register type=register_space size=4; + +define register offset=0x0020 size=4 [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ]; +define register offset=0x0060 size=1 [ NG ZR CY OV tmpNG tmpZR tmpCY tmpOV shift_carry TB Q GE1 GE2 GE3 GE4 ]; +define register offset=0x0070 size=4 [ cpsr spsr ]; +define register offset=0x0080 size=4 [ mult_addr ]; # Special internal register for dealing with multiple stores/loads +define register offset=0x0084 size=4 [ r14_svc r13_svc spsr_svc ]; +define register offset=0x0090 size=8 [ mult_dat8 ]; # Special internal register for dealing with multiple stores/loads +define register offset=0x0090 size=16 [ mult_dat16 ]; # Special internal register for dealing with multiple stores/loads +define register offset=0x00A0 size=4 [ fpsr ]; # floating point state register (for FPA10 floating-point accelerator) +define register offset=0x00B0 size=1 [ ISAModeSwitch ]; # generic name for TB ThumbBit - set same as TB + +@define FPSCR_N "fpscr[31,1]" +@define FPSCR_Z "fpscr[30,1]" +@define FPSCR_C "fpscr[29,1]" +@define FPSCR_V "fpscr[28,1]" + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + define register offset=0x00B0 size=4 [ fpsid fpscr fpexc mvfr0 mvfr1 ]; +@endif +define register offset=0x0100 size=10 [ fp0 fp1 fp2 fp3 fp4 fp5 fp6 fp7 ]; # eight 80-bit floating registers + +# pseudo-registers for coprocessor calculations +define register offset=0x0200 size=4 [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ]; + +# Advanced SIMD and VFP extension registers +@if defined(VFPv2) || defined(VFPv3) + +@if ENDIAN == "little" + define register offset=0x0300 size=4 [ s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 + s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 ]; +@else # ENDIAN == "big" + define register offset=0x0300 size=4 [ s31 s30 s29 s28 s27 s26 s25 s24 s23 s22 s21 s20 s19 s18 s17 s16 + s15 s14 s13 s12 s11 s10 s9 s8 s7 s6 s5 s4 s3 s2 s1 s0 ]; +@endif # ENDIAN = "big" + +@endif # VFPv2 || VFPv3 + +@if defined(VFPv2) + +@if ENDIAN == "little" + define register offset=0x0300 size=8 [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ]; +@else # ENDIAN == "big" + define register offset=0x0300 size=8 [ d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ]; +@endif # ENDIAN = "big" + +@endif # VFPv2 + +@if defined(SIMD) || defined(VFPv3) + +@if ENDIAN == "little" + define register offset=0x0300 size=8 [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 + d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 ]; +@else # ENDIAN == "big" + define register offset=0x0300 size=8 [ d31 d30 d29 d28 d27 d26 d25 d24 d23 d22 d21 d20 d19 d18 d17 d16 + d15 d14 d13 d12 d11 d10 d9 d8 d7 d6 d5 d4 d3 d2 d1 d0 ]; +@endif # ENDIAN = "big" + +@endif # SIMD || VFPv3 + +@if defined(SIMD) + +@if ENDIAN == "little" + define register offset=0x0300 size=16 [ q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 ]; +@else # ENDIAN == "big" + define register offset=0x0300 size=16 [ q15 q14 q13 q12 q11 q10 q9 q8 q7 q6 q5 q4 q3 q2 q1 q0 ]; +@endif # ENDIAN = "big" + +@endif # SIMD + +# Define context bits +# WARNING: when adjusting context keep compiler packing in mind +# and make sure fields do not span a 32-bit boundary before or +# after context packing +define register offset=0x00 size=8 contextreg; +define context contextreg +@ifdef T_VARIANT + TMode = (0,0) # 1 if in Thumb instruction decode mode + T = (0,0) # exact copy (alias!) of TMode + LowBitCodeMode = (0,0) # 1 if low bit of instruction address is set on a branch + ISA_MODE = (0,0) # 1 for Thumb instruction decode mode +@endif + LRset = (1,1) noflow # 1 if the instruction right before was a mov lr,pc + REToverride = (2,2) noflow # 1 if the instruction should be a branch not a return + CALLoverride = (3,3) noflow # 1 if the call should actually be a jump +@if defined(VERSION_6T2) || defined(VERSION_7) + TEEMode = (4,4) # 1 if in ThumbEE mode, changes some instruction behavior, and makes some instructions invalid + condit = (5,13) noflow # both base and shift + cond_mask = (10,13) # base condition + cond_full = (6,9) # full condition + cond_true = (9,9) # true if this condition should be tested for true + cond_base = (6,8) # shift mask for controlling shift + cond_shft = (9,13) # mask and lower bit of it condition field + itmode = (5,5) # true if in ITBlock mode + +@endif + + # Transient context bits + counter = (14,18) # 0 to 7 counter (for building variable length register lists) +# dreg = (17,21) # D register (attached, for building register lists) +# sreg = (17,21) # S register (attached, for building register lists) + regNum = (19,23) # D register number (see dreg) + counter2 = (24,26) # 0 to 7 counter (for building variable length register lists) +# dreg2 = (25,29) # 2nd D register (attached, for building register lists) +# sreg2 = (25,29) # 2nd S register (attached, for building register lists) + reg2Num = (27,31) # 2nd D register number (see dreg2) +# --- do not allow any field to span 32-bit boundary --- + regInc = (32,33) # Pair register increment + ARMcond = (34,34) # ARM conditional instruction + ARMcondCk = (35,35) # Finished ARM condition check phase +; + +define pcodeop count_leading_zeroes; +define pcodeop coprocessor_function; +define pcodeop coprocessor_function2; +define pcodeop coprocessor_load; +define pcodeop coprocessor_load2; +define pcodeop coprocessor_loadlong; +define pcodeop coprocessor_loadlong2; +define pcodeop coprocessor_moveto; +define pcodeop coprocessor_moveto2; +define pcodeop coprocessor_movefromRt; +define pcodeop coprocessor_movefromRt2; +define pcodeop coprocessor_movefrom2; +define pcodeop coprocessor_store; +define pcodeop coprocessor_store2; +define pcodeop coprocessor_storelong; +define pcodeop coprocessor_storelong2; +define pcodeop software_interrupt; +define pcodeop software_bkpt; +define pcodeop software_udf; +define pcodeop software_hlt; +define pcodeop software_hvc; +define pcodeop software_smc; + +# CPS methods (Version 6) +define pcodeop setUserMode; +define pcodeop setFIQMode; +define pcodeop setIRQMode; +define pcodeop setSupervisorMode; +define pcodeop setMonitorMode; +define pcodeop setAbortMode; +define pcodeop setUndefinedMode; +define pcodeop setSystemMode; +define pcodeop enableIRQinterrupts; +define pcodeop enableFIQinterrupts; +define pcodeop enableDataAbortInterrupts; +define pcodeop disableIRQinterrupts; +define pcodeop disableFIQinterrupts; +define pcodeop isFIQinterruptsEnabled; +define pcodeop isIRQinterruptsEnabled; +define pcodeop disableDataAbortInterrupts; +define pcodeop hasExclusiveAccess; +define pcodeop isCurrentModePrivileged; +define pcodeop setThreadModePrivileged; +define pcodeop isThreadMode; + +define pcodeop jazelle_branch; +define pcodeop ClearExclusiveLocal; +define pcodeop HintDebug; + +define pcodeop DataMemoryBarrier; +define pcodeop DataSynchronizationBarrier; + +define pcodeop secureMonitorCall; + +define pcodeop WaitForEvent; +define pcodeop WaitForInterrupt; + +define pcodeop HintYield; +define pcodeop InstructionSynchronizationBarrier; + +define pcodeop HintPreloadData; +define pcodeop HintPreloadDataForWrite; +define pcodeop HintPreloadInstruction; + +define pcodeop SignedSaturate; +define pcodeop SignedDoesSaturate; +define pcodeop UnsignedSaturate; +define pcodeop UnsignedDoesSaturate; +define pcodeop Absolute; +define pcodeop ReverseBitOrder; +define pcodeop SendEvent; +define pcodeop setEndianState; + +macro affectflags() { + CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; +} + +macro affect_resflags() { + ZR = tmpZR; NG = tmpNG; +} + +macro SetThumbMode(value) { + ISAModeSwitch = value; + TB = ISAModeSwitch; +} + +# +# simple branch, not inter-working +macro BranchWritePC(addr) { + pc = addr; +} + +# +# Interworking branch, ARM<->Thumb +macro BXWritePC(addr) { + SetThumbMode((addr & 0x1) != 0); + local tmp = addr & 0xfffffffe; + pc = tmp; +} + +# +# Branch depends on version +macro LoadWritePC(addr) { +@if defined(VERSION_5) + BXWritePC(addr); +@else + BranchWritePC(addr); +@endif +} + +# Branch depends on version +macro ALUWritePC(addr) { +@if defined(VERSION_7) + BXWritePC(addr); +@else + BranchWritePC(addr); +@endif +} + +@if defined(T_VARIANT) + +ItCond: is TMode=1 { } +CheckInIT_CZNO: is TMode=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; } # in older, arms always affect flags +CheckInIT_CZN: is TMode=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; } # in older, arms always affect flags +CheckInIT_ZN: is TMode=1 { ZR = tmpZR; NG = tmpNG; } # in older, arms always affect flags + +@endif + +@if defined(VERSION_6T2) || defined(VERSION_7) + +# conditionals for instruction following IT Block +thfcc: "eq" is cond_full=0 { local tmp:1 = (ZR!=0); export tmp; } +thfcc: "ne" is cond_full=1 { local tmp:1 = (ZR==0); export tmp; } +thfcc: "cs" is cond_full=2 { local tmp:1 = (CY!=0); export tmp; } +thfcc: "cc" is cond_full=3 { local tmp:1 = (CY==0); export tmp; } +thfcc: "mi" is cond_full=4 { local tmp:1 = (NG!=0); export tmp; } +thfcc: "pl" is cond_full=5 { local tmp:1 = (NG==0); export tmp; } +thfcc: "vs" is cond_full=6 { local tmp:1 = (OV!=0); export tmp; } +thfcc: "vc" is cond_full=7 { local tmp:1 = (OV==0); export tmp; } +thfcc: "hi" is cond_full=8 { local tmp:1 = CY && !ZR; export tmp; } +thfcc: "ls" is cond_full=9 { local tmp:1 = !CY || ZR; export tmp; } +thfcc: "ge" is cond_full=10 { local tmp:1 = (NG == OV); export tmp; } +thfcc: "lt" is cond_full=11 { local tmp:1 = (NG != OV); export tmp; } +thfcc: "gt" is cond_full=12 { local tmp:1 = !ZR && (NG == OV); export tmp; } +thfcc: "le" is cond_full=13 { local tmp:1 = ZR || (NG != OV); export tmp; } +thfcc: "al" is cond_full=14 { local tmp:1 = 1; export tmp; } #can happen +#thfcc: "nv" is cond_full=15 { local tmp:1 = 0; export tmp; } #unpredictable, shouldn't happen + + +# no ITcondition +ItCond: is TMode=1 & itmode=0 & cond_mask=0 {} +# ITBlock then/else case - the condition being tested is modified by the shift below +ItCond: "."thfcc is TMode=1 & itmode=0 & cond_mask & thfcc [ itmode=1; globalset(inst_next,condit);] + { if (!thfcc) goto inst_next; } + +# last ITBlock then/else case - the condition being tested is modified by the shift below +ItCond: "."thfcc is TMode=1 & itmode=0 & cond_mask=8 & thfcc + { if (!thfcc) goto inst_next; } + +# certain Thumb instructions don't affect all flags in the IT block +CheckInIT_CZNO: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits +CheckInIT_CZNO: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits +CheckInIT_CZNO: "s" is TMode=1 & itmode=0 & cond_mask=0 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; } + +CheckInIT_CZN: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits +CheckInIT_CZN: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits +CheckInIT_CZN: "s" is TMode=1 & itmode=0 & cond_mask=0 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; } + +CheckInIT_ZN: is TMode=1 & itmode=1 & cond_mask { } # Do nothing to the flag bits +CheckInIT_ZN: is TMode=1 & itmode=0 & cond_mask { } # Do nothing to the flag bits +CheckInIT_ZN: "s" is TMode=1 & itmode=0 & cond_mask=0 { ZR = tmpZR; NG = tmpNG; } + + +:^instruction is itmode=1 & cond_mask=8 & instruction [ condit=0; ] {} +:^instruction is itmode=1 & cond_mask & instruction [ cond_shft=cond_shft << 1; itmode=0; ]{} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +@include "ARMinstructions.sinc" + +# THUMB instructions +@ifdef T_VARIANT +@include "ARMTHUMBinstructions.sinc" +@endif diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM4_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM4_be.slaspec new file mode 100644 index 00000000..ef190b18 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM4_be.slaspec @@ -0,0 +1,5 @@ + +@define ENDIAN "big" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM4_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM4_le.slaspec new file mode 100644 index 00000000..ee66cfc6 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM4_le.slaspec @@ -0,0 +1,5 @@ + +@define ENDIAN "little" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_be.slaspec new file mode 100644 index 00000000..1e56f79d --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_be.slaspec @@ -0,0 +1,6 @@ + +@define ENDIAN "big" +@define T_VARIANT "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_le.slaspec new file mode 100644 index 00000000..712b6367 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM4t_le.slaspec @@ -0,0 +1,6 @@ + +@define ENDIAN "little" +@define T_VARIANT "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM5_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM5_be.slaspec new file mode 100644 index 00000000..c490b017 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM5_be.slaspec @@ -0,0 +1,7 @@ + +@define ENDIAN "big" +@define VERSION_5 "" +@define VERSION_5E "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM5_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM5_le.slaspec new file mode 100644 index 00000000..48f9cf7a --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM5_le.slaspec @@ -0,0 +1,7 @@ + +@define ENDIAN "little" +@define VERSION_5 "" +@define VERSION_5E "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_be.slaspec new file mode 100644 index 00000000..dbd9cc1c --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_be.slaspec @@ -0,0 +1,9 @@ + +@define ENDIAN "big" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" + +@include "ARM.sinc" + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_le.slaspec new file mode 100644 index 00000000..ae5bc1d0 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM5t_le.slaspec @@ -0,0 +1,8 @@ + +@define ENDIAN "little" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM6_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM6_be.slaspec new file mode 100644 index 00000000..02983a4c --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM6_be.slaspec @@ -0,0 +1,12 @@ + +@define ENDIAN "big" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VFPv2 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM6_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM6_le.slaspec new file mode 100644 index 00000000..f45a5101 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM6_le.slaspec @@ -0,0 +1,12 @@ + +@define ENDIAN "little" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VFPv2 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM7_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM7_be.slaspec new file mode 100644 index 00000000..896066e7 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM7_be.slaspec @@ -0,0 +1,15 @@ + +@define ENDIAN "big" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VERSION_7 "" +@define VERSION_7M "" +@define SIMD "" +@define VFPv3 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM7_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM7_le.slaspec new file mode 100644 index 00000000..e2df6c39 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM7_le.slaspec @@ -0,0 +1,15 @@ + +@define ENDIAN "little" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VERSION_7 "" +@define VERSION_7M "" +@define SIMD "" +@define VFPv3 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM8_be.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM8_be.slaspec new file mode 100644 index 00000000..71536634 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM8_be.slaspec @@ -0,0 +1,16 @@ + +@define ENDIAN "big" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VERSION_7 "" +@define VERSION_7M "" +@define VERSION_8 "" +@define SIMD "" +@define VFPv3 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM8_le.slaspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM8_le.slaspec new file mode 100644 index 00000000..6eda33d9 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM8_le.slaspec @@ -0,0 +1,16 @@ + +@define ENDIAN "little" +@define T_VARIANT "" +@define VERSION_5 "" +@define VERSION_5E "" +@define VERSION_6 "" +@define VERSION_6K "" +@define VERSION_6T2 "" +@define VERSION_7 "" +@define VERSION_7M "" +@define VERSION_8 "" +@define SIMD "" +@define VFPv3 "" + +@include "ARM.sinc" + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMCortex.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARMCortex.pspec new file mode 100644 index 00000000..64222b6c --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMCortex.pspec @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMTHUMBinstructions.sinc b/src/third-party/sleigh/processors/ARM/data/languages/ARMTHUMBinstructions.sinc new file mode 100644 index 00000000..daf70573 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMTHUMBinstructions.sinc @@ -0,0 +1,5294 @@ +# Specification for the THUMB Version 2 +# This closely follows +# "Architecture Reference Manual" Second Edition Edited by David Seal + +# +# WARNING NOTE: Be very careful taking a subpiece or truncating a register with :# or (#) +# The LEBE hybrid language causes endian issues if you do not assign the register to a temp +# variable and then take a subpiece or truncate. +# + +define token instr2 (16) + part2op=(11,15) # this second instruction token is needed for the + part2J1=(13,13) + part2J2=(11,11) + part2cond=(6,9) + part2imm6=(0,5) + part2S=(10,10) + part2imm11=(0,10) + part2imm10=(0,9) + part2off=(0,10) # bl and blx instructions which use 2 16-bit instructions + part2off_10=(1,10) # blx instruction which switches to ARM mode + part2c1415=(14,15) + part2c1212=(12,12) + part2c0615=(6,15) + part2Rt=(12,15) + part2c0011=(0,11) + part2c0909=(9,9) + part2c0808=(8,8) + part2c0707=(7,7) + part2c0505=(5,5) + part2c0404=(4,4) + part2Rd0003=(0,3) +; + +define token instrThumb (16) + op4=(4,15) + op6=(6,15) + op7=(7,15) + op8=(8,15) + op9=(9,15) + op11=(11,15) + op12=(12,15) + op0=(0,15) + sop0407=(4,7) + sop0507=(5,7) + sop0508=(5,8) + sop0003=(0,3) + sop0608=(6,8) + sop0610=(6,10) + + sopit=(0,7) + + Ra1215=(12,15) + Rd0002=(0,2) + Rd0003=(0,3) + Rd0810=(8,10) + Rd0811=(8,11) + Rn0002=(0,2) + Rn0003=(0,3) + Rn0305=(3,5) + Rn0810=(8,10) + Rm0305=(3,5) + Rm0306=(3,6) + Rm0608=(6,8) + Rm0003=(0,3) + Rs0305=(3,5) + Rt1215=(12,15) + Rt0811=(8,11) + + thI9=(9,9) + thP8=(8,8) + thH8=(8,8) + thL8=(8,8) + thU7=(7,7) + thB6=(6,6) + thN6=(6,6) + thS6=(6,6) + thW5=(5,5) + thL4=(4,4) + + thCRd=(12,15) + thCRn=(0,3) + thCRm=(0,3) + + hrn0002=(0,2) + hrm0305=(3,5) + rm0306=(3,6) + hrd0002=(0,2) + + immed3=(6,8) + immed5=(6,10) + immed6=(0,5) + immed7=(0,6) + immed8=(0,7) + + immed12_i=(10,10) + immed12_imm3=(12,14) + immed12_imm8=(0,7) + + soffset8=(0,7) signed + offset10=(0,9) + offset10S=(10,10) + offset11=(0,10) + soffset11=(0,10) signed + offset12=(0,11) + + thcond=(8,11) + thcpn=(8,11) + thopcode1=(4,7) + thopcode2=(5,7) + l07=(7,7) + l11=(11,11) + h1=(7,7) + h2=(6,6) + R=(8,8) + sbz=(0,2) + thwbit=(5,5) + + th_psrmask=(8,11) + + addr_pbit=(10,10) + addr_ubit=(9,9) + addr_wbit=(8,8) + addr_puw =(8,10) + addr_puw1 =(5,8) + + thsrsMode=(0,4) + + fcond=(4,7) + + throt=(4,6) + + imm3_12=(12,14) + + imm3_shft=(12,14) + imm2_shft=(6,7) + + imm5=(3,7) + + sysm=(0,7) + sysm37=(3,7) + sysm02=(0,2) + + + thc0001=(0,1) + thc0002=(0,2) + thc0003=(0,3) + thc0004=(0,4) + thc0005=(0,5) + thc0006=(0,6) + thc0007=(0,7) + thc0011=(0,11) + thc0107=(1,7) + thc0207=(2,7) + thc0307=(3,7) + thc0407=(4,7) + thc0405=(4,5) + thc0409=(4,9) + thc0506=(5,6) + thc0507=(5,7) + thc0607=(6,7) + thc0810=(8,10) + thc0811=(8,11) + thc0910=(9,10) + thc1414=(14,14) + thc1313=(13,13) + thc1212=(12,12) + thc1214=(12,14) + thc1111=(11,11) + thc1010=(10,10) + thc0909=(9,9) + thc0808=(8,8) + thc0707=(7,7) + thc0606=(6,6) + thc0505=(5,5) + thc0404=(4,4) + thc0303=(3,3) + thc0202=(2,2) + thc0101=(1,1) + thc0000=(0,0) + thc0115=(1,15) + thc0215=(2,15) + thc0315=(3,15) + thc0415=(4,15) + thc0515=(5,15) + thc0615=(6,15) + thc0715=(7,15) + thc0815=(8,15) + thc0915=(9,15) + thc1015=(10,15) + thc1112=(11,12) + thc1115=(11,15) + thc1215=(12,15) + thc1315=(13,15) + thc1415=(14,15) + thc1515=(15,15) +; + +attach variables [ Rd0002 Rd0810 Rn0002 Rn0305 Rn0810 Rm0305 Rm0608 Rs0305 ] + [ r0 r1 r2 r3 r4 r5 r6 r7 ]; + +attach variables [ Rm0003 Rm0306 Rd0811 Rn0003 Rt1215 Rt0811 Ra1215 Rd0003 part2Rt part2Rd0003 ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ]; + +attach variables [ thCRn thCRd thCRm ] [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ]; + +attach names [ thcpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 ]; + +attach variables [ hrn0002 hrm0305 hrd0002 ] + [ r8 r9 r10 r11 r12 sp lr pc ]; + +macro th_addflags(op1,op2) { + tmpCY = carry(op1,op2); + tmpOV = scarry(op1,op2); +} + +#See ARM Architecture reference section "Pseudocode details of addition and subtraction" +macro th_add_with_carry_flags(op1,op2){ + local CYz = zext(CY); + local result = op1 + op2; + tmpCY = carry( op1, op2 ) || carry( result, CYz ); + tmpOV = scarry( op1, op2) ^^ scarry( result, CYz ); +} + +#Note: used for subtraction op1 - (op2 + !CY) +#sets tmpCY if there is NO borrow +macro th_sub_with_carry_flags(op1, op2){ + local result = op1 - op2; + tmpCY = (op1 > op2) || (result < zext(CY)); + tmpOV = sborrow(op1,op2) ^^ sborrow(result,zext(!CY)); +} + + +macro th_test_flags(result){ + ZR = (result == 0); + NG = (result s< 0); + CY = shift_carry; +} + +# Note (unlike x86) carry flag is SET if there is NO borrow +macro th_subflags(op1,op2) { + tmpCY = op2 <= op1; + tmpOV = sborrow(op1,op2); +} +macro th_subflags0(op2) { + tmpCY = op2 == 0; + tmpOV = sborrow(0,op2); +} + + + +macro resflags(result) { + tmpNG = result s< 0; + tmpZR = result == 0; +} + +macro th_logicflags() { + tmpCY = shift_carry; + tmpOV = OV; +} + +macro th_affectflags() { + CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; +} + +############################################################################### + +# conditionals for the branch instruction + +thcc: "eq" is thcond=0 { tmp:1 = (ZR!=0); export tmp; } +thcc: "ne" is thcond=1 { tmp:1 = (ZR==0); export tmp; } +thcc: "cs" is thcond=2 { tmp:1 = (CY!=0); export tmp; } +thcc: "cc" is thcond=3 { tmp:1 = (CY==0); export tmp; } +thcc: "mi" is thcond=4 { tmp:1 = (NG!=0); export tmp; } +thcc: "pl" is thcond=5 { tmp:1 = (NG==0); export tmp; } +thcc: "vs" is thcond=6 { tmp:1 = (OV!=0); export tmp; } +thcc: "vc" is thcond=7 { tmp:1 = (OV==0); export tmp; } +thcc: "hi" is thcond=8 { tmp:1 = CY && !ZR; export tmp; } +thcc: "ls" is thcond=9 { tmp:1 = !CY || ZR; export tmp; } +thcc: "ge" is thcond=10 { tmp:1 = (NG == OV); export tmp; } +thcc: "lt" is thcond=11 { tmp:1 = (NG != OV); export tmp; } +thcc: "gt" is thcond=12 { tmp:1 = !ZR && (NG == OV); export tmp; } +thcc: "le" is thcond=13 { tmp:1 = ZR || (NG != OV); export tmp; } +# thcc: "AL" is thcond=14 { tmp = 1; export tmp; } +# thcc: "NV" is thcond=15 { tmp = 0; export tmp; } + +@define THCC "thcc & (thc1515=0 | thc1414=0 | thc1313=0)" + + +@if defined(VERSION_6T2) || defined(VERSION_7) + +part2thcc: "eq" is part2cond=0 { tmp:1 = (ZR!=0); export tmp; } +part2thcc: "ne" is part2cond=1 { tmp:1 = (ZR==0); export tmp; } +part2thcc: "cs" is part2cond=2 { tmp:1 = (CY!=0); export tmp; } +part2thcc: "cc" is part2cond=3 { tmp:1 = (CY==0); export tmp; } +part2thcc: "mi" is part2cond=4 { tmp:1 = (NG!=0); export tmp; } +part2thcc: "pl" is part2cond=5 { tmp:1 = (NG==0); export tmp; } +part2thcc: "vs" is part2cond=6 { tmp:1 = (OV!=0); export tmp; } +part2thcc: "vc" is part2cond=7 { tmp:1 = (OV==0); export tmp; } +part2thcc: "hi" is part2cond=8 { tmp:1 = CY && !ZR; export tmp; } +part2thcc: "ls" is part2cond=9 { tmp:1 = !CY || ZR; export tmp; } +part2thcc: "ge" is part2cond=10 { tmp:1 = (NG == OV); export tmp; } +part2thcc: "lt" is part2cond=11 { tmp:1 = (NG != OV); export tmp; } +part2thcc: "gt" is part2cond=12 { tmp:1 = !ZR && (NG == OV); export tmp; } +part2thcc: "le" is part2cond=13 { tmp:1 = ZR || (NG != OV); export tmp; } +# part2thcc: "AL" is part2cond=14 { tmp = 1; export tmp; } +# part2thcc: "NV" is part2cond=15 { tmp = 0; export tmp; } + +@define PART2THCC "part2thcc & (part2c0909=0 | part2c0808=0 | part2c0707=0)" + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + + +@if defined(VERSION_6T2) || defined(VERSION_7) + +# conditionals for IT Block +# Marvel at the UGLINESS: the p-code for pairs (eq,ne) (cs,cc) (mi,pl), etc. are the same +# The IT block decoding fills in the complement (if necessary) based on the IT mask bit for the instruction +it_thfcc: "eq" is fcond=0 { tmp:1 = (ZR!=0); export tmp; } +it_thfcc: "ne" is fcond=1 { tmp:1 = (ZR!=0); export tmp; } +it_thfcc: "cs" is fcond=2 { tmp:1 = (CY!=0); export tmp; } +it_thfcc: "cc" is fcond=3 { tmp:1 = (CY!=0); export tmp; } +it_thfcc: "mi" is fcond=4 { tmp:1 = (NG!=0); export tmp; } +it_thfcc: "pl" is fcond=5 { tmp:1 = (NG!=0); export tmp; } +it_thfcc: "vs" is fcond=6 { tmp:1 = (OV!=0); export tmp; } +it_thfcc: "vc" is fcond=7 { tmp:1 = (OV!=0); export tmp; } +it_thfcc: "hi" is fcond=8 { tmp:1 = CY && !ZR; export tmp; } +it_thfcc: "ls" is fcond=9 { tmp:1 = CY && !ZR; export tmp; } +it_thfcc: "ge" is fcond=10 { tmp:1 = (NG == OV); export tmp; } +it_thfcc: "lt" is fcond=11 { tmp:1 = (NG == OV); export tmp; } +it_thfcc: "gt" is fcond=12 { tmp:1 = !ZR && (NG == OV); export tmp; } +it_thfcc: "le" is fcond=13 { tmp:1 = !ZR && (NG == OV); export tmp; } +it_thfcc: "al" is fcond=14 { tmp:1 = 1; export tmp; } + +@define IT_THFCC "it_thfcc & (thc0707=0 | thc0606=0 | thc0505=0 | thc0404=0)" + +ByteRotate: "#"^rot is throt [rot = throt << 3; ] { export *[const]:1 rot; } + +thSBIT_CZNO: is thc0404=0 { } # Do nothing to the flag bits +thSBIT_CZNO: "s" is thc0404=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; } +thSBIT_CZN: is thc0404=0 { } # Do nothing to the flags bits +thSBIT_CZN: "s" is thc0404=1 {CY = tmpCY; ZR = tmpZR; NG = tmpNG;} +thSBIT_ZN: is thc0404=0 { } # Do nothing to the flag bits +thSBIT_ZN: "s" is thc0404=1 { ZR = tmpZR; NG = tmpNG; } + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + + +# Addressing modes +# The capitalized fields are raw register addressing modes + +Hrd0002: Rd0002 is Rd0002 & h1=0 { export Rd0002; } +Hrd0002: hrd0002 is hrd0002 & h1=1 { export hrd0002; } +Hrd0002: pc is pc & hrd0002=7 & h1=1 { tmp:4 = inst_start + 4; export tmp; } + +Hrn0002: Rn0002 is Rn0002 & h1=0 { export Rn0002; } +Hrn0002: hrn0002 is hrn0002 & h1=1 { export hrn0002; } +Hrn0002: pc is pc & hrn0002=7 & h1=1 { tmp:4 = inst_start + 4; export tmp; } + +Hrm0305: Rm0305 is Rm0305 & h2=0 { export Rm0305; } +Hrm0305: hrm0305 is hrm0305 & h2=1 { export hrm0305; } +Hrm0305: pc is pc & hrm0305=7 & h2=1 { tmp:4 = inst_start + 4; export tmp; } + +@if defined(VERSION_6T2) || defined(VERSION_7) +Immed8_4: "#"^immval is immed8 [ immval = immed8 * 4; ] { export *[const]:4 immval; } +Immed4: "#"^thc0003 is thc0003 { export *[const]:4 thc0003; } +@endif + +Immed8: "#"^immed8 is immed8 { export *[const]:4 immed8; } +Immed3: "#"^immed3 is immed3 { export *[const]:4 immed3; } + +Pcrel8: [reloc] is immed8 + [ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ] +{ + # don't export as an address, may be PIC code, and would add spurious symbols. + export *[const]:4 reloc; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +Pcrel8_s8: [reloc] is immed8 + [ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ] +{ + export *:8 reloc; +} +@endif # defined(VERSION_6T2) || defined(VERSION_7) + + +Sprel8: sp,"#"^immval is sp & immed8 [ immval = immed8 * 4; ] { local tmp = sp + immval; export tmp; } +Immed7_4: "#"^immval is immed7 [ immval = immed7 * 4; ] { tmp:4 = immval; export tmp; } +Immed5: "#"^immed5 is immed5 { export *[const]:4 immed5; } + + +@if defined(VERSION_6T2) || defined(VERSION_7) + +Immed12: "#"^immed12 is immed12_i; immed12_imm3 & immed12_imm8 + [ immed12=(immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8); ] +{ + export *[const]:4 immed12; +} + +Immed16: "#"^immed16 is immed12_i & sop0003; immed12_imm3 & immed12_imm8 + [ immed16 = (sop0003 << 12) | (immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8); ] +{ + export *[const]:2 immed16; +} + +PcrelImmed12Addr: reloc is immed12_i; immed12_imm3 & immed12_imm8 + [ reloc = ((inst_start+4) $and 0xfffffffc) + ((immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8)); ] +{ + # don't export as an address, may be PIC code, and would add spurious symbols. + export *[const]:4 reloc; +} + +NegPcrelImmed12Addr: reloc is immed12_i; immed12_imm3 & immed12_imm8 + [ reloc = ((inst_start+4) $and 0xfffffffc) - ((immed12_i<<11) | (immed12_imm3<<8) | (immed12_imm8)); ] +{ + # don't export as an address, may be PIC code, and would add spurious symbols. + export *[const]:4 reloc; +} + +PcrelOffset12: [reloc] is thc0707=1; offset12 + [ reloc = ((inst_start+4) $and 0xfffffffc) + offset12; ] +{ + export *:4 reloc; +} +PcrelOffset12: [reloc] is thc0707=0; offset12 + [ reloc = ((inst_start+4) $and 0xfffffffc) - offset12; ] +{ + export *:4 reloc; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + + +# decode thumb immediate12 encoded value + +@if defined(VERSION_6T2) || defined(VERSION_7) + +ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=0 & immed12_imm8 + [ imm32=immed12_imm8 $and 0xff; ] +{ + tmp:4 = imm32; shift_carry = CY; export tmp; +} +ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=1 & immed12_imm8 + [ imm32=(immed12_imm8<<16) | (immed12_imm8); ] +{ + tmp:4 = imm32; shift_carry = CY; export tmp; +} +ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=2 & immed12_imm8 + [ imm32=(immed12_imm8<<24) | (immed12_imm8<<8); ] +{ + tmp:4 = imm32; shift_carry = CY; export tmp; +} +ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; thc1414=0 & immed12_imm3=3 & immed12_imm8 + [ imm32=(immed12_imm8<<24) | (immed12_imm8<<16) | (immed12_imm8<<8) | (immed12_imm8); ] +{ + tmp:4 = imm32; shift_carry = CY; export tmp; +} +ThumbExpandImm12: "#"^imm32 is immed12_i=0 ; immed12_imm3 & thc0707 & immed7 + [ imm32=(((0x80+immed7)<<(32-((immed12_imm3<<1)|thc0707)))|((0x80+immed7)>>(((immed12_imm3<<1)|thc0707)))) $and 0xffffffff; ] +{ + tmp:4 = imm32; local tmp1 = (tmp >> 31); shift_carry = tmp1(0); export tmp; +} +ThumbExpandImm12: "#"^imm32 is immed12_i=1 ; immed12_imm3 & thc0707 & immed7 + [ imm32=(((0x80+immed7)<<(32-(16+((immed12_imm3<<1)|thc0707))))|((0x80+immed7)>>((16+((immed12_imm3<<1)|thc0707))))) $and 0xffffffff; ] +{ + tmp:4 = imm32; local tmp1 = (tmp >> 31); shift_carry = tmp1(0); export tmp; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +@if defined(VERSION_6T2) || defined(VERSION_7) + +thLsbImm: "#"^lsb is imm3_shft & imm2_shft [ lsb= (imm3_shft<<2) | imm2_shft; ] { tmp:4 = lsb; export tmp; } +thMsbImm: "#"^thc0004 is thc0004 { tmp:4 = thc0004; export tmp; } +thWidthMinus1: "#"^width is thc0004 [ width = thc0004 + 1; ] { tmp:4 = thc0004; export tmp; } +thBitWidth: "#"^w is imm3_shft & imm2_shft & thc0004 [ w = thc0004 - ((imm3_shft<<2) | imm2_shft) + 1; ] { tmp:4 = w; export tmp; } + +@endif # VERSION_6T2 || VERSION_7 + + +##################### +###### thshift2 ###### +##################### + +@if defined(VERSION_6T2) || defined(VERSION_7) + +thshift2: Rm0003 is imm3_shft=0 & imm2_shft=0 & thc0405=0 & Rm0003 +{ + shift_carry = CY; export Rm0003; +} + +thshift2: Rm0003, "lsl #"^shftval is imm3_shft & imm2_shft & thc0405=0 & Rm0003 + [ shftval=(imm3_shft<<2) | (imm2_shft); ] +{ + local tmp1=(Rm0003>>(32-shftval))&1; shift_carry=tmp1(0); local tmp2=Rm0003<>31); shift_carry=tmp1(0); tmp2:4=0; export tmp2; +} + +thshift2: Rm0003, "lsr #"^shftval is imm3_shft & imm2_shft & thc0405=1 & Rm0003 + [ shftval=(imm3_shft<<2) | (imm2_shft); ] +{ + local tmp1=(Rm0003>>(shftval-1))&1; shift_carry=tmp1(0); local tmp2=Rm0003>>shftval; export tmp2; +} + +thshift2: Rm0003, "asr #32" is imm3_shft=0 & imm2_shft=0 & thc0405=2 & Rm0003 +{ + local tmp1=(Rm0003>>31); shift_carry=tmp1(0); local tmp2 = Rm0003 s>> 32; export tmp2; +} + +thshift2: Rm0003, "asr #"^shftval is imm3_shft & imm2_shft & thc0405=2 & Rm0003 + [ shftval=(imm3_shft<<2) | (imm2_shft); ] +{ + local tmp1=(Rm0003>>(shftval-1))&1; shift_carry=tmp1(0); local tmp2=Rm0003 s>> shftval; export tmp2; +} + +thshift2: Rm0003, "rrx" is imm3_shft=0 & imm2_shft=0 & thc0405=3 & Rm0003 +{ + local tmp1=Rm0003&1; shift_carry=tmp1(0); local tmp2 = (zext(CY)<<31)|(Rm0003>>1); export tmp2; +} + +thshift2: Rm0003, "ror #"^shftval is imm3_shft & imm2_shft & thc0405=3 & Rm0003 + [ shftval=(imm3_shft<<2) | (imm2_shft); ] +{ + local tmp1=(Rm0003>>shftval)|(Rm0003<<(32-shftval)); local tmp2=tmp1 >> 31; shift_carry=tmp2(0); export tmp1; +} + +@endif # VERSION_6T2 || VERSION_7 + +Addr5: reloc is imm5 & thc0909 + [ reloc = inst_start + 4 + ((thc0909 << 6) | (imm5 << 1)); ] +{ + export *:4 reloc; +} + +Addr8: reloc is soffset8 + [ reloc = (inst_start+4) + 2*soffset8; ] +{ + export *:4 reloc; +} + +Addr11: reloc is soffset11 + [ reloc = (inst_start+4) + 2*soffset11; ] +{ + export *:4 reloc; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +ThAddr20: reloc is part2S=1 & part2imm6; part2J1 & part2J2 & part2imm11 + [ reloc = inst_start + 4 + ((-1 << 20) $or (part2J2 << 19) $or (part2J1 << 18) $or (part2imm6 << 12) $or (part2imm11 << 1)); ] +{ + export *:4 reloc; +} + +ThAddr20: reloc is part2S=0 & part2imm6; part2J1 & part2J2 & part2imm11 + [ reloc = inst_start + 4 + ((part2J2 << 19) $or (part2J1 << 18) $or (part2imm6 << 12) $or (part2imm11 << 1)); ] +{ + export *:4 reloc; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +ThAddr24: reloc is offset10S=0 & offset10; part2J1 & part2J2 & part2off + [ reloc = inst_start + 4 + (((part2J1 $xor 1) << 23) $or ((part2J2 $xor 1) << 22) $or (offset10 << 12) $or (part2off << 1)); ] +{ + export *:4 reloc; +} + +ThAddr24: reloc is offset10S=1 & offset10; part2J1 & part2J2 & part2off + [ reloc = inst_start + 4 + ((-1 << 24) $or (part2J1 << 23) $or (part2J2 << 22) $or (offset10 << 12) $or (part2off << 1)); ] +{ + export *:4 reloc; +} + +@if defined(VERSION_5) + +ThArmAddr23: reloc is offset10S=0 & offset10; part2J1 & part2J2 & part2off_10 + [ reloc = ((inst_start + 4) $and 0xfffffffc) + (((part2J1 $xor 1) << 23) $or ((part2J2 $xor 1) << 22) $or (offset10 << 12) $or (part2off_10 << 2)); ] +{ + export *:4 reloc; +} + +ThArmAddr23: reloc is offset10S=1 & offset10; part2J1 & part2J2 & part2off_10 + [ reloc = ((inst_start + 4) $and 0xfffffffc) + ((-1 << 24) $or (part2J1 << 23) $or (part2J2 << 22) $or (offset10 << 12) $or (part2off_10 << 2)); ] +{ + export *:4 reloc; +} + +@endif # VERSION_5 + + +Rn_exclaim: Rn0810 is Rn0810 & thc0810=0 & thc0000=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=1 & thc0101=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=2 & thc0202=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=3 & thc0303=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=4 & thc0404=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=5 & thc0505=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=6 & thc0606=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810 is Rn0810 & thc0810=7 & thc0707=1 { mult_addr = Rn0810; export Rn0810; } +Rn_exclaim: Rn0810! is Rn0810 & thc0810 { mult_addr = Rn0810; export Rn0810; } + +Rn_exclaim_WB: is Rn0810 & thc0810=0 & thc0000=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=1 & thc0101=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=2 & thc0202=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=3 & thc0303=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=4 & thc0404=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=5 & thc0505=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=6 & thc0606=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810=7 & thc0707=1 { } +Rn_exclaim_WB: is Rn0810 & thc0810 { Rn0810 = mult_addr; } + +# ldlist is the list of registers to be loaded or popped +LdRtype0: " "^r0 is thc0000=1 & r0 & thc0107=0 { r0 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype0: " "^r0^"," is thc0000=1 & r0 { r0 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype0: is thc0000=0 { } +LdRtype1: LdRtype0 r1 is LdRtype0 & thc0101=1 & r1 & thc0207=0 { r1 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype1: LdRtype0 r1^"," is LdRtype0 & thc0101=1 & r1 { r1 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype1: LdRtype0 is LdRtype0 & thc0101=0 { } +LdRtype2: LdRtype1 r2 is LdRtype1 & thc0202=1 & r2 & thc0307=0 { r2 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype2: LdRtype1 r2^"," is LdRtype1 & thc0202=1 & r2 { r2 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype2: LdRtype1 is LdRtype1 & thc0202=0 { } +LdRtype3: LdRtype2 r3 is LdRtype2 & thc0303=1 & r3 & thc0407=0 { r3 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype3: LdRtype2 r3^"," is LdRtype2 & thc0303=1 & r3 { r3 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype3: LdRtype2 is LdRtype2 & thc0303=0 { } +LdRtype4: LdRtype3 r4 is LdRtype3 & thc0404=1 & r4 & thc0507=0 { r4 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype4: LdRtype3 r4^"," is LdRtype3 & thc0404=1 & r4 { r4 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype4: LdRtype3 is LdRtype3 & thc0404=0 { } +LdRtype5: LdRtype4 r5 is LdRtype4 & thc0505=1 & r5 & thc0607=0 { r5 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype5: LdRtype4 r5^"," is LdRtype4 & thc0505=1 & r5 { r5 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype5: LdRtype4 is LdRtype4 & thc0505=0 { } +LdRtype6: LdRtype5 r6 is LdRtype5 & thc0606=1 & r6 & thc0707=0 { r6 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype6: LdRtype5 r6^"," is LdRtype5 & thc0606=1 & r6 { r6 = *mult_addr; mult_addr = mult_addr + 4; } +LdRtype6: LdRtype5 is LdRtype5 & thc0606=0 { } +ldlist: LdRtype6 r7 is LdRtype6 & thc0707=1 & r7 { r7 = *mult_addr; mult_addr = mult_addr + 4; } +ldlist: LdRtype6 is LdRtype6 & thc0707=0 { } + +#strlist is the list of registers to be stored +StrType0: " "^r0 is thc0000=1 & r0 & thc0107=0 { *mult_addr = r0; mult_addr = mult_addr + 4; } +StrType0: " "^r0^"," is thc0000=1 & r0 { *mult_addr = r0; mult_addr = mult_addr + 4; } +StrType0: is thc0000=0 { } +StrType1: StrType0 r1 is StrType0 & thc0101=1 & r1 & thc0207=0 { *mult_addr = r1; mult_addr = mult_addr + 4; } +StrType1: StrType0 r1^"," is StrType0 & thc0101=1 & r1 { *mult_addr = r1; mult_addr = mult_addr + 4; } +StrType1: StrType0 is StrType0 & thc0101=0 { } +StrType2: StrType1 r2 is StrType1 & thc0202=1 & r2 & thc0307=0 { *mult_addr = r2; mult_addr = mult_addr + 4; } +StrType2: StrType1 r2^"," is StrType1 & thc0202=1 & r2 { *mult_addr = r2; mult_addr = mult_addr + 4; } +StrType2: StrType1 is StrType1 & thc0202=0 { } +StrType3: StrType2 r3 is StrType2 & thc0303=1 & r3 & thc0407=0 { *mult_addr = r3; mult_addr = mult_addr + 4; } +StrType3: StrType2 r3^"," is StrType2 & thc0303=1 & r3 { *mult_addr = r3; mult_addr = mult_addr + 4; } +StrType3: StrType2 is StrType2 & thc0303=0 { } +StrType4: StrType3 r4 is StrType3 & thc0404=1 & r4 & thc0507=0 { *mult_addr = r4; mult_addr = mult_addr + 4; } +StrType4: StrType3 r4^"," is StrType3 & thc0404=1 & r4 { *mult_addr = r4; mult_addr = mult_addr + 4; } +StrType4: StrType3 is StrType3 & thc0404=0 { } +StrType5: StrType4 r5 is StrType4 & thc0505=1 & r5 & thc0607=0 { *mult_addr = r5; mult_addr = mult_addr + 4; } +StrType5: StrType4 r5^"," is StrType4 & thc0505=1 & r5 { *mult_addr = r5; mult_addr = mult_addr + 4; } +StrType5: StrType4 is StrType4 & thc0505=0 { } +StrType6: StrType5 r6 is StrType5 & thc0606=1 & r6 & thc0707=0 { *mult_addr = r6; mult_addr = mult_addr + 4; } +StrType6: StrType5 r6^"," is StrType5 & thc0606=1 & r6 { *mult_addr = r6; mult_addr = mult_addr + 4; } +StrType6: StrType5 is StrType5 & thc0606=0 { } +StrType7: StrType6 r7 is StrType6 & thc0707=1 & r7 { *mult_addr = r7; mult_addr = mult_addr + 4; } +StrType7: StrType6 is StrType6 & thc0707=0 { } +strlist: StrType7 is StrType7 { } + +# pshlist is the list registers to be pushed to memory +# SCR 10921, fix the order in which the regs appear in the disassembled insn, to be in line with objdump +# Also add commas between regs +# +PshType7: "" is thc0707=0 { } +PshType7: r7 is thc0707=1 & r7 { mult_addr = mult_addr - 4; *mult_addr = r7; } +PshType6: PshType7 is PshType7 & thc0606=0 { } +PshType6: r6 is PshType7 & thc0606=1 & r6 & thc0707=0 { mult_addr = mult_addr - 4; *mult_addr = r6; } +PshType6: r6^"," PshType7 is PshType7 & thc0606=1 & r6 { mult_addr = mult_addr - 4; *mult_addr = r6; } +PshType5: PshType6 is PshType6 & thc0505=0 { } +PshType5: r5 is PshType6 & thc0505=1 & r5 & thc0607=0 { mult_addr = mult_addr - 4; *mult_addr = r5; } +PshType5: r5^"," PshType6 is PshType6 & thc0505=1 & r5 { mult_addr = mult_addr - 4; *mult_addr = r5; } +PshType4: PshType5 is PshType5 & thc0404=0 { } +PshType4: r4 is PshType5 & thc0404=1 & r4 & thc0507=0 { mult_addr = mult_addr - 4; *mult_addr = r4; } +PshType4: r4^"," PshType5 is PshType5 & thc0404=1 & r4 { mult_addr = mult_addr - 4; *mult_addr = r4; } +PshType3: PshType4 is PshType4 & thc0303=0 { } +PshType3: r3 is PshType4 & thc0303=1 & r3 & thc0407=0 { mult_addr = mult_addr - 4; *mult_addr = r3; } +PshType3: r3^"," PshType4 is PshType4 & thc0303=1 & r3 { mult_addr = mult_addr - 4; *mult_addr = r3; } +PshType2: PshType3 is PshType3 & thc0202=0 { } +PshType2: r2 is PshType3 & thc0202=1 & r2 & thc0307=0 { mult_addr = mult_addr - 4; *mult_addr = r2; } +PshType2: r2^"," PshType3 is PshType3 & thc0202=1 & r2 { mult_addr = mult_addr - 4; *mult_addr = r2; } +PshType1: PshType2 is PshType2 & thc0101=0 { } +PshType1: r1 is PshType2 & thc0101=1 & r1 & thc0207=0 { mult_addr = mult_addr - 4; *mult_addr = r1; } +PshType1: r1^"," PshType2 is PshType2 & thc0101=1 & r1 { mult_addr = mult_addr - 4; *mult_addr = r1; } +pshlist: PshType1 is PshType1 & thc0000=0 { } +pshlist: r0 is PshType1 & thc0000=1 & r0 & thc0107=0 { mult_addr = mult_addr - 4; *mult_addr = r0; } +pshlist: r0^"," PshType1 is PshType1 & thc0000=1 & r0 { mult_addr = mult_addr - 4; *mult_addr = r0; } + +# ldlist_inc is the list of registers to be loaded for pop instructions +thrlist15: r0 is thc0000=1 & r0 & thc0115=0 { r0 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist15: r0^"," is thc0000=1 & r0 { r0 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist15: is thc0000=0 { } +thrlist14: thrlist15 r1 is thc0101=1 & thrlist15 & r1 & thc0215=0 { r1 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist14: thrlist15 r1^"," is thc0101=1 & thrlist15 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist14: thrlist15 is thc0101=0 & thrlist15 { } +thrlist13: thrlist14 r2 is thc0202=1 & thrlist14 & r2 & thc0315=0 { r2 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist13: thrlist14 r2^"," is thc0202=1 & thrlist14 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist13: thrlist14 is thc0202=0 & thrlist14 { } +thrlist12: thrlist13 r3 is thc0303=1 & thrlist13 & r3 & thc0415=0 { r3 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist12: thrlist13 r3^"," is thc0303=1 & thrlist13 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist12: thrlist13 is thc0303=0 & thrlist13 { } +thrlist11: thrlist12 r4 is thc0404=1 & thrlist12 & r4 & thc0515=0 { r4 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist11: thrlist12 r4^"," is thc0404=1 & thrlist12 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist11: thrlist12 is thc0404=0 & thrlist12 { } +thrlist10: thrlist11 r5 is thc0505=1 & thrlist11 & r5 & thc0615=0 { r5 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist10: thrlist11 r5^"," is thc0505=1 & thrlist11 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist10: thrlist11 is thc0505=0 & thrlist11 { } +thrlist9: thrlist10 r6 is thc0606=1 & thrlist10 & r6 & thc0715=0 { r6 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist9: thrlist10 r6^"," is thc0606=1 & thrlist10 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist9: thrlist10 is thc0606=0 & thrlist10 { } +thrlist8: thrlist9 r7 is thc0707=1 & thrlist9 & r7 & thc0815=0 { r7 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist8: thrlist9 r7^"," is thc0707=1 & thrlist9 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist8: thrlist9 is thc0707=0 & thrlist9 { } +thrlist7: thrlist8 r8 is thc0808=1 & thrlist8 & r8 & thc0915=0 { r8 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist7: thrlist8 r8^"," is thc0808=1 & thrlist8 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist7: thrlist8 is thc0808=0 & thrlist8 { } +thrlist6: thrlist7 r9 is thc0909=1 & thrlist7 & r9 & thc1015=0 { r9 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist6: thrlist7 r9^"," is thc0909=1 & thrlist7 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist6: thrlist7 is thc0909=0 & thrlist7 { } +thrlist5: thrlist6 r10 is thc1010=1 & thrlist6 & r10 & thc1115=0 { r10 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist5: thrlist6 r10^"," is thc1010=1 & thrlist6 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist5: thrlist6 is thc1010=0 & thrlist6 { } +thrlist4: thrlist5 r11 is thc1111=1 & thrlist5 & r11 & thc1215=0 { r11 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist4: thrlist5 r11^"," is thc1111=1 & thrlist5 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist4: thrlist5 is thc1111=0 & thrlist5 { } +thrlist3: thrlist4 r12 is thc1212=1 & thrlist4 & r12 & thc1315=0 { r12 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist3: thrlist4 r12^"," is thc1212=1 & thrlist4 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; } +thrlist3: thrlist4 is thc1212=0 & thrlist4 { } +thrlist2: thrlist3 sp is thc1313=1 & thrlist3 & sp & thc1415=0 { sp = * mult_addr; mult_addr = mult_addr + 4; } +thrlist2: thrlist3 sp^"," is thc1313=1 & thrlist3 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; } +thrlist2: thrlist3 is thc1313=0 & thrlist3 { } +thrlist1: thrlist2 lr is thc1414=1 & thrlist2 & lr & thc1515=0 { lr = * mult_addr; mult_addr = mult_addr + 4; } +thrlist1: thrlist2 lr^"," is thc1414=1 & thrlist2 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; } +thrlist1: thrlist2 is thc1414=0 & thrlist2 { } +thldrlist_inc: {thrlist1 pc } is thc1515=1 & thrlist1 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; } +thldrlist_inc: {thrlist1 } is thc1515=0 & thrlist1 { } + +@if defined(VERSION_6T2) || defined(VERSION_7) + +# thstrlist_inc is the list of registers to be stored using IA or IB in Addressing Mode 4 +thsinc15: r0 is thc0000=1 & r0 { * mult_addr = r0; mult_addr = mult_addr + 4; } +thsinc15: is thc0000=0 { } +thsinc14: thsinc15 r1 is thc0101=1 & thsinc15 & r1 & thc0215=0 { * mult_addr = r1; mult_addr = mult_addr + 4; } +thsinc14: thsinc15 r1^"," is thc0101=1 & thsinc15 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; } +thsinc14: thsinc15 is thc0101=0 & thsinc15 { } +thsinc13: thsinc14 r2 is thc0202=1 & thsinc14 & r2 & thc0315=0 { * mult_addr = r2; mult_addr = mult_addr + 4; } +thsinc13: thsinc14 r2^"," is thc0202=1 & thsinc14 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; } +thsinc13: thsinc14 is thc0202=0 & thsinc14 { } +thsinc12: thsinc13 r3 is thc0303=1 & thsinc13 & r3 & thc0415=0 { * mult_addr = r3; mult_addr = mult_addr + 4; } +thsinc12: thsinc13 r3^"," is thc0303=1 & thsinc13 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; } +thsinc12: thsinc13 is thc0303=0 & thsinc13 { } +thsinc11: thsinc12 r4 is thc0404=1 & thsinc12 & r4 & thc0515=0 { * mult_addr = r4; mult_addr = mult_addr + 4; } +thsinc11: thsinc12 r4^"," is thc0404=1 & thsinc12 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; } +thsinc11: thsinc12 is thc0404=0 & thsinc12 { } +thsinc10: thsinc11 r5 is thc0505=1 & thsinc11 & r5 & thc0615=0 { * mult_addr = r5; mult_addr = mult_addr + 4; } +thsinc10: thsinc11 r5^"," is thc0505=1 & thsinc11 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; } +thsinc10: thsinc11 is thc0505=0 & thsinc11 { } +thsinc9: thsinc10 r6 is thc0606=1 & thsinc10 & r6 & thc0715=0 { * mult_addr = r6; mult_addr = mult_addr + 4; } +thsinc9: thsinc10 r6^"," is thc0606=1 & thsinc10 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; } +thsinc9: thsinc10 is thc0606=0 & thsinc10 { } +thsinc8: thsinc9 r7 is thc0707=1 & thsinc9 & r7 & thc0815=0 { * mult_addr = r7; mult_addr = mult_addr + 4; } +thsinc8: thsinc9 r7^"," is thc0707=1 & thsinc9 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; } +thsinc8: thsinc9 is thc0707=0 & thsinc9 { } +thsinc7: thsinc8 r8 is thc0808=1 & thsinc8 & r8 & thc0915=0 { * mult_addr = r8; mult_addr = mult_addr + 4; } +thsinc7: thsinc8 r8^"," is thc0808=1 & thsinc8 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; } +thsinc7: thsinc8 is thc0808=0 & thsinc8 { } +thsinc6: thsinc7 r9 is thc0909=1 & thsinc7 & r9 & thc1015=0 { * mult_addr = r9; mult_addr = mult_addr + 4; } +thsinc6: thsinc7 r9^"," is thc0909=1 & thsinc7 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; } +thsinc6: thsinc7 is thc0909=0 & thsinc7 { } +thsinc5: thsinc6 r10 is thc1010=1 & thsinc6 & r10 & thc1115=0 { * mult_addr = r10; mult_addr = mult_addr + 4; } +thsinc5: thsinc6 r10^"," is thc1010=1 & thsinc6 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; } +thsinc5: thsinc6 is thc1010=0 & thsinc6 { } +thsinc4: thsinc5 r11 is thc1111=1 & thsinc5 & r11 & thc1215=0 { * mult_addr = r11; mult_addr = mult_addr + 4; } +thsinc4: thsinc5 r11^"," is thc1111=1 & thsinc5 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; } +thsinc4: thsinc5 is thc1111=0 & thsinc5 { } +thsinc3: thsinc4 r12 is thc1212=1 & thsinc4 & r12 & thc1315=0 { * mult_addr = r12; mult_addr = mult_addr + 4; } +thsinc3: thsinc4 r12^"," is thc1212=1 & thsinc4 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; } +thsinc3: thsinc4 is thc1212=0 & thsinc4 { } +thsinc2: thsinc3 sp is thc1313=1 & thsinc3 & sp & thc1415=0 { * mult_addr = sp; mult_addr = mult_addr + 4; } +thsinc2: thsinc3 sp^"," is thc1313=1 & thsinc3 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; } +thsinc2: thsinc3 is thc1313=0 & thsinc3 { } +thsinc1: thsinc2 lr is thc1414=1 & thsinc2 & lr & thc1515=0 { * mult_addr = lr; mult_addr = mult_addr + 4; } +thsinc1: thsinc2 lr^"," is thc1414=1 & thsinc2 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; } +thsinc1: thsinc2 is thc1414=0 & thsinc2 { } +thstrlist_inc: {thsinc1 pc } is thc1515=1 & thsinc1 & pc { *:4 mult_addr = inst_start+4; mult_addr = mult_addr + 4; } +thstrlist_inc: {thsinc1 } is thc1515=0 & thsinc1 { } + +# thldrlist_dec is the list of registers to be loaded using DA or DB in Addressing Mode 4 +thrldec15: pc is thc1515=1 & pc { pc = * mult_addr; mult_addr = mult_addr - 4; } +thrldec15: is thc1515=0 { } +thrldec14: lr thrldec15 is thc1414=1 & thrldec15 & lr & thc1515=0 { lr = * mult_addr; mult_addr = mult_addr - 4; } +thrldec14: lr^"," thrldec15 is thc1414=1 & thrldec15 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; } +thrldec14: thrldec15 is thc1414=0 & thrldec15 { } +thrldec13: sp thrldec14 is thc1313=1 & thrldec14 & sp & thc1415=0 { sp = * mult_addr; mult_addr = mult_addr - 4; } +thrldec13: sp^"," thrldec14 is thc1313=1 & thrldec14 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; } +thrldec13: thrldec14 is thc1313=0 & thrldec14 { } +thrldec12: r12 thrldec13 is thc1212=1 & thrldec13 & r12 & thc1315=0 { r12 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec12: r12^"," thrldec13 is thc1212=1 & thrldec13 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec12: thrldec13 is thc1212=0 & thrldec13 { } +thrldec11: r11 thrldec12 is thc1111=1 & thrldec12 & r11 & thc1215=0 { r11 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec11: r11^"," thrldec12 is thc1111=1 & thrldec12 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec11: thrldec12 is thc1111=0 & thrldec12 { } +thrldec10: r10 thrldec11 is thc1010=1 & thrldec11 & r10 & thc1115=0 { r10 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec10: r10^"," thrldec11 is thc1010=1 & thrldec11 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec10: thrldec11 is thc1010=0 & thrldec11 { } +thrldec9: r9 thrldec10 is thc0909=1 & thrldec10 & r9 & thc1015=0 { r9 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec9: r9^"," thrldec10 is thc0909=1 & thrldec10 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec9: thrldec10 is thc0909=0 & thrldec10 { } +thrldec8: r8 thrldec9 is thc0808=1 & thrldec9 & r8 & thc0915=0 { r8 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec8: r8^"," thrldec9 is thc0808=1 & thrldec9 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec8: thrldec9 is thc0808=0 & thrldec9 { } +thrldec7: r7 thrldec8 is thc0707=1 & thrldec8 & r7 & thc0815=0 { r7 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec7: r7^"," thrldec8 is thc0707=1 & thrldec8 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec7: thrldec8 is thc0707=0 & thrldec8 { } +thrldec6: r6 thrldec7 is thc0606=1 & thrldec7 & r6 & thc0715=0 { r6 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec6: r6^"," thrldec7 is thc0606=1 & thrldec7 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec6: thrldec7 is thc0606=0 & thrldec7 { } +thrldec5: r5 thrldec6 is thc0505=1 & thrldec6 & r5 & thc0615=0 { r5 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec5: r5^"," thrldec6 is thc0505=1 & thrldec6 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec5: thrldec6 is thc0505=0 & thrldec6 { } +thrldec4: r4 thrldec5 is thc0404=1 & thrldec5 & r4 & thc0515=0 { r4 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec4: r4^"," thrldec5 is thc0404=1 & thrldec5 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec4: thrldec5 is thc0404=0 & thrldec5 { } +thrldec3: r3 thrldec4 is thc0303=1 & thrldec4 & r3 & thc0415=0 { r3 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec3: r3^"," thrldec4 is thc0303=1 & thrldec4 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec3: thrldec4 is thc0303=0 & thrldec4 { } +thrldec2: r2 thrldec3 is thc0202=1 & thrldec3 & r2 & thc0315=0 { r2 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec2: r2^"," thrldec3 is thc0202=1 & thrldec3 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec2: thrldec3 is thc0202=0 & thrldec3 { } +thrldec1: r1 thrldec2 is thc0101=1 & thrldec2 & r1 & thc0215=0 { r1 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec1: r1^"," thrldec2 is thc0101=1 & thrldec2 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; } +thrldec1: thrldec2 is thc0101=0 & thrldec2 { } +thldrlist_dec: { r0 thrldec1 } is thc0000=1 & thrldec1 & r0 & thc0115=0 { r0 = * mult_addr; mult_addr = mult_addr - 4; } +thldrlist_dec: { r0^"," thrldec1 } is thc0000=1 & thrldec1 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; } +thldrlist_dec: { thrldec1 } is thc0000=0 & thrldec1 { } + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +# thstrlist_dec is the list of registers to be pushed +thsdec15: pc is thc1515=1 & pc { *:4 mult_addr = inst_start+4; mult_addr = mult_addr - 4; } +thsdec15: is thc1515=0 { } +thsdec14: lr thsdec15 is thc1414=1 & thsdec15 & lr & thc1515=0 { * mult_addr=lr; mult_addr = mult_addr - 4; } +thsdec14: lr^"," thsdec15 is thc1414=1 & thsdec15 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; } +thsdec14: thsdec15 is thc1414=0 & thsdec15 { } +thsdec13: sp thsdec14 is thc1313=1 & thsdec14 & sp & thc1415=0 { * mult_addr=sp; mult_addr = mult_addr - 4; } +thsdec13: sp^"," thsdec14 is thc1313=1 & thsdec14 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; } +thsdec13: thsdec14 is thc1313=0 & thsdec14 { } +thsdec12: r12 thsdec13 is thc1212=1 & thsdec13 & r12 & thc1315=0 { * mult_addr=r12; mult_addr = mult_addr - 4; } +thsdec12: r12^"," thsdec13 is thc1212=1 & thsdec13 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; } +thsdec12: thsdec13 is thc1212=0 & thsdec13 { } +thsdec11: r11 thsdec12 is thc1111=1 & thsdec12 & r11 & thc1215=0 { * mult_addr=r11; mult_addr = mult_addr - 4; } +thsdec11: r11^"," thsdec12 is thc1111=1 & thsdec12 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; } +thsdec11: thsdec12 is thc1111=0 & thsdec12 { } +thsdec10: r10 thsdec11 is thc1010=1 & thsdec11 & r10 & thc1115=0 { * mult_addr=r10; mult_addr = mult_addr - 4; } +thsdec10: r10^"," thsdec11 is thc1010=1 & thsdec11 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; } +thsdec10: thsdec11 is thc1010=0 & thsdec11 { } +thsdec9: r9 thsdec10 is thc0909=1 & thsdec10 & r9 & thc1015=0 { * mult_addr=r9; mult_addr = mult_addr - 4; } +thsdec9: r9^"," thsdec10 is thc0909=1 & thsdec10 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; } +thsdec9: thsdec10 is thc0909=0 & thsdec10 { } +thsdec8: r8 thsdec9 is thc0808=1 & thsdec9 & r8 & thc0915=0 { * mult_addr=r8; mult_addr = mult_addr - 4; } +thsdec8: r8^"," thsdec9 is thc0808=1 & thsdec9 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; } +thsdec8: thsdec9 is thc0808=0 & thsdec9 { } +thsdec7: r7 thsdec8 is thc0707=1 & thsdec8 & r7 & thc0815=0 { * mult_addr=r7; mult_addr = mult_addr - 4; } +thsdec7: r7^"," thsdec8 is thc0707=1 & thsdec8 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; } +thsdec7: thsdec8 is thc0707=0 & thsdec8 { } +thsdec6: r6 thsdec7 is thc0606=1 & thsdec7 & r6 & thc0715=0 { * mult_addr=r6; mult_addr = mult_addr - 4; } +thsdec6: r6^"," thsdec7 is thc0606=1 & thsdec7 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; } +thsdec6: thsdec7 is thc0606=0 & thsdec7 { } +thsdec5: r5 thsdec6 is thc0505=1 & thsdec6 & r5 & thc0615=0 { * mult_addr=r5; mult_addr = mult_addr - 4; } +thsdec5: r5^"," thsdec6 is thc0505=1 & thsdec6 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; } +thsdec5: thsdec6 is thc0505=0 & thsdec6 { } +thsdec4: r4 thsdec5 is thc0404=1 & thsdec5 & r4 & thc0515=0 { * mult_addr=r4; mult_addr = mult_addr - 4; } +thsdec4: r4^"," thsdec5 is thc0404=1 & thsdec5 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; } +thsdec4: thsdec5 is thc0404=0 & thsdec5 { } +thsdec3: r3 thsdec4 is thc0303=1 & thsdec4 & r3 & thc0415=0 { * mult_addr=r3; mult_addr = mult_addr - 4; } +thsdec3: r3^"," thsdec4 is thc0303=1 & thsdec4 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; } +thsdec3: thsdec4 is thc0303=0 & thsdec4 { } +thsdec2: r2 thsdec3 is thc0202=1 & thsdec3 & r2 & thc0415=0 { * mult_addr=r2; mult_addr = mult_addr - 4; } +thsdec2: r2^"," thsdec3 is thc0202=1 & thsdec3 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; } +thsdec2: thsdec3 is thc0202=0 & thsdec3 { } +thsdec1: r1 thsdec2 is thc0101=1 & thsdec2 & r1 & thc0215=0 { * mult_addr=r1; mult_addr = mult_addr - 4; } +thsdec1: r1^"," thsdec2 is thc0101=1 & thsdec2 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; } +thsdec1: thsdec2 is thc0101=0 & thsdec2 { } +thstrlist_dec: { r0 thsdec1 } is thc0000=1 & thsdec1 & r0 & thc0115=0 { * mult_addr=r0; mult_addr = mult_addr - 4; } +thstrlist_dec: { r0^"," thsdec1 } is thc0000=1 & thsdec1 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; } +thstrlist_dec: { thsdec1 } is thc0000=0 & thsdec1 { } + +ldbrace: {ldlist } is ldlist { } +stbrace: {strlist } is strlist { } +psbrace: { pshlist } is pshlist { } + +# Some extra subconstructors for the push and pop instructions +pclbrace:{ldlist^"," pc } is ldlist & pc { build ldlist; pc = *mult_addr; mult_addr = mult_addr + 4; } +pclbrace:{ pc } is thc0007=0 & pc { pc = *mult_addr; mult_addr = mult_addr + 4; } +pcpbrace:{ pshlist^"," lr } is pshlist & lr { mult_addr = mult_addr - 4; *mult_addr = lr; build pshlist; } +pcpbrace:{ lr } is thc0007=0 & lr { mult_addr = mult_addr - 4; *mult_addr = lr; } + +@if defined(VERSION_6T2) || defined(VERSION_7) +RnIndirect12: [Rn0003,"#"^offset12] is Rn0003; offset12 { local tmp = Rn0003 + offset12; export tmp; } + +RnIndirectPUW: [Rn0003],"#"^-immed8 is Rn0003; addr_puw=1 & immed8 { local tmp = Rn0003; Rn0003=Rn0003-immed8; export tmp; } +RnIndirectPUW: [Rn0003],"#"^immed8 is Rn0003; addr_puw=3 & immed8 { local tmp = Rn0003; Rn0003=Rn0003+immed8; export tmp; } +RnIndirectPUW: [Rn0003,"#"^-immed8] is Rn0003; addr_puw=4 & immed8 { local tmp = Rn0003 - immed8; export tmp; } +RnIndirectPUW: [Rn0003,"#"^-immed8]! is Rn0003; addr_puw=5 & immed8 { local tmp = Rn0003 - immed8; Rn0003=tmp; export tmp; } +RnIndirectPUW: [Rn0003,"#"^immed8]! is Rn0003; addr_puw=7 & immed8 { local tmp = Rn0003 + immed8; Rn0003=tmp; export tmp; } + +@define RN_INDIRECT_PUW "(op0; (addr_puw=4 | thc0808=1)) & RnIndirectPUW" # constraint for RnIndirectPUW + +RnIndirectPUW1: [Rn0003],"#"^-immval is Rn0003 & addr_puw1=0x3; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003; Rn0003=Rn0003-immval; export tmp; } +RnIndirectPUW1: [Rn0003],"#"^immval is Rn0003 & addr_puw1=0x7; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003; Rn0003=Rn0003+immval; export tmp; } +RnIndirectPUW1: [Rn0003,"#"^-immval] is Rn0003 & addr_puw1=0xa; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 - immval; export tmp; } +RnIndirectPUW1: [Rn0003,"#"^-immval]! is Rn0003 & addr_puw1=0xb; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 - immval; Rn0003=tmp; export tmp; } +RnIndirectPUW1: [Rn0003,"#"^immval] is Rn0003 & addr_puw1=0xe; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 + immval; export tmp; } +RnIndirectPUW1: [Rn0003,"#"^immval]! is Rn0003 & addr_puw1=0xf; immed8 [ immval = immed8 * 4; ] { local tmp = Rn0003 + immval; Rn0003=tmp; export tmp; } + +@endif # VERSION_6T2 || VERSION_7 + +@define RN_INDIRECT_PUW1 "((thc0808=1 | thc0505=1); op0) & RnIndirectPUW1" # constraint for RnIndirectPUW1 + +RnIndirect4: [Rn0305,"#"^immval] is Rn0305 & immed5 [ immval = immed5 * 4; ] { local tmp = Rn0305 + immval; export tmp; } +RnIndirect2: [Rn0305,"#"^immval] is Rn0305 & immed5 [ immval = immed5 * 2; ] { local tmp = Rn0305 + immval; export tmp; } +RnIndirect1: [Rn0305,"#"^immed5] is Rn0305 & immed5 { local tmp = Rn0305 + immed5; export tmp; } + +RnRmIndirect: [Rn0305,Rm0608] is Rn0305 & Rm0608 { local tmp = Rn0305 + Rm0608; export tmp; } + +Pcrel8Indirect: [reloc] is immed8 + [ reloc = ((inst_start+4) $and 0xfffffffc) + 4*immed8; ] +{ + export *:4 reloc; +} + +Sprel8Indirect: [sp,"#"^immval] is sp & immed8 [ immval = immed8 * 4; ] { local tmp = sp + immval; export tmp; } + +@if defined(VERSION_6T2) || defined(VERSION_7) + +taddrmode5: [Rn0003,"#"^off8] is thP8=1 & thU7=1 & thW5=0 & Rn0003; immed8 [ off8=immed8*4; ] { local tmp = Rn0003 + off8; export tmp; } +taddrmode5: [Rn0003,"#"^noff8] is thP8=1 & thU7=0 & thW5=0 & Rn0003; immed8 [ noff8=-(immed8*4); ] { local tmp = Rn0003 + noff8; export tmp; } +taddrmode5: [Rn0003,"#"^off8]! is thP8=1 & thU7=1 & thW5=1 & Rn0003; immed8 [ off8=immed8*4; ] { Rn0003 = Rn0003 + off8; export Rn0003; } +taddrmode5: [Rn0003,"#"^noff8]! is thP8=1 & thU7=0 & thW5=1 & Rn0003; immed8 [ noff8=-(immed8*4); ] { Rn0003 = Rn0003 + noff8; export Rn0003; } +taddrmode5: [Rn0003],"#"^off8 is thP8=0 & thU7=1 & thW5=1 & Rn0003; immed8 [ off8=immed8*4; ] { local tmp = Rn0003; Rn0003 = Rn0003+off8; export tmp; } +taddrmode5: [Rn0003],"#"^noff8 is thP8=0 & thU7=0 & thW5=1 & Rn0003; immed8 [ noff8=-(immed8*4); ] { local tmp = Rn0003; Rn0003 = Rn0003 + noff8; export tmp; } +taddrmode5: [Rn0003],{immed8} is thP8=0 & thU7=1 & thW5=0 & Rn0003; immed8 { export Rn0003; } + +@endif # VERSION_6T2 || VERSION_7 + +# +# Modes for SRS instructions +# +thSRSMode: "usr" is thsrsMode=8 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "fiq" is thsrsMode=9 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "irq" is thsrsMode=10 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "svc" is thsrsMode=11 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "mon" is thsrsMode=14 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "abt" is thsrsMode=15 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "und" is thsrsMode=19 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "sys" is thsrsMode=23 & thc0004 { export *[const]:1 thc0004; } +thSRSMode: "#"^thsrsMode is thsrsMode { export *[const]:1 thsrsMode; } + +# +# Detect if the PC is loaded and do a GOTO +# +# TODO: this is how all detections of writes into the PC should be done. +# Instead of enumerating and splitting the case into PC loaded and non loaded, IE (add PC,#0x...) +# Should only have one base constructor and have a sub constructor and build to test if the PC was loaded and do the right thing. +# + +@if defined(VERSION_6T2) || defined(VERSION_7) + +RtGotoCheck: is Rt1215=15 { + LoadWritePC(pc); + goto [pc]; +} +RtGotoCheck: is Rt1215 {} + +@endif # VERSION_6T2 || VERSION_7 + +############################################################ + +# Base constructors + +# We have the following operand types: +# Type Corresponding syntax in ARM/THUMB manual +# +# Rd0002 with Rd occupying bits 0-2 +# Rd0810 with Rd occupying bits 8-10 +# Rm0305 with Rm occupying bits 3-5 +# Rm0608 with Rm occupying bits 6-8 +# Rn0002 with Rn occupying bits 0-2 +# Rn0305 with Rn occupying bits 3-5 +# Rn0810 with Rn occupying bits 8-10 +# Hrd0002 with H1 bit in diagram +# Hrn0002 with H1 bit in diagram +# Hrm0305 with H2 bit in diagram +# Rs0305 with Rs occupying bits 3-5 +# Immed3 # +# Immed5 # +# Immed8 # +# Pcrel8 PC,#*4 +# Sprel8 SP,#*4 +# Immed7_4 #*4 +# thcc +# Addr8 (for B) +# Addr11 (for B no condition) +# ThAddr22 (for double BL, BLX) +# immed8 (no "#" as in BKPT and SWI) +# Rn_exclaim ! +# ldbrace (load instructions) +# strbrace (store instructions) +# RnIndirect4 [,#*4] +# RnIndirect2 [,#*2] +# RnIndirect1 [,#] +# RnRmIndirect [,] +# Pcrel8Indirect [PC,#*4] +# Sprel8Indirect [SP,#*4] + +# + + +@if defined(VERSION_6T2) || defined(VERSION_7) +# Ensure that the recursive rule for ARMcond is applied for assembly +with : ARMcondCk=1 { +@endif + + +:adc^CheckInIT_CZNO^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x105 & Rm0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_add_with_carry_flags(Rd0002,Rm0305); + Rd0002 = Rd0002 + Rm0305 + zext(CY); + resflags(Rd0002); + build CheckInIT_CZNO; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:adc^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0xa & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_add_with_carry_flags(Rn0003,ThumbExpandImm12); + Rd0811 = Rn0003 + ThumbExpandImm12 + zext(CY); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:adc^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0xa & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + th_add_with_carry_flags(Rn0003,thshift2); + local tmp = thshift2+zext(CY); + Rd0811 = Rn0003+tmp; + resflags(Rd0811); + build thSBIT_CZNO; +} +@endif # VERSION_6T2 || VERSION_7 + +:add^CheckInIT_CZNO^ItCond Rd0002,Rn0305,Immed3 is TMode=1 & ItCond & op9=0x0e & Immed3 & Rn0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_addflags(Rn0305,Immed3); + Rd0002 = Rn0305 + Immed3; + resflags(Rd0002); + build CheckInIT_CZNO; +} + +:add^CheckInIT_CZNO^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=0x06 & Rd0810 & Immed8 & CheckInIT_CZNO +{ + build ItCond; + th_addflags(Rd0810,Immed8); + Rd0810 = Rd0810 + Immed8; + resflags(Rd0810); + build CheckInIT_CZNO; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:add^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_addflags(Rn0003,ThumbExpandImm12); + Rd0811 = Rn0003+ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:addw^ItCond Rd0811,Rn0003,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & Rn0003; thc1515=0 & Rd0811) & Immed12 +{ + build ItCond; + th_addflags(Rn0003,Immed12); + Rd0811 = Rn0003+Immed12; + resflags(Rd0811); +} + +:add^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=8 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + local tmp = thshift2; + th_addflags(Rn0003,tmp); + Rd0811 = Rn0003+tmp; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:add^thSBIT_CZNO^ItCond^".w" Rd0811,sp,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thSBIT_CZNO & sp & sop0003=0xd; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_addflags(sp,ThumbExpandImm12); + Rd0811 = sp+ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:addw^ItCond Rd0811,sp,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xd & sp; thc1515=0 & Rd0811) & Immed12 +{ + build ItCond; + th_addflags(sp,Immed12); + Rd0811 = sp+Immed12; + resflags(Rd0811); +} + +:add^thSBIT_CZNO^ItCond^".w" Rd0811,sp,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=8 & thSBIT_CZNO & sop0003=0xd & sp; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + local tmp = thshift2; + th_addflags(sp,tmp); + Rd0811 = sp+tmp; + resflags(Rd0811); + build thSBIT_CZNO; +} + +@endif # VERSION_6T2 || VERSION_7 + +:add^CheckInIT_CZNO^ItCond Rd0002,Rn0305,Rm0608 is TMode=1 & ItCond & op9=0x0c & Rm0608 & Rn0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_addflags(Rn0305,Rm0608); + Rd0002 = Rn0305 + Rm0608; + resflags(Rd0002); + build CheckInIT_CZNO; +} + +:add^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x44 & Hrd0002 & Hrm0305 +{ + build ItCond; + Hrd0002 = Hrd0002 + Hrm0305; +} + +:add^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x44 & Hrd0002 & Hrm0305 & hrd0002=7 & h1=1 +{ + build ItCond; + dest:4 = Hrd0002 + Hrm0305; + BranchWritePC(dest); + goto [pc]; +} + +:add^ItCond Rd0810,Sprel8 is TMode=1 & ItCond & op11=0x15 & Rd0810 & Sprel8 +{ + build ItCond; + Rd0810 = Sprel8; +} + +:add^ItCond sp,Immed7_4 is TMode=1 & ItCond & op7=0x160 & sp & Immed7_4 +{ + build ItCond; + sp = sp + Immed7_4; +} + +:adr^ItCond Rd0810,Pcrel8 is TMode=1 & ItCond & op11=0x14 & Rd0810 & Pcrel8 +{ + build ItCond; + Rd0810 = &Pcrel8; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:adr^ItCond^".w" Rd0811,NegPcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811) & NegPcrelImmed12Addr +{ + build ItCond; + Rd0811 = &NegPcrelImmed12Addr; +} + +:adr^ItCond^".w" Rd0811,PcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811) & PcrelImmed12Addr +{ + build ItCond; + Rd0811 = &PcrelImmed12Addr; +} + +:adr^ItCond^".w" Rd0811,NegPcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811 & thc0811=15) & NegPcrelImmed12Addr +{ + build ItCond; + pc = &NegPcrelImmed12Addr; + goto NegPcrelImmed12Addr; +} + +:adr^ItCond^".w" Rd0811,PcrelImmed12Addr is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=0 & thc0404=0 & sop0003=0xf; thc1515=0 & Rd0811 & thc0811=15) & PcrelImmed12Addr +{ + build ItCond; + pc = &PcrelImmed12Addr; + goto PcrelImmed12Addr; +} + +@endif # VERSION_6T2 || VERSION_7 + +:and^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x100 & Rd0002 & Rm0305 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rd0002 & Rm0305; + resflags(Rd0002); + build CheckInIT_ZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:and^thSBIT_ZN^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + Rd0811 = Rn0003 & ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_ZN; +} + +:and^thSBIT_ZN^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + Rd0811 = Rn0003 & thshift2; + resflags(Rd0811); + build thSBIT_ZN; +} +@endif # VERSION_6T2 || VERSION_7 + +macro th_set_carry_for_asr(op1,shift_count) { + local bit = (op1 s>> (shift_count-1)) & 1; + tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0)); +} + +#note that this is a special case where immed5 = 0, which corresponds to a shift amount of 32 +:asr^CheckInIT_CZN^ItCond Rd0002,Rm0305,"#0x20" is TMode=1 & ItCond & op11=0x02 & Immed5 & Rm0305 & Rd0002 & immed5=0 & CheckInIT_CZN +{ + build ItCond; + th_set_carry_for_asr(Rm0305,32:1); + Rd0002 = Rm0305 s>> 32; + resflags(Rd0002); + build CheckInIT_CZN; +} + +:asr^CheckInIT_CZN^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=0x02 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN +{ + build ItCond; + th_set_carry_for_asr(Rm0305,Immed5); + Rd0002 = Rm0305 s>> Immed5; + resflags(Rd0002); + build CheckInIT_CZN; +} + +:asr^CheckInIT_CZN^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x104 & Rd0002 & Rs0305 & CheckInIT_CZN +{ + build ItCond; + local shift_amount = Rs0305 & 0xff; + th_set_carry_for_asr(Rd0002,shift_amount); + Rd0002 = Rd0002 s>> (shift_amount); + resflags(Rd0002); + build CheckInIT_CZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:asr^thSBIT_CZN^ItCond^".w" Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=0xf; thc1515=0 & Rd0811 & thc0405=2 & thshift2 +{ + build ItCond; + build thshift2; + Rd0811 = thshift2; + tmpCY = shift_carry; + resflags(Rd0811); + build thSBIT_CZN; +} + +:asr^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=2 & thSBIT_CZN & Rn0003; op12=0xf & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + local shift_amount = Rm0003 & 0xff; + th_set_carry_for_asr(Rn0003,shift_amount); + Rd0811 = Rn0003 s>> (shift_amount); + resflags(Rd0811); + build thSBIT_CZN; +} +@endif # VERSION_6T2 || VERSION_7 + +# this constructor is identical to 16-bit udf instruction. it looks +# like it implented an unconditional branch instruction (giving it a +# made up name), but the thumb 16-bit instruction does not support +# unconditional branching. + +@ifdef NOT_AN_INSTRUCTION +:bal Addr8 is TMode=1 & op12=0xd & thcond=14 & Addr8 +{ + goto Addr8; +} +@endif + +:b^thcc Addr8 is TMode=1 & ItCond & op12=0b1101 & $(THCC) & Addr8 +{ + if (thcc) goto Addr8; +} + +:b^ItCond Addr11 is TMode=1 & ItCond & op11=0b11100 & Addr11 +{ + goto Addr11; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:b^part2thcc^".w" ThAddr20 is TMode=1 & (part2op=0x1e & $(PART2THCC); part2c1415=2 & part2c1212=0) & ThAddr20 +{ + if (part2thcc) goto ThAddr20; +} + +:b^ItCond^".w" ThAddr24 is TMode=1 & ItCond & (op11=0x1e; part2c1415=2 & part2c1212=1) & ThAddr24 +{ + build ItCond; + goto ThAddr24; +} +@endif # VERSION_6T2 || VERSION_7 + + +@if defined(VERSION_6T2) || defined(VERSION_7) +:bfc^ItCond Rd0811,thLsbImm,thBitWidth is TMode=1 & ItCond & op0=0xf36f; thc1515=0 & Rd0811 & thc0505=0 & thLsbImm & thMsbImm & thBitWidth +{ + build ItCond; + clearMask:4 = (-1 << (thMsbImm + 1)) | (-1 >> (32 - thLsbImm)); + Rd0811 = Rd0811 & clearMask; +} + +:bfi^ItCond Rd0811,Rn0003,thLsbImm,thBitWidth is TMode=1 & ItCond & op4=0xf36 & Rn0003; thc1515=0 & Rd0811 & thc0505=0 & thLsbImm & thMsbImm & thBitWidth +{ + build ItCond; + clearMask:4 = (-1 << (thMsbImm + 1)) | (-1 >> (32 - thLsbImm)); + bits:4 = (Rn0003 << thLsbImm) & ~clearMask; + Rd0811 = (Rd0811 & clearMask) | bits; +} + +@endif # VERSION_6T2 || VERSION_7 + + +:bic^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10e & Rd0002 & Rm0305 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rd0002 & (~Rm0305); + resflags(Rd0002); + build CheckInIT_ZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:bic^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=1 & thSBIT_ZN & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + Rd0811 = Rn0003&(~ThumbExpandImm12); + resflags(Rd0811); + build thSBIT_ZN; +} + +:bic^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=1 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + Rd0811 = Rn0003&(~thshift2); + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} +@endif # VERSION_6T2 || VERSION_7 + + +@if defined(VERSION_5) + +# Exception Generation and UDF + +:hlt immed6 is TMode=1 & op6=0b1011101010 & immed6 +{ + software_hlt(immed6:4); +} + +:bkpt immed8 is TMode=1 & ItCond & op8=0xbe & immed8 +{ + software_bkpt(immed8:4); + # Not a mistake, breakpoint always unconditional even in IT Block + build ItCond; +} + +:hvc "#"^tmp is TMode=1 & op4=0xf7e & thc0003; op12=0x8 & thc0011 [tmp = thc0003 << 12 | thc0011;] +{ + software_hvc(tmp:4); +} + +# Requires Security Extensions +:smc^ItCond "#"^thc0003 is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0x8 +{ + build ItCond; + software_smc(thc0003:1); +} + +@ifndef NOT_AN_INSTRUCTION +:udf^ItCond "#"thc0007 is TMode=1 & ItCond & op8 = 0xde & thc0007 +{ + build ItCond; + local excaddr:4 = inst_start; + local target:4 = software_udf(thc0007:4, excaddr); + goto [target]; +} +@endif + +:udf^ItCond "#"tmp is TMode=1 & ItCond & op4=0xf7f & thc0003; op12=0xa & thc0011 [tmp = thc0003 << 12 | thc0011;] +{ + build ItCond; + local excaddr:4 = inst_start; + local target:4 = software_udf(tmp:4, excaddr); + goto [target]; +} + +@endif # VERSION_5 + +:bl^ItCond ThAddr24 is TMode=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=1) & ThAddr24 +{ + build ItCond; + lr = inst_next|1; + SetThumbMode(1); + call ThAddr24; +} + +@ifndef VERSION_6T2 + +:bl^ItCond "#"^off is TMode=1 & ItCond & op11=0x1e & soffset11 [ off = inst_start + 4 + (soffset11 << 12); ] +{ + build ItCond; + lr = off:4; +} + +:bl^ItCond "#"^off is TMode=1 & ItCond & op11=0x1f & offset11 [ off = offset11 << 1; ] +{ + build ItCond; + local dest = lr + off:4; + lr = inst_next|1; + SetThumbMode(1); + goto [dest]; +} + +:blx^ItCond "#"^off is TMode=1 & ItCond & op11=0x1d & offset11 & thc0000=0 [ off = offset11 << 1; ] +{ + build ItCond; + local dest = (lr & (~0x3)) + off:4; + lr = inst_next|1; + SetThumbMode(0); + call [dest]; +} +@endif + +:bl^ItCond ThAddr24 is TMode=1 & CALLoverride=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=1) & ThAddr24 +{ + build ItCond; + lr = inst_next|1; + SetThumbMode(1); + goto ThAddr24; +} + +bxns: "" is thc0003 { } +bxns: "ns" is thc0002=0b100 { } + +@if defined(VERSION_5) + +:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & (op11=0x1e;part2op=0x1d) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ] +{ + build ItCond; + lr = inst_next|1; + SetThumbMode(0); + call ThArmAddr23; + # Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1; +} + +:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & CALLoverride=1 & (op11=0x1e;part2op=0x1d) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ] +{ + build ItCond; + lr = inst_next|1; + SetThumbMode(0); + goto ThArmAddr23; +} + +:blx^ItCond ThArmAddr23 is TMode=1 & ItCond & (op11=0x1e; part2c1415=3 & part2c1212=0) & ThArmAddr23 [ TMode=0; globalset(ThArmAddr23,TMode); TMode=1; ] +{ + build ItCond; + lr = inst_next|1; + SetThumbMode(0); + call ThArmAddr23; +} + +:blx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08f & Hrm0305 & bxns +{ + build ItCond; + BXWritePC(Hrm0305); + lr = inst_next|1; + call [pc]; + # Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1; +} + +@endif # VERSION_5 + +:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08e & Hrm0305 & hrm0305=6 & h2=1 & bxns +{ + build ItCond; + BXWritePC(Hrm0305); + return [pc]; +} + +:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & op7=0x08e & Hrm0305 & bxns +{ + build ItCond; + BXWritePC(Hrm0305); + goto [pc]; +} + +:bx^bxns^ItCond Hrm0305 is TMode=1 & ItCond & LRset=1 & op7=0x08e & Hrm0305 & bxns [ LRset=0; TMode=1; globalset(inst_next,LRset); globalset(inst_next,TMode); ] +{ + build ItCond; + BXWritePC(Hrm0305); + call [pc]; + # Don't set this, assume return will set for emulation. Was screwing up decompiler. TB = 1; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:bxj^ItCond Rn0003 is TMode=1 & ItCond & op4=0xf3c & Rn0003; op0=0x8f00 +{ + build ItCond; + success:1 = jazelle_branch(); + if (success) goto ; + SetThumbMode( (Rn0003&0x00000001)!=0 ); + local tmp=Rn0003&0xfffffffe; + goto [tmp]; + +} # Optional change to THUMB + +@endif # VERSION_6T2 || VERSION_7 + +:cbnz^ItCond Rn0002,Addr5 is TMode=1 & ItCond & op12=0xb & thc1111=1 & thc1010=0 & thc0808=1 & Rn0002 & Addr5 +{ + build ItCond; + local tmp = Rn0002 != 0; + if (tmp) goto Addr5; +} + +:cbz^ItCond Rn0002,Addr5 is TMode=1 & ItCond & op12=0xb & thc1111=0 & thc1010=0 & thc0808=1 & Rn0002 & Addr5 +{ + build ItCond; + local tmp = Rn0002 == 0; + if (tmp) goto Addr5; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:cdp^ItCond thcpn,thopcode1,thCRd,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thopcode1 & thCRn; thCRd & thcpn & thopcode2 & thc0404=0 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thopcode1; + t_op2:4 = thopcode2; + coprocessor_function(t_cpn,t_op1,t_op2,thCRd,thCRn,thCRm); +} + +:cdp2^ItCond thcpn,thopcode1,thCRd,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thopcode1 & thCRn; thCRd & thcpn & thopcode2 & thc0404=0 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thopcode1; + t_op2:4 = thopcode2; + coprocessor_function2(t_cpn,t_op1,t_op2,thCRd,thCRn,thCRm); +} + +define pcodeop IndexCheck; + +:chka^ItCond Hrn0002,Rm0306 is TMode=1 & ItCond & TEEMode=1 & op8=0xca & Rm0306 & Hrn0002 +{ + build ItCond; + local tmp = Hrn0002 <= Rm0306; + if (!tmp) goto inst_next; + lr = inst_next|1; + IndexCheck(); +} + +:clrex^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f2f +{ + build ItCond; + ClearExclusiveLocal(); +} + +:clz^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfab & Rm0003; op12=15 & Rd0811 +{ + build ItCond; + Rd0811 = count_leading_zeroes(Rm0003); +} + +:cmn^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thc0404=1 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12 +{ + build ItCond; + th_addflags(Rn0003,ThumbExpandImm12); + local tmp = Rn0003 + ThumbExpandImm12; + resflags(tmp); + th_affectflags(); +} + +:cmn^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeb1 & Rn0003; thc1515=0 & thc0811=15 & thshift2 +{ + build ItCond; + build thshift2; + th_addflags(Rn0003,thshift2); + local tmp = Rn0003+thshift2; + resflags(tmp); + th_affectflags(); +} + +@endif # VERSION_6T2 || VERSION_7 + +:cmn^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x10b & Rm0305 & Rn0002 +{ + build ItCond; + th_addflags(Rn0002,Rm0305); + local tmp = Rn0002 + Rm0305; + resflags(tmp); + th_affectflags(); +} + +:cmp^ItCond Rn0810,Immed8 is TMode=1 & ItCond & op11=5 & Rn0810 & Immed8 +{ + build ItCond; + th_subflags(Rn0810,Immed8); + local tmp = Rn0810 - Immed8; + resflags(tmp); + th_affectflags(); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:cmp^ItCond^".w" Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & thc0404=1 & sop0508=13 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12 +{ + build ItCond; + th_subflags(Rn0003,ThumbExpandImm12); + local tmp = Rn0003 - ThumbExpandImm12; + resflags(tmp); + th_affectflags(); +} + +:cmp^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op4=0xebb & Rn0003; thc1515=0 & thc0811=15 & thshift2 +{ + build ItCond; + th_subflags(Rn0003,thshift2); + local tmp = Rn0003 - thshift2; + resflags(tmp); + th_affectflags(); +} + +@endif # VERSION_6T2 || VERSION_7 + +:cmp^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x10a & Rm0305 & Rn0002 +{ + build ItCond; + th_subflags(Rn0002,Rm0305); + local tmp = Rn0002 - Rm0305; + resflags(tmp); + th_affectflags(); +} + +:cmp^ItCond Hrn0002,Hrm0305 is TMode=1 & ItCond & op8=0x45 & Hrm0305 & Hrn0002 +{ + build ItCond; + th_subflags(Hrn0002,Hrm0305); + local tmp = Hrn0002 - Hrm0305; + resflags(tmp); + th_affectflags(); +} + +@if defined(VERSION_6) + +aflag: "a" is thc0202=1 & thc0404=0 { enableDataAbortInterrupts(); } +aflag: "a" is thc0202=1 { disableDataAbortInterrupts(); } +aflag: is thc0202=0 { } + +iflag: "i" is thc0101=1 & thc0404=0 { enableIRQinterrupts(); } # 7M: set primask +iflag: "i" is thc0101=1 { disableIRQinterrupts(); } # 7M: clear primask +iflag: is thc0101=0 { } + +fflag: "f" is thc0000=1 & thc0404=0 { enableFIQinterrupts(); } # 7M: set faultmask +fflag: "f" is thc0000=1 { disableFIQinterrupts(); } # 7M: clear faultmask +fflag: is thc0000=0 { } + +iflags: aflag^iflag^fflag is aflag & iflag & fflag { } + +:cpsie^ItCond iflags is TMode=1 & ItCond & op8=0xb6 & sop0507=3 & thc0303=0 & iflags & thc0404=0 +{ + build ItCond; + build iflags; + # see iflags for semantics +} + +:cpsid^ItCond iflags is TMode=1 & ItCond & op8=0xb6 & sop0507=3 & thc0303=0 & iflags & thc0404=1 +{ + build ItCond; + build iflags; + # see iflags for semantics +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +# For SCR 11074, implement the "Encoding T2" 32-bit Thumb-2 cps change processor state instruction +# Note the manual says there are no conditions on this insn +# +th2_aflag: "a" is thc0707=1 & thc0910=0x2 { enableDataAbortInterrupts(); } +th2_aflag: "a" is thc0707=1 { disableDataAbortInterrupts(); } +th2_aflag: is thc0707=0 { } + +th2_iflag: "i" is thc0606=1 & thc0910=0x2 { enableIRQinterrupts(); } # 7M: set primask +th2_iflag: "i" is thc0606=1 { disableIRQinterrupts(); } # 7M: clear primask +th2_iflag: is thc0606=0 { } + +th2_fflag: "f" is thc0505=1 & thc0910=0 { enableFIQinterrupts(); } # 7M: set faultmask +th2_fflag: "f" is thc0505=1 { disableFIQinterrupts(); } # 7M: clear faultmask +th2_fflag: is thc0505=0 { } + +th2_iflags: th2_aflag^th2_iflag^th2_fflag is th2_aflag & th2_iflag & th2_fflag { } + +th2_SetMode: "#"^16 is thc0004=0x10 { setUserMode(); } +th2_SetMode: "#"^17 is thc0004=0x11 { setFIQMode(); } +th2_SetMode: "#"^18 is thc0004=0x12 { setIRQMode(); } +th2_SetMode: "#"^19 is thc0004=0x13 { setSupervisorMode(); } +th2_SetMode: "#"^22 is thc0004=0x16 { setMonitorMode(); } +th2_SetMode: "#"^23 is thc0004=0x17 { setAbortMode(); } +th2_SetMode: "#"^27 is thc0004=0x1b { setUndefinedMode(); } +th2_SetMode: "#"^31 is thc0004=0x1f { setSystemMode(); } + +# 11110 0 1110 1 0 1111 10 0 0 0 +:cpsie th2_iflags, th2_SetMode is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ; + thc0910=0x2 & th2_SetMode & op11=0x10 & th2_iflags +{ + build th2_iflags; +} + +:cpsid th2_iflags, th2_SetMode is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ; + thc0910=0x3 & th2_SetMode & op11=0x10 & th2_iflags +{ + build th2_iflags; +} + +:cps th2_SetMode is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2imm6=0x2f ; + thc0808=0x1 & th2_SetMode & op11=0x10 +{ +} + +@endif # (VERSION_6T2) || defined(VERSION_7) + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:dbg^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3af; op4=0x80f & thc0004 +{ +@if defined(VERSION_7) + HintDebug(thc0004:1); +@endif # VERSION_7 +} + +@if defined(VERSION_7) +:dmb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f5 & thc0004 +{ + DataMemoryBarrier(thc0004:1); +} + +:dsb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f4 & thc0004 +{ + DataSynchronizationBarrier(thc0004:1); +} +@endif + +:eor^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=4 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + Rd0811 = Rn0003 ^ ThumbExpandImm12; + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:eor^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=4 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + Rd0811 = Rn0003 ^ thshift2; + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + + +:enterx^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f1f [ TEEMode=1; globalset(inst_next,TEEMode); ] +{ + build ItCond; +} + +:leavex^ItCond is TMode=1 & ItCond & op0=0xf3bf; op0=0x8f0f [ TEEMode=0; globalset(inst_next,TEEMode); ] +{ + build ItCond; +} + +@endif # VERSION_6T2 || VERSION_7 + + +:eor^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x101 & Rm0305 & Rd0002 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rd0002 ^ Rm0305; + resflags(Rd0002); + build CheckInIT_ZN; +} + +@if defined(VERSION_7) + +:hb^ItCond "#"^immed8 is TMode=1 & ItCond & TEEMode=1 & op9=0x61 & immed8 +{ + build ItCond; +} + + +:isb^ItCond "#"^thc0004 is TMode=1 & ItCond & op0=0xf3bf; op4=0x8f6 & thc0004 +{ + InstructionSynchronizationBarrier(thc0004:1); +} + +@endif # VERSION_7 + +@if defined(VERSION_8) + +# F5.1.178 p2969 SEVL T1 variant +:sevl + is TMode=1 & op0=0b1011111101010000 + & ItCond + { + build ItCond; + SendEvent(); + } + +@endif # VERSION_8 + +@if defined(VERSION_6T2) || defined(VERSION_7) +X: "t" is TMode=1 & ((thc0404=1 & thc0303=1) | (thc0404=0 & thc0303=0)) & (thc0202=1 | thc0101=1 | thc0000=1) { } +X: "e" is TMode=1 & ((thc0404=1 & thc0303=0) | (thc0404=0 & thc0303=1)) & (thc0202=1 | thc0101=1 | thc0000=1) { } +X: "" is TMode=1 & thc0404 & thc0303 & (thc0202=0 & thc0101=0 & thc0000=0) { } +Y: "t" is TMode=1 & ((thc0404=1 & thc0202=1) | (thc0404=0 & thc0202=0)) & (thc0101=1 | thc0000=1) { } +Y: "e" is TMode=1 & ((thc0404=1 & thc0202=0) | (thc0404=0 & thc0202=1)) & (thc0101=1 | thc0000=1) { } +Y: "" is TMode=1 & thc0404 & thc0202 & (thc0101=0 & thc0000=0) { } +Z: "t" is TMode=1 & ((thc0404=1 & thc0101=1) | (thc0404=0 & thc0101=0)) & (thc0000=1) { } +Z: "e" is TMode=1 & ((thc0404=1 & thc0101=0) | (thc0404=0 & thc0101=1)) & (thc0000=1) { } +Z: "" is TMode=1 & thc0404 & thc0101 & (thc0000=0) { } + +XYZ: is TMode=1 & sop0003=8 { } +XYZ: X^Y^Z is TMode=1 & X & Y & Z { } + + +:it^XYZ it_thfcc is TMode=1 & op8=0xbf & XYZ & $(IT_THFCC) & thc0507 & thc0004 + [ itmode=0; cond_base = thc0507; cond_shft=thc0004; globalset(inst_next,condit); ] +{ + # just sets up the condition and If Then/Else mask +} + +:ldc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=1; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_load(t_cpn,thCRd,taddrmode5); +} + +:ldcl^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=1 & thL4=1; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_loadlong(t_cpn,thCRd,taddrmode5); +} + +:ldc2^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=0 & thL4=1; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_load(t_cpn,thCRd,taddrmode5); +} + +:ldc2l^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=1 & thL4=1; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_loadlong(t_cpn,thCRd,taddrmode5); +} + +@endif # VERSION_6T2 || VERSION_7 + +:ldmia^ItCond Rn_exclaim,ldbrace is TMode=1 & ItCond & op11=0x19 & Rn_exclaim & ldbrace & Rn_exclaim_WB +{ + build ItCond; + build Rn_exclaim; + build ldbrace; + build Rn_exclaim_WB; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:ldm^ItCond^".w" Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=1 & Rn0003; thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thldrlist_inc; +} + +:ldm^ItCond^".w" Rn0003!,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=1 & Rn0003; thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thldrlist_inc; + Rn0003 = mult_addr; +} + +:ldm^ItCond Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=1 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thldrlist_inc; + LoadWritePC(pc); + goto [pc]; +} + +:ldm^ItCond^".w" Rn0003,thldrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=1 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thldrlist_inc; + Rn0003 = mult_addr; + LoadWritePC(pc); + goto [pc]; +} + + +:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe91 & Rn0003; thc1313=0 & thldrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thldrlist_dec; +} + +:ldmdb^ItCond Rn0003!,thldrlist_dec is TMode=1 & ItCond & op4=0xe93 & Rn0003; thc1313=0 & thldrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thldrlist_dec; + Rn0003 = mult_addr + 4; +} + +:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe91 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thldrlist_dec; + LoadWritePC(pc); + goto [pc]; +} + +:ldmdb^ItCond Rn0003,thldrlist_dec is TMode=1 & ItCond & op4=0xe93 & Rn0003; thc1515=1 & thc1313=0 & thldrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thldrlist_dec; + Rn0003 = mult_addr + 4; + LoadWritePC(pc); + goto [pc]; +} + +@endif # VERSION_6T2 || VERSION_7 + +:ldr^ItCond Rd0002,RnIndirect4 is TMode=1 & ItCond & op11=0xd & RnIndirect4 & Rd0002 +{ + build ItCond; + build RnIndirect4; + Rd0002 = *RnIndirect4; +} + +:ldr^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2c & RnRmIndirect & Rd0002 +{ + build ItCond; + build RnRmIndirect; + Rd0002 = *RnRmIndirect; +} + +:ldr^ItCond Rd0810,Pcrel8Indirect is TMode=1 & ItCond & op11=9 & Pcrel8Indirect & Rd0810 +{ + build ItCond; + build Pcrel8Indirect; + Rd0810 = Pcrel8Indirect; +} + + # Note: NO '*' IS INTENTIONAL +:ldr^ItCond Rd0810,Sprel8Indirect is TMode=1 & ItCond & op11=0x13 & Sprel8Indirect & Rd0810 +{ + build ItCond; + build Sprel8Indirect; + Rd0810 = *Sprel8Indirect; +} + +:ldrb^ItCond Rd0002,RnIndirect1 is TMode=1 & ItCond & op11=0xf & RnIndirect1 & Rd0002 +{ + build ItCond; + build RnIndirect1; + Rd0002 = zext( *:1 RnIndirect1 ); +} + +:ldrb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2e & RnRmIndirect & Rd0002 +{ + build ItCond; + build RnRmIndirect; + Rd0002 = zext( *:1 RnRmIndirect); +} + +:ldrh^ItCond Rd0002,RnIndirect2 is TMode=1 & ItCond & op11=0x11 & RnIndirect2 & Rd0002 +{ + build ItCond; + build RnIndirect2; + Rd0002 = zext( *:2 RnIndirect2); +} + +:ldrh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2d & RnRmIndirect & Rd0002 +{ + build ItCond; + build RnRmIndirect; + Rd0002 = zext( *:2 RnRmIndirect); +} + +:ldrsb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2b & RnRmIndirect & Rd0002 +{ + build ItCond; + build RnRmIndirect; + Rd0002 = sext( *:1 RnRmIndirect); +} + +:ldrsh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2f & RnRmIndirect & Rd0002 +{ + build ItCond; + build RnRmIndirect; + Rd0002 = sext( *:2 RnRmIndirect); +} + +define pcodeop ExclusiveAccess; + +@if defined(VERSION_7) + +:ldrexb^ItCond Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & thc0811=15 & thc0407=4 & thc0003=15 +{ + build ItCond; + local tmp = Rn0003; + ExclusiveAccess(tmp); + val:1 = *tmp; + Rt1215 = zext(val); +} + +:ldrexh^ItCond Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & thc0811=15 & thc0407=5 & thc0003=15 +{ + build ItCond; + local tmp = Rn0003; + ExclusiveAccess(tmp); + val:2 = *tmp; + Rt1215 = zext(val); +} + +:ldrexd^ItCond Rt1215,Rt0811,[Rn0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; Rt1215 & Rt0811 & thc0407=7 & thc0003=15 +{ + build ItCond; + local tmp = Rn0003; + ExclusiveAccess(tmp); + val1:4 = *tmp; + val2:4 = *(tmp + 4); + Rt1215 = val1; + Rt0811 = val2; +} + +@endif # VERSION_7 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:ldrex^ItCond Rt1215,[Rn0003,Immed8_4] is TMode=1 & ItCond & op4=0xe85 & Rn0003; Rt1215 & thc0811=15 & Immed8_4 +{ + build ItCond; + local tmp = Rn0003 + Immed8_4; + ExclusiveAccess(tmp); + Rt1215 = *tmp; +} + + +:ldr^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8d; Rt1215 & RtGotoCheck) & RnIndirect12 +{ + build ItCond; + build RnIndirect12; + Rt1215 = *RnIndirect12; + build RtGotoCheck; +} + +:ldr^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf85; Rt1215 & thc1111=1 & RtGotoCheck) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + Rt1215 = *RnIndirectPUW; + build RtGotoCheck; +} + +:ldr^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf8d & sop0003=15; Rt1215 & RtGotoCheck) & PcrelOffset12 +{ + build ItCond; + build PcrelOffset12; + Rt1215 = PcrelOffset12:4; + build RtGotoCheck; +} + +# overlaps pattern with next ldr intruction, must occur first +:ldr^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf85 & sop0003=15; Rt1215 & RtGotoCheck) & PcrelOffset12 +{ + build ItCond; + build PcrelOffset12; + Rt1215 = PcrelOffset12:4; + build RtGotoCheck; +} + +:ldr^ItCond^".w" Rt1215,[Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & RtGotoCheck & thc1111=0 & sop0610=0 & thc0405=0 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + Rm0003; + Rt1215 = *tmp; + build RtGotoCheck; +} + +:ldr^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & RtGotoCheck & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + Rt1215 = *tmp; + build RtGotoCheck; +} + +:ldrb^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf89; Rt1215) & RnIndirect12 +{ + build ItCond; + build RnIndirect12; + tmp:1 = *RnIndirect12; + Rt1215 = zext(tmp); +} + +:ldrb^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf81; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + tmp:1 = *RnIndirectPUW; + Rt1215 = zext(tmp); +} + +:ldrb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf89 & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + build PcrelOffset12; + tmp:1 = PcrelOffset12:1; + Rt1215 = zext(tmp); +} +:ldrb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf81 & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + build PcrelOffset12; + tmp:1 = PcrelOffset12:1; + Rt1215 = zext(tmp); +} + +:ldrb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf81 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + val:1 = *tmp; + Rt1215 = zext(val); +} + +:ldrbt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf81 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + val:1 = *tmp; + Rt1215 = zext(val); +} + +:ldrd^ItCond Rt1215,Rt0811,RnIndirectPUW1 is TMode=1 & ItCond & (op9=0x74 & thc0606=1 & thc0404=1 & Rn0003; Rt1215 & Rt0811) & $(RN_INDIRECT_PUW1) +{ + build ItCond; + build RnIndirectPUW1; + Rt1215 = *RnIndirectPUW1; + Rt0811 = *(RnIndirectPUW1+4); +} + +:ldrd^ItCond Rt1215,Rt0811,Pcrel8_s8 is TMode=1 & ItCond & op9=0x74 & thc0606=1 & thc0404=1 & sop0003=15; Rt1215 & Rt0811 & Pcrel8_s8 +{ + build ItCond; + build Pcrel8_s8; + local val = Pcrel8_s8; + Rt1215 = val(4); + Rt0811 = val(0); +} + +:ldrh.w^ItCond Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8B; Rt1215) & RnIndirect12 +{ + build ItCond; + build RnIndirect12; + tmp:2 = *RnIndirect12; + Rt1215 = zext(tmp); +} + +:ldrh^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf83; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + tmp:2 = *RnIndirectPUW; + Rt1215 = zext(tmp); +} + +:ldrh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf83 & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + local tmp = PcrelOffset12:2; + Rt1215 = zext(tmp); +} +:ldrh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op4=0xf8b & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + tmp:2 = PcrelOffset12:2; + Rt1215 = zext(tmp); +} + +:ldrh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf83 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + val:2 = *tmp; + Rt1215 = zext(val); +} + +:ldrht^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf83 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + val:2 = *tmp; + Rt1215 = zext(val); +} + +:ldrsb^ItCond".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf99; Rt1215) & RnIndirect12 +{ + build ItCond; + tmp:1 = *RnIndirect12; + Rt1215 = sext(tmp); +} + +:ldrsb^ItCond".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf91; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + tmp:1 = *RnIndirectPUW; + Rt1215 = sext(tmp); +} + +:ldrsb^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=0 & thc0404=1 & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + tmp:1 = *PcrelOffset12; + Rt1215 = sext(tmp); +} + +:ldrsb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf91 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + val:1 = *tmp; + Rt1215 = sext(val); +} + +:ldrsbt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf91 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + val:1 = *tmp; + Rt1215 = sext(val); +} + +:ldrsh^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf9B; Rt1215) & RnIndirect12 +{ + build ItCond; + tmp:2 = *RnIndirect12; + Rt1215 = sext(tmp); +} + +:ldrsh^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf93; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + tmp:2 = *RnIndirectPUW; + Rt1215 = sext(tmp); +} + +:ldrsh^ItCond^".w" Rt1215,PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=1 & thc0404=1 & sop0003=15; Rt1215) & PcrelOffset12 +{ + build ItCond; + build PcrelOffset12; + tmp:2 = *PcrelOffset12; + Rt1215 = sext(tmp); +} + +:ldrsh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf93 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + val:2 = *tmp; + Rt1215 = sext(val); +} + +:ldrsht^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf93 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + val:2 = *tmp; + Rt1215 = sext(val); +} + +:ldrt^ItCond^".w" Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf85 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + Rt1215 = *tmp; +} + +@endif # VERSION_6T2 || VERSION_7 + +macro th_set_carry_for_lsl(op1,shift_count) { + local bit = (op1 << (shift_count-1)) & 0x80000000; + tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0)); +} + +:lsl^CheckInIT_CZN^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=0x0 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN +{ + build ItCond; + th_set_carry_for_lsl(Rm0305,Immed5); + Rd0002 = Rm0305 << Immed5; + resflags(Rd0002); + build CheckInIT_CZN; +} + +:lsl^CheckInIT_CZN^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x102 & Rs0305 & Rd0002 & CheckInIT_CZN +{ + build ItCond; + local shift_count = Rs0305 & 0xff; + th_set_carry_for_lsl(Rd0002,shift_count); + Rd0002 = Rd0002 << shift_count; + resflags(Rd0002); + build CheckInIT_CZN; +} + +macro th_set_carry_for_lsr(op1,shift_count) { + local bit = (op1 >> (shift_count-1)) & 1; + tmpCY = ((shift_count == 0) && CY) || ((shift_count != 0) && (bit != 0)); +} + +#note that this is a special case where immed5 = 0, which corresponds to a shift amount of 32 +:lsr^CheckInIT_CZN^ItCond Rd0002,Rm0305,"#0x20" is TMode=1 & ItCond & op11=1 & Immed5 & Rm0305 & Rd0002 & immed5=0 & CheckInIT_CZN +{ + build ItCond; + th_set_carry_for_lsr(Rm0305,32:1); + Rd0002 = Rm0305 >> 32; + resflags(Rd0002); + build CheckInIT_CZN; +} + +:lsr^CheckInIT_CZN^ItCond Rd0002,Rm0305,Immed5 is TMode=1 & ItCond & op11=1 & Immed5 & Rm0305 & Rd0002 & CheckInIT_CZN +{ + build ItCond; + local shift_amount = Immed5; + th_set_carry_for_lsr(Rm0305,shift_amount); + Rd0002 = Rm0305 >> Immed5; + resflags(Rd0002); + build CheckInIT_CZN; +} + +:lsr^CheckInIT_CZN^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x103 & Rd0002 & Rs0305 & CheckInIT_CZN +{ + build ItCond; + local shift_amount = (Rs0305 & 0xff); + th_set_carry_for_lsr(Rd0002,shift_amount); + Rd0002 = Rd0002 >> (Rs0305 & 0xff); + resflags(Rd0002); + build CheckInIT_CZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:lsl^thSBIT_CZN^ItCond^".w" Rd0811,Rm0003,thLsbImm is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=15; thc1515=0 & Rd0811 & thc0405=0 & Rm0003 & thLsbImm +{ + build ItCond; + th_set_carry_for_lsl(Rm0003,thLsbImm); + Rd0811 = Rm0003 << thLsbImm; + resflags(Rd0811); + build thSBIT_CZN; +} + +:lsl^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=0 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + local shift_amount = (Rm0003 & 0xff); + th_set_carry_for_lsl(Rn0003,shift_amount); + Rd0811 = Rn0003 << (shift_amount); + resflags(Rd0811); + build thSBIT_CZN; +} + +:lsr^thSBIT_CZN^ItCond^".w" Rd0811,Rm0003,thLsbImm is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & sop0003=15; thc1515=0 & Rd0811 & thc0405=1 & Rm0003 & thLsbImm +{ + build ItCond; + th_set_carry_for_lsr(Rm0003,thLsbImm); + Rd0811 = Rm0003 >> thLsbImm; + resflags(Rd0811); + build thSBIT_CZN; +} + +:lsr^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op11=0x1f & thc0910=1 & sop0508=1 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + local shift_amount = Rm0003 & 0xff; + th_set_carry_for_lsr(Rn0003,shift_amount); + Rd0811 = Rn0003 >> shift_amount; + resflags(Rd0811); + build thSBIT_CZN; +} + + +@endif # VERSION_6T2 || VERSION_7 + +:mcr^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=0 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thc0507; + t_op2:4 = thopcode2; + coprocessor_moveto(t_cpn,t_op1,t_op2,Rt1215,thCRn,thCRm); +} + +:mcr2^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=0 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thc0507; + t_op2:4 = thopcode2; + coprocessor_moveto(t_cpn,t_op1,t_op2,Rt1215,thCRn,thCRm); +} + +:mcrr^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xec4 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op:4 = thopcode1; + coprocessor_moveto2(t_cpn,t_op,Rt1215,Rn0003,thCRm); +} + +:mcrr^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xfc4 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op:4 = thopcode1; + coprocessor_moveto2(t_cpn,t_op,Rt1215,Rn0003,thCRm); +} + + +:mov^CheckInIT_ZN^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=4 & Rd0810 & Immed8 & CheckInIT_ZN +{ + build ItCond; + Rd0810 = Immed8; + resflags(Rd0810); + build CheckInIT_ZN; +} + +:mov^CheckInIT_ZN^ItCond Rd0002,Rn0305 is TMode=1 & ItCond & op6=0x000 & Rn0305 & Rd0002 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rn0305; + resflags(Rd0002); + build CheckInIT_ZN; +} + +:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & Hrd0002 +{ + build ItCond; + Hrd0002 = Hrm0305; +} + +:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & Hrd0002 & hrd0002=7 & h1=1 +{ + build ItCond; + dest:4 = Hrm0305; + BranchWritePC(dest); + goto [pc]; +} + +:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & rm0306=14 & Hrd0002 & hrd0002=7 & h1=1 +{ + build ItCond; + dest:4 = Hrm0305; + BranchWritePC(dest); + return [pc]; +} + +:mov^ItCond Hrd0002,Hrm0305 is TMode=1 & ItCond & op8=0x46 & Hrm0305 & hrm0305=7 & Hrd0002 & hrd0002=6 & h1=1 [ LRset=1; TMode=1; globalset(inst_next,LRset); globalset(inst_next,TMode); ] +{ + build ItCond; + Hrd0002 = Hrm0305; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:mov^thSBIT_ZN^ItCond^".w" Rd0811,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=2 & thSBIT_ZN & sop0003=15; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + Rd0811 = ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_ZN; +} + +:movw^ItCond Rd0811,Immed16 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=2 & thc0404=0; thc1515=0 & Rd0811) & Immed16 +{ + build ItCond; + Rd0811 = zext(Immed16); + resflags(Rd0811); +} + +:mov^thSBIT_ZN^ItCond^".w" Rd0811,Rm0003 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_ZN & sop0003=15; op12=0 & Rd0811 & thc0407=0 & Rm0003 +{ + build ItCond; + Rd0811 = Rm0003; + resflags(Rd0811); + build thSBIT_ZN; +} + +:movt^ItCond Rd0811,Immed16 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=6 & thc0404=0; thc1515=0 & Rd0811) & Immed16 +{ + build ItCond; + Rd0811 = (zext(Immed16) << 16) | (Rd0811 & 0xffff); +} + + +:mrc^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xee & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thc0507; + t_op2:4 = thopcode2; + Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm); +} + +:mrc2^ItCond thcpn,thc0507,Rt1215,thCRn,thCRm,thopcode2 is TMode=1 & ItCond & op8=0xfe & thc0507 & thc0404=1 & thCRn; Rt1215 & thcpn & thopcode2 & thc0404=1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op1:4 = thc0507; + t_op2:4 = thopcode2; + Rt1215 = coprocessor_movefromRt(t_cpn,t_op1,t_op2,thCRn,thCRm); +} + +:mrrc^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xec5 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op:4 = thopcode1; + Rt1215 = coprocessor_movefromRt(t_cpn,t_op,thCRm); + Rn0003 = coprocessor_movefromRt2(t_cpn,t_op,thCRm); +} + +:mrrc2^ItCond thcpn,thopcode1,Rt1215,Rn0003,thCRm is TMode=1 & ItCond & op4=0xfc5 & Rn0003; Rt1215 & thcpn & thopcode1 & thCRm +{ + build ItCond; + t_cpn:4 = thcpn; + t_op:4 = thopcode1; + Rt1215 = coprocessor_movefromRt(t_cpn,t_op,thCRm); + Rn0003 = coprocessor_movefromRt2(t_cpn,t_op,thCRm); +} + +macro readAPSR(r) { +# TODO: GE bits have not been included + r = r | zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27; +} + +macro writeAPSR(r) { +# TODO: GE bits have not been included + local tmp = r >> 27 & 0x1f; + Q = ((tmp ) & 0x1) != 0; + OV = ((tmp >> 1) & 0x1) != 0; + CY = ((tmp >> 2) & 0x1) != 0; + ZR = ((tmp >> 3) & 0x1) != 0; + NG = ((tmp >> 4) & 0x1) != 0; +} + +@if defined(VERSION_7M) + +define pcodeop getMainStackPointer; +define pcodeop getProcessStackPointer; +define pcodeop getBasePriority; +define pcodeop getCurrentExceptionNumber; + +mrsipsr: "i" is thc0000=1 & Rd0811 { + b:1 = isCurrentModePrivileged(); + if (!b) goto ; + ipsr:4 = getCurrentExceptionNumber(); + Rd0811 = Rd0811 | (ipsr & 0x1f); + +} +mrsipsr: is thc0000=0 { } +mrsepsr: "e" is thc0101=1 { } +mrsepsr: is thc0101=0 { } +mrsapsr: is thc0202=1 { } +mrsapsr: "a" is thc0202=0 & Rd0811 { readAPSR(Rd0811); } + +mrspsr: mrsipsr^mrsepsr^mrsapsr^"psr" is mrsipsr & mrsepsr & mrsapsr & Rd0811 { + Rd0811 = 0; + build mrsapsr; + build mrsipsr; +} +mrspsr: "xpsr" is sysm02=3 & mrsipsr & mrsepsr & mrsapsr & Rd0811 { + Rd0811 = 0; + build mrsapsr; + build mrsipsr; +} + +:mrs^ItCond Rd0811,mrspsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm37=0 & mrspsr +{ + build ItCond; + build mrspsr; +} + +msp: "msp" is epsilon {} + +:mrs^ItCond Rd0811,msp is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=8 & msp +{ + build ItCond; + Rd0811 = getMainStackPointer(); +} + +psp: "psp" is epsilon {} + +:mrs^ItCond Rd0811,psp is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=9 & psp +{ + build ItCond; + Rd0811 = getProcessStackPointer(); +} + +primask: "primask" is epsilon {} + +:mrs^ItCond Rd0811,primask is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=16 & primask +{ + build ItCond; + Rd0811 = 0; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + Rd0811 = isIRQinterruptsEnabled(); # should reflect primask register/bit +} + +basepri: "basepri" is epsilon {} + +:mrs^ItCond Rd0811,basepri is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=17 & basepri +{ + build ItCond; + Rd0811 = 0; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + Rd0811 = getBasePriority(); +} + +basepri_max: "basepri_max" is epsilon {} + +:mrs^ItCond Rd0811,basepri_max is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=18 & basepri_max +{ + build ItCond; + Rd0811 = 0; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + Rd0811 = getBasePriority(); +} + +faultmask: "faultmask" is epsilon {} + +:mrs^ItCond Rd0811,faultmask is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=19 & faultmask +{ + build ItCond; + Rd0811 = 0; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + Rd0811 = isFIQinterruptsEnabled(); # should reflect faultmask register/bit +} + +define pcodeop isThreadModePrivileged; +define pcodeop isUsingMainStack; + +control: "control" is epsilon {} + +:mrs^ItCond Rd0811,control is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=20 & control +{ + build ItCond; + notPrivileged:1 = isThreadModePrivileged() != 1:1; + altStackMode:1 = isUsingMainStack() != 1:1; + Rd0811 = zext((altStackMode << 1) | notPrivileged); +} + +@endif + +:mrs^ItCond Rd0811,cpsr is TMode=1 & ItCond & op0=0xf3ef; op12=0x8 & Rd0811 & sysm=0 & cpsr +{ + build ItCond; + tmp:4 = 0; + readAPSR(tmp); + Rd0811 = tmp; +} + +:mrs^ItCond Rd0811,spsr is TMode=1 & ItCond & op0=0xf3ff; op12=0x8 & Rd0811 & sysm=0 & spsr +{ + build ItCond; + Rd0811 = spsr; +} + + +@if defined(VERSION_7M) + +msripsr: "i" is thc0000=1 { } +msripsr: is thc0000=0 { } +msrepsr: "e" is thc0101=1 { } +msrepsr: is thc0101=0 { } +msrapsr: is thc0202=1 { } +msrapsr: "a" is thc0202=0 & Rn0003 { + cpsr = cpsr | (Rn0003 & 0xf8000000); + writeAPSR(cpsr); +} + +msrpsr: msripsr^msrepsr^msrapsr^"psr" is msripsr & msrepsr & msrapsr { + build msrapsr; +} +msrpsr: "xpsr" is sysm02=3 & msrapsr { + build msrapsr; +} + +:msr^ItCond msrpsr,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm37=0 & msrpsr +{ + build ItCond; + build msrpsr; +} + +define pcodeop setMainStackPointer; +define pcodeop setProcessStackPointer; +define pcodeop setBasePriority; + +:msr^ItCond msp,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=8 & msp +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + setMainStackPointer(Rn0003); +} + +:msr^ItCond psp,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=9 & psp +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + setProcessStackPointer(Rn0003); +} + +:msr^ItCond primask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=16 & primask +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + enableIRQinterrupts((Rn0003 & 1) == 1); # should set/clear primask register/bit +} + +:msr^ItCond basepri,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=17 & basepri +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + setBasePriority(Rn0003); +} + +:msr^ItCond basepri_max,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=18 & basepri_max +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + if (Rn0003 == 0) goto inst_next; +# TODO: does the following compare need to be signed?? + cur:4 = getBasePriority(); + if (cur != 0 && Rn0003 >= cur) goto inst_next; + setBasePriority(Rn0003); +} + +:msr^ItCond faultmask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=19 & faultmask +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + enableFIQinterrupts((Rn0003 & 1) == 1); +} + +define pcodeop setStackMode; + +:msr^ItCond control,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & th_psrmask=8 & sysm=20 & control +{ + build ItCond; + b:1 = isCurrentModePrivileged(); + if (!b) goto inst_next; + privileged:1 = (Rn0003 & 1) == 0; + setThreadModePrivileged(privileged); +# TODO: not sure about the following semantics + b = isThreadMode(); + if (!b) goto inst_next; + stackMode:1 = isUsingMainStack() == 1:1; + setStackMode(stackMode); +# TODO: should we set sp ? +} + +@endif + +thpsrmask: is th_psrmask=0 { export 0:4; } +thpsrmask: "_c" is th_psrmask=1 { export 0xff:4; } +thpsrmask: "_x" is th_psrmask=2 { export 0xff00:4; } +thpsrmask: "_cx" is th_psrmask=3 { export 0xffff:4; } +thpsrmask: "_s" is th_psrmask=4 { export 0xff0000:4; } +thpsrmask: "_cs" is th_psrmask=5 { export 0xff00ff:4; } +thpsrmask: "_xs" is th_psrmask=6 { export 0xffff00:4; } +thpsrmask: "_cxs" is th_psrmask=7 { export 0xffffff:4; } +thpsrmask: "_f" is th_psrmask=8 { export 0xff000000:4; } +thpsrmask: "_cf" is th_psrmask=9 { export 0xff0000ff:4; } +thpsrmask: "_xf" is th_psrmask=10 { export 0xff00ff00:4; } +thpsrmask: "_cxf" is th_psrmask=11 { export 0xff00ffff:4; } +thpsrmask: "_sf" is th_psrmask=12 { export 0xffff0000:4; } +thpsrmask: "_csf" is th_psrmask=13 { export 0xffff00ff:4; } +thpsrmask: "_xsf" is th_psrmask=14 { export 0xffffff00:4; } +thpsrmask: "_cxsf" is th_psrmask=15 { export 0xffffffff:4; } + +thcpsrmask: cpsr^thpsrmask is thpsrmask & cpsr { export thpsrmask; } + +:msr^ItCond thcpsrmask,Rn0003 is TMode=1 & ItCond & op4=0xf38 & Rn0003; op12=0x8 & thcpsrmask & thc0007=0 +{ + build ItCond; + build thcpsrmask; + cpsr = (cpsr& ~thcpsrmask) | (Rn0003 & thcpsrmask); + writeAPSR(cpsr); +} + +thspsrmask: spsr^thpsrmask is thpsrmask & spsr { export thpsrmask; } + +:msr^ItCond thspsrmask,Rn0003 is TMode=1 & ItCond & op4=0xf39 & Rn0003; op12=0x8 & thspsrmask & thc0007=0 +{ + build ItCond; + build thspsrmask; + spsr = (spsr& ~thspsrmask) | (Rn0003 & thspsrmask); +} + +:mvn^thSBIT_ZN^ItCond Rd0811,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=3 & thSBIT_ZN & thc0003=15; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + Rd0811 = ~ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_ZN; +} + +:mvn^thSBIT_ZN^ItCond^".w" Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=3 & thSBIT_ZN & thc0003=15; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + Rd0811 = ~thshift2; + resflags(Rd0811); + build thSBIT_ZN; +} + +@endif # VERSION_6T2 || VERSION_7 + +:mul^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10d & Rm0305 & Rd0002 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rm0305 * Rd0002; + resflags(Rd0002); + build CheckInIT_ZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:mla^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + Rd0811 = Rn0003 * Rm0003 + Ra1215; +} + +:mls^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; Ra1215 & Rd0811 & sop0407=1 & Rm0003 +{ + build ItCond; + Rd0811 = Ra1215- Rn0003 * Rm0003; +} + +:mul^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb0 & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + Rd0811 = Rn0003 * Rm0003; +} + +@endif # VERSION_6T2 || VERSION_7 + +:mvn^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10f & Rm0305 & Rd0002 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = ~Rm0305; + resflags(Rd0002); + build CheckInIT_ZN; +} + +:nop^ItCond is TMode=1 & ItCond & op0=0xbf00 +{ +} + +:nop^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8000 +{ +} + +:nop is op0=0x46c0 # This is just like a mov r0 r0 +{ +} + +:orr^CheckInIT_ZN^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x10c & Rm0305 & Rd0002 & CheckInIT_ZN +{ + build ItCond; + Rd0002 = Rd0002 | Rm0305; + resflags(Rd0002); + build CheckInIT_ZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:orn^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=3 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + Rd0811 = Rn0003 | ~(ThumbExpandImm12); + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:orn^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=3 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + Rd0811 = Rn0003 | ~(thshift2); + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:orr^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=2 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + Rd0811 = Rn0003 | ThumbExpandImm12; + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:orr^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + Rd0811 = Rn0003 | thshift2; + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:pkhbt^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeac & Rn0003; thc1515=0 & Rd0811 & thc0505=0 & thc0404=0 & thshift2 +{ + build ItCond; + Rd0811 = (Rn0003 & 0x0000ffff) | (thshift2 & 0xffff0000); + th_logicflags(); + resflags(Rd0811); +} + +:pkhtb^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op4=0xeac & Rn0003; thc1515=0 & Rd0811 & thc0505=1 & thc0404=0 & thshift2 +{ + build ItCond; + Rd0811 = (Rn0003 & 0xffff0000) | (thshift2 & 0x0000ffff); + th_logicflags(); + resflags(Rd0811); +} + +:pld^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op6=0x3e2 & thwbit=0 & thc0404=1 & Rn0003; op12=0xf & offset12 +{ + build ItCond; + addr:4 = Rn0003 + offset12; + HintPreloadData(addr); +} + +:pldw^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op6=0x3e2 & thwbit=1 & thc0404=1 & Rn0003; op12=0xf & offset12 +{ + build ItCond; + addr:4 = Rn0003 + offset12; + HintPreloadDataForWrite(addr); +} + +:pld^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op6=0x3e0 & thwbit=0 & thc0404=1 & Rn0003; op8=0xfc & immed8 +{ + build ItCond; + addr:4 = Rn0003 - immed8; + HintPreloadData(addr); +} + +:pldw^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op6=0x3e0 & thwbit=1 & thc0404=1 & Rn0003; op8=0xfc & immed8 +{ + build ItCond; + addr:4 = Rn0003 - immed8; + HintPreloadDataForWrite(addr); +} + +:pld^ItCond PcrelOffset12 is TMode=1 & ItCond & (op8=0xf8 & thc0506=0 & thc0004=0x1f; thc1215=0xf) & PcrelOffset12 +{ + build ItCond; + HintPreloadData(PcrelOffset12); +} + +:pld^ItCond Rn0003,Rm0003"lsl #"^thc0405 is TMode=1 & ItCond & op6=0x3e0 & thwbit=0 & thc0404=1 & Rn0003; op8=0xf0 & thc0607=0 & thc0405 & Rm0003 +{ + build ItCond; + addr:4 = Rn0003 + (Rm0003 << thc0405); + HintPreloadData(addr); +} + +:pldw^ItCond Rn0003,Rm0003,"lsl #"^thc0405 is TMode=1 & ItCond & op6=0x3e0 & thwbit=1 & thc0404=1 & Rn0003; op8=0xf0 & thc0607=0 & thc0405 & Rm0003 +{ + build ItCond; + addr:4 = Rn0003 + (Rm0003 << thc0405); + HintPreloadDataForWrite(addr); +} + + +:pli^ItCond Rn0003,"#"^offset12 is TMode=1 & ItCond & op4=0xf99 & Rn0003; op12=0xf & offset12 +{ + build ItCond; + addr:4 = Rn0003 + offset12; + HintPreloadInstruction(addr); +} + +:pli^ItCond Rn0003,"#-"^immed8 is TMode=1 & ItCond & op4=0xf91 & Rn0003; op8=0xfc & immed8 +{ + build ItCond; + addr:4 = Rn0003 - immed8; + HintPreloadInstruction(addr); +} + +:pli^ItCond PcrelOffset12 is TMode=1 & ItCond & (op8=0xf9 & thc0506=0 & thc0004=0x1f; thc1215=0xf) & PcrelOffset12 +{ + build ItCond; + HintPreloadInstruction(PcrelOffset12); +} + +:pli^ItCond Rn0003,Rm0003"lsl #"^thc0405 is TMode=1 & ItCond & op4=0xf91 & Rn0003; op6=0x3c0 & thc0405 & Rm0003 +{ + build ItCond; + addr:4 = Rn0003 + (Rm0003 << thc0405); + HintPreloadInstruction(addr); +} + + +@endif # VERSION_6T2 || VERSION_7 + +# +# Removed the masking of the stack pointer on push and pop to ignore the lower 2 bits. +# This isn't really needed for modeling. +# NOTE: It may need to be put back in to model correctly for nasty stack shenanigans. +# +:pop^ItCond ldbrace is TMode=1 & ItCond & op9=0x5e & R=0 & ldbrace +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build ldbrace; + sp = mult_addr; +} + +:pop^ItCond pclbrace is TMode=1 & ItCond & op9=0x5e & R=1 & pclbrace +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build pclbrace; + sp = mult_addr; + LoadWritePC(pc); + return [pc]; +} + +:pop^ItCond thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thldrlist_inc +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build thldrlist_inc; + sp = mult_addr; +} + +:pop^ItCond thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thldrlist_inc & thc1515=1 +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build thldrlist_inc; + sp = mult_addr; + LoadWritePC(pc); + return [pc]; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:pop^ItCond^".w" thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thc1515=0 & thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = sp; + build thldrlist_inc; + sp = mult_addr; +} + +:pop^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf85d; Rt1215 & offset12=0xb04 +{ + build ItCond; + Rt1215 = *sp; + sp=sp+4; +} + +:pop^ItCond^".w" thldrlist_inc is TMode=1 & ItCond & op0=0xe8bd; thc1515=1 & thc1313=0 & thldrlist_inc +{ + build ItCond; + mult_addr = sp; + build thldrlist_inc; + sp = mult_addr; + LoadWritePC(pc); + return [pc]; +} + +:pop^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf85d; Rt1215 & op12=15 & offset12=0xb04 +{ + build ItCond; + dest:4 = *sp; + sp=sp+4; + LoadWritePC(dest); + return [pc]; +} + +:push^ItCond^".w" thstrlist_dec is TMode=1 & ItCond & op0=0xe8ad; thc1515=0 & thc1313=0 & thstrlist_dec +{ + build ItCond; + mult_addr = sp-4; + build thstrlist_dec; + sp = mult_addr + 4; +} + +:push^ItCond^".w" Rt1215 is TMode=1 & ItCond & op0=0xf84d; Rt1215 & offset12=0xd04 +{ + build ItCond; + sp=sp-4; + *sp = Rt1215; +} + +@endif # VERSION_6T2 || VERSION_7 + +:push^ItCond psbrace is TMode=1 & ItCond & op9=0x5a & R=0 & psbrace +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build psbrace; + sp = mult_addr; +} + +:push^ItCond pcpbrace is TMode=1 & ItCond & op9=0x5a & R=1 & pcpbrace +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp; + build pcpbrace; + sp = mult_addr; +} + +:push^ItCond thstrlist_dec is TMode=1 & ItCond & op0=0xe92d; thstrlist_dec +{ + build ItCond; +# mult_addr = sp & 0xfffffffc; + mult_addr = sp-4; + build thstrlist_dec; + sp = mult_addr+4; +} + +@if defined(VERSION_5E) + +:qadd^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x8 & Rm0003 +{ + build ItCond; + local sum1 = Rm0003 + Rn0003; + sum1 = SignedSaturate(sum1,32:2); + Q = SignedDoesSaturate(sum1,32:2); + Rd0811 = sum1; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:qadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local lRn = Rn0003 & 0xffff; + local lRm = Rm0003 & 0xffff; + local uRn = (Rn0003) & 0xffff; + local uRm = (Rm0003 >> 16) & 0xffff; + sum1:2 = lRn:2 + lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 + uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd0811 = (zext(sum2) << 16) | zext(sum1); +} + +:qadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local rn1 = Rn0003 & 0xff; + local rm1 = Rm0003 & 0xff; + local rn2 = (Rn0003 >> 8) & 0xff; + local rm2 = (Rm0003 >> 8) & 0xff; + local rn3 = (Rn0003 >> 16) & 0xff; + local rm3 = (Rm0003 >> 16) & 0xff; + local rn4 = (Rn0003 >> 24) & 0xff; + local rm4 = (Rm0003 >> 24) & 0xff; + sum1:1 = rn1:1 + rm1:1; + sum1 = SignedSaturate(sum1,8:2); + sum2:1 = rn2:1 + rm2:1; + sum2 = SignedSaturate(sum2,8:2); + sum3:1 = rn3:1 + rm3:1; + sum3 = SignedSaturate(sum3,8:2); + sum4:1 = rn4:1 + rm4:1; + sum4 = SignedSaturate(sum4,8:2); + Rd0811 = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +# qaddsubx +:qasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local lRn = Rn0003 & 0xffff; + local lRm = Rm0003 & 0xffff; + local uRn = (Rn0003 >> 16) & 0xffff; + local uRm = (Rm0003 >> 16) & 0xffff; + sum1:2 = lRn:2 - lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 + uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd0811 = (zext(sum2) << 16) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:qdadd^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x9 & Rm0003 +{ + build ItCond; + tmp:4 = Rn0003 * 2; + tmp = SignedSaturate(tmp,32:2); + Q = SignedDoesSaturate(tmp,32:2); + tmp = tmp + Rm0003; + tmp = SignedSaturate(tmp,32:2); + Q = Q | SignedDoesSaturate(tmp,32:2); + Rd0811 = tmp; +} + +:qdsub^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0xb & Rm0003 +{ + build ItCond; + tmp:4 = Rn0003 * 2; + tmp = SignedSaturate(tmp); + Q = SignedDoesSaturate(tmp,32:2); + tmp = Rm0003 - tmp; + tmp = SignedSaturate(tmp,32:2); + Q = Q | SignedDoesSaturate(tmp,32:2); + Rd0811 = tmp; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +# qsubaddx +:qsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local lRn = Rn0003 & 0xffff; + local lRm = Rm0003 & 0xffff; + local uRn = (Rn0003 >> 16) & 0xffff; + local uRm = (Rm0003 >> 16) & 0xffff; + sum1:2 = lRn:2 + lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 - uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd0811 = (zext(sum2) << 16) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:qsub^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0xa & Rm0003 +{ + build ItCond; + tmp:4 = Rm0003 - Rn0003; + tmp = SignedSaturate(tmp,32:2); + Q = SignedDoesSaturate(tmp,32:2); + Rd0811 = tmp; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:qsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local lRn = Rn0003 & 0xffff; + local lRm = Rm0003 & 0xffff; + local uRn = (Rn0003 >> 16) & 0xffff; + local uRm = (Rm0003 >> 16) & 0xffff; + sum1:2 = lRn:2 - lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 - uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd0811 = (zext(sum2) << 16) | zext(sum1); +} + +:qsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x1 & Rm0003 +{ + build ItCond; + local rn1 = Rn0003 & 0xff; + local rm1 = Rm0003 & 0xff; + local rn2 = (Rn0003 >> 8) & 0xff; + local rm2 = (Rm0003 >> 8) & 0xff; + local rn3 = (Rn0003 >> 16) & 0xff; + local rm3 = (Rm0003 >> 16) & 0xff; + local rn4 = (Rn0003 >> 24) & 0xff; + local rm4 = (Rm0003 >> 24) & 0xff; + sum1:1 = rn1:1 - rm1:1; + sum1 = SignedSaturate(sum1,8:2); + sum2:1 = rn2:1 - rm2:1; + sum2 = SignedSaturate(sum2,8:2); + sum3:1 = rn3:1 - rm3:1; + sum3 = SignedSaturate(sum3,8:2); + sum4:1 = rn4:1 - rm4:1; + sum4 = SignedSaturate(sum4,8:2); + Rd0811 = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(THUMB_2) + +# WARNING Rm0003 on the first 2 bytes must be the same value as Rm0003 on the last bytes! +# but there is no easy way to check this now... +:rev^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfa9; op6=0x2e8 & Rd0811 & Rm0003 +{ + build ItCond; + local tmp1 = Rm0003 & 0xff; + local tmp2 = (Rm0003 >> 8) & 0xff; + local tmp3 = (Rm0003 >> 16) & 0xff; + local tmp4 = (Rm0003 >> 24) & 0xff; + Rd0811 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4; +} + +@endif # THUMB_2 + +:rsb^CheckInIT_CZNO^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x109 & Rm0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_subflags0(Rm0305); + Rd0002 = 0-Rm0305; + resflags(Rd0002); + build CheckInIT_CZNO; +} + +@if defined(VERSION_6) + +:rev^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2e8 & Rd0002 & Rm0305 +{ + build ItCond; + local tmp1 = Rm0305 & 0xff; + local tmp2 = (Rm0305 >> 8) & 0xff; + local tmp3 = (Rm0305 >> 16) & 0xff; + local tmp4 = (Rm0305 >> 24) & 0xff; + Rd0002 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4; +} + +:rev16^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2e9 & Rd0002 & Rm0305 +{ + build ItCond; + local tmp1 = Rm0305 & 0xff; + local tmp2 = (Rm0305 >> 8) & 0xff; + local tmp3 = (Rm0305 >> 16) & 0xff; + local tmp4 = (Rm0305 >> 24) & 0xff; + Rd0002 = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2; +} + +:revsh^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x2eb & Rd0002 & Rm0305 +{ + build ItCond; + local tmp1 = Rm0305 & 0xff; + local tmp2 = (Rm0305 >> 8) & 0xff; + local result = (tmp1 << 8) | tmp2; + Rd0002 = sext(result:2); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +macro BitReverse(val) { + tval:1 = val; + result:1 = 0; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + val = result; +} + +:rbit^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=0xa & Rn0003 +{ + build ItCond; + t:4 = Rm0003 & 0xff; + b1:1 = t:1; + t = (Rm0003 >> 8) & 0xff; + b2:1 = t:1; + t = (Rm0003 >> 16) & 0xff; + b3:1 = t:1; + t = (Rm0003 >> 24) & 0xff; + b4:1 = t:1; + BitReverse(b1); + BitReverse(b2); + BitReverse(b3); + BitReverse(b4); + Rd0811 = (zext(b1) << 24) | (zext(b2) << 16) | (zext(b3) << 8) | zext(b4); +} + +:rev^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=8 & Rn0003 +{ + build ItCond; + local tmp1 = Rm0003 & 0xff; + local tmp2 = (Rm0003 >> 8) & 0xff; + local tmp3 = (Rm0003 >> 16) & 0xff; + local tmp4 = (Rm0003 >> 24) & 0xff; + Rd0811 = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4; +} + +:rev16^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=9 & Rn0003 +{ + build ItCond; + local tmp1 = Rm0003 & 0xff; + local tmp2 = (Rm0003 >> 8) & 0xff; + local tmp3 = (Rm0003 >> 16) & 0xff; + local tmp4 = (Rm0003 >> 24) & 0xff; + Rd0811 = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2; +} + +:revsh^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rm0003; op12=0xf & Rd0811 & thc0407=0xb & Rn0003 +{ + build ItCond; + local tmp1 = Rm0003 & 0xff; + local tmp2 = (Rm0003 >> 8) & 0xff; + local result = (tmp1 << 8) | tmp2; + Rd0811 = sext(result:2); +} + +# RFE instructions for Thumb-2 "Encoding T1" and "Encoding T2" on page 1574 +# +:rfedb part2Rd0003 is TMode=1 & part2c0615=0x3a0 & part2c0505=0x0 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000 +{ + # register list is always: pc, cpsr + ptr:4 = part2Rd0003 - 4; + cpsr = *ptr; + ptr = ptr - 4; + dest:4 = *ptr; + BranchWritePC(dest); + return [pc]; +} + +:rfedb part2Rd0003^"!" is TMode=1 & part2c0615=0x3a0 & part2c0505=0x1 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000 +{ + # register list is always: pc, cpsr + ptr:4 = part2Rd0003 - 4; + cpsr = *ptr; + ptr = ptr - 4; + dest:4 = *ptr; + part2Rd0003 = ptr; + BranchWritePC(dest); + return [pc]; +} + +:rfeia part2Rd0003 is TMode=1 & part2c0615=0x3a6 & part2c0505=0x0 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000 +{ + # register list is always: pc, cpsr + ptr:4 = part2Rd0003; + cpsr = *ptr; + ptr = ptr + 4; + dest:4 = *ptr; + BranchWritePC(dest); + return [pc]; +} + +:rfeia part2Rd0003^"!" is TMode=1 & part2c0615=0x3a6 & part2c0505=0x1 & part2c0404=0x1 & part2Rd0003 ; op0=0xc000 +{ + # register list is always: pc, cpsr + ptr:4 = part2Rd0003; + cpsr = *ptr; + ptr = ptr + 4; + dest:4 = *ptr; + part2Rd0003 = ptr + 4; + BranchWritePC(dest); + return [pc]; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + + +:rsb^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=14 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + th_subflags(ThumbExpandImm12,Rn0003); + Rd0811 = ThumbExpandImm12 - Rn0003; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:rsb^thSBIT_CZNO^ItCond Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=14 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + th_subflags(thshift2,Rn0003); + Rd0811 = thshift2 - Rn0003; + resflags(Rd0811); + build thSBIT_CZNO; +} + +@endif # VERSION_6 + +macro th_set_carry_for_ror(result, count) { + local bit = result & 0x80000000; + tmpCY = ((count == 0) && CY) || ((count != 0) && (bit != 0)); +} + +:ror^CheckInIT_CZN^ItCond Rd0002,Rs0305 is TMode=1 & ItCond & op6=0x107 & Rs0305 & Rd0002 & CheckInIT_CZN +{ + build ItCond; + local shift_amount = Rs0305 & 0x1f; + local tmp = (Rd0002 >> shift_amount)|(Rd0002 << (32-shift_amount)); + th_set_carry_for_ror(tmp,Rs0305 & 0xff); + Rd0002 = tmp; + resflags(Rd0002); + build CheckInIT_CZN; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:ror^thSBIT_CZN^ItCond Rd0811,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & thc0003=0xf; thc1515=0 & Rd0811 & thc0405=3 & thshift2 +{ + build ItCond; + Rd0811 = thshift2; + tmpCY = shift_carry; + resflags(Rd0811); + build thSBIT_CZN; +} + +:ror^thSBIT_CZN^ItCond^".w" Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op8=0xfa & thc0707=0 & thc0506=3 & thSBIT_CZN & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + local shift_amount = Rm0003 & 0x1f; + local tmp = (Rn0003>>shift_amount)|(Rn0003<<(32-shift_amount)); + th_set_carry_for_ror(tmp,Rm0003 & 0xff); + Rd0811 = tmp; + resflags(Rd0811); + build thSBIT_CZN; +} + +:rrx^thSBIT_CZN^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=2 & thSBIT_CZN & thc0003=0xf; thc1515=0 & thc1214=0 & Rd0811 & thc0607=0 & thc0405=3 & Rm0003 +{ + build ItCond; + local tmp1=Rm0003&1; + shift_carry=tmp1(0); + local tmp2 = (zext(CY)<<31)|(Rm0003>>1); + Rd0811 = tmp2; + th_logicflags(); + resflags(Rd0811); + build thSBIT_CZN; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:sadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + local tmpRn0003 = Rn0003; + sum1:4 = sext(tmpRn0003[ 0,16]) + sext(tmpRm0003[ 0,16]); + sum2:4 = sext(tmpRn0003[16,16]) + sext(tmpRm0003[16,16]); + Rd0811[ 0,16] = sum1:2; + Rd0811[16,16] = sum2:2; + GE1 = sum1 s>= 0; + GE2 = sum1 s>= 0; + GE3 = sum2 s>= 0; + GE4 = sum2 s>= 0; +} + +:sadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + local tmpRn0003 = Rn0003; + sum1:4 = sext(tmpRn0003[ 0,8]) + sext(tmpRm0003[ 0,8]); + sum2:4 = sext(tmpRn0003[ 8,8]) + sext(tmpRm0003[ 8,8]); + sum3:4 = sext(tmpRn0003[16,8]) + sext(tmpRm0003[16,8]); + sum4:4 = sext(tmpRn0003[24,8]) + sext(tmpRm0003[24,8]); + Rd0811[ 0,8] = sum1:1; + Rd0811[ 8,8] = sum2:1; + Rd0811[16,8] = sum3:1; + Rd0811[24,8] = sum4:1; + GE1 = sum1 s>= 0; + GE2 = sum2 s>= 0; + GE3 = sum3 s>= 0; + GE4 = sum4 s>= 0; +} + +:sasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + local tmpRn0003 = Rn0003; + diff:4 = sext(tmpRn0003[ 0,16]) - sext(tmpRm0003[16,16]); + sum:4 = sext(tmpRn0003[16,16]) + sext(tmpRm0003[ 0,16]); + Rd0811[ 0,16] = diff[ 0,16]; + Rd0811[16,16] = sum[ 0,16]; + GE1 = diff s>= 0; + GE2 = diff s>= 0; + GE3 = sum s>= 0; + GE4 = sum s>= 0; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +:sbc^CheckInIT_CZNO^ItCond Rd0002,Rm0305 is TMode=1 & ItCond & op6=0x106 & Rm0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_sub_with_carry_flags(Rd0002,Rm0305); + Rd0002 = Rd0002 - Rm0305 - zext(!CY); + resflags(Rd0002); + build CheckInIT_CZNO; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:sbc^thSBIT_CZNO^ItCond Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=11 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_sub_with_carry_flags(Rn0003,ThumbExpandImm12); + Rd0811 = Rn0003 - ThumbExpandImm12 - zext(!CY); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:sbc^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=11 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + th_sub_with_carry_flags(Rn0003,thshift2); + Rd0811 = Rn0003 - thshift2 - zext(!CY); + resflags(Rd0811); + build thSBIT_CZNO; +} + +:sbfx^ItCond Rd0811,Rn0003,thLsbImm,thWidthMinus1 is TMode=1 & ItCond & op4=0xf34 & Rn0003; thc1515=0 & Rd0811 & thLsbImm & thWidthMinus1 +{ + build ItCond; + build thLsbImm; + build thWidthMinus1; + shift:4 = 31 - (thLsbImm + thWidthMinus1); # thMsbImm represents widthMinus1 + Rd0811 = Rn0003 << shift; + shift = 31 - thWidthMinus1; # msbImm represents widthMinus1 + Rd0811 = Rd0811 s>> shift; +} + +:sdiv^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb9 & Rn0003; op12=0xf & Rd0811 & thc0407=0xf & Rm0003 +{ + build ItCond; + local result = Rn0003 / Rm0003; + Rd0811 = result; +} + +:sel^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x8 & Rm0003 +{ + build ItCond; + Rd0811[ 0,8] = ((GE1 == 1) * Rn0003[ 0,8]) + ((GE1 == 0) * Rm0003[ 0,8]); + Rd0811[ 8,8] = ((GE2 == 1) * Rn0003[ 8,8]) + ((GE2 == 0) * Rm0003[ 8,8]); + Rd0811[16,8] = ((GE3 == 1) * Rn0003[16,8]) + ((GE3 == 0) * Rm0003[16,8]); + Rd0811[24,8] = ((GE4 == 1) * Rn0003[24,8]) + ((GE4 == 0) * Rm0003[24,8]); +} + +:shadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + sum1:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[ 0,16]); + sum2:4 = sext(Rn0003[16,16]) + sext(Rm0003[16,16]); + Rd0811[ 0,16] = sum1[1,16]; + Rd0811[16,16] = sum2[1,16]; +} + +:shadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + sum1:4 = sext(Rn0003[ 0,8]) + sext(Rm0003[ 0,8]); + sum2:4 = sext(Rn0003[ 8,8]) + sext(Rm0003[ 8,8]); + sum3:4 = sext(Rn0003[16,8]) + sext(Rm0003[16,8]); + sum4:4 = sext(Rn0003[24,8]) + sext(Rm0003[24,8]); + Rd0811[ 0,8] = sum1[1,8]; + Rd0811[ 8,8] = sum2[1,8]; + Rd0811[16,8] = sum3[1,8]; + Rd0811[24,8] = sum4[1,8]; +} + +:shasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + diff:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[16,16]); + sum:4 = sext(Rn0003[16,16]) + sext(Rm0003[ 0,16]); + Rd0811[ 0,16] = diff[1,16]; + Rd0811[16,16] = sum[1,16]; +} + +:shsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + sum:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[16,16]); + diff:4 = sext(Rn0003[16,16]) - sext(Rm0003[ 0,16]); + Rd0811[ 0,16] = sum[1,16]; + Rd0811[16,16] = diff[1,16]; +} + +:shsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + diff1:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[ 0,16]); + diff2:4 = sext(Rn0003[16,16]) - sext(Rm0003[16,16]); + Rd0811[ 0,16] = diff1[1,16]; + Rd0811[16,16] = diff2[1,16]; +} + +:shsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x2 & Rm0003 +{ + build ItCond; + diff1:4 = sext(Rn0003[ 0,8]) - sext(Rm0003[ 0,8]); + diff2:4 = sext(Rn0003[ 8,8]) - sext(Rm0003[ 8,8]); + diff3:4 = sext(Rn0003[16,8]) - sext(Rm0003[16,8]); + diff4:4 = sext(Rn0003[24,8]) - sext(Rm0003[24,8]); + Rd0811[ 0,8] = diff1[1,8]; + Rd0811[ 8,8] = diff2[1,8]; + Rd0811[16,8] = diff3[1,8]; + Rd0811[24,8] = diff4[1,8]; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +thXBIT: "b" is Rn0003 ; thc0505=0 { local tmpRn0003 = Rn0003; tmp_x:2 = tmpRn0003:2; export tmp_x; } +thXBIT: "t" is Rn0003 ; thc0505=1 { local tmpRn0003 = Rn0003; tmp_x:2 = tmpRn0003(2); export tmp_x; } + +thYBIT: "b" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp_y:2 = tmpRm0003:2; export tmp_y; } +thYBIT: "t" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp_y:2 = tmpRm0003(2); export tmp_y; } + +:smla^thXBIT^thYBIT^ItCond Rd0811,Rn0003,Rm0003,Rt1215 is TMode=1 & ItCond & (op4=0xfb1 & Rn0003; Rt1215 & Rd0811 & thc0607=0 & thYBIT & Rm0003) & thXBIT +{ + build ItCond; + tmp:4 = sext(thXBIT) * sext(thYBIT); + Q = scarry(tmp,Rt1215) || Q; #Q flag is never cleared by this instruction + Rd0811 = tmp + Rt1215; +} + +thdXbot: "" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003:2; export tmp; } +thdXbot: "X" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003(2); export tmp; } + +thdXtop: "" is thc0404=0 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003(2); export tmp; } +thdXtop: "X" is thc0404=1 & Rm0003 { local tmpRm0003 = Rm0003; tmp:2 = tmpRm0003:2; export tmp; } + +:smlad^thdXbot^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb2 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + rnbot:2 = tmpRn0003:2; + rntop:2 = tmpRn0003(2); + tmpbot:4 = sext(rnbot) * sext(thdXbot); + tmptop:4 = sext(rntop) * sext(thdXtop); + tmp:4 = sext(tmpbot) + sext(tmptop); + Q = scarry(tmp,Ra1215) || Q; #Q flag is never cleared by this instruction + Rd0811 = tmp + Ra1215; +} + +:smlald^thdXbot^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbc & Rn0003; Rt1215 & Rd0811 & thc0507=6 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + rnbot:2 = tmpRn0003:2; + rntop:2 = tmpRn0003(2); + tmpbot:4 = sext(rnbot) * sext(thdXbot); + tmptop:4 = sext(rntop) * sext(thdXtop); + accum:8 = (sext(Rd0811) << 32) | zext(Rt1215); + tmp:8 = sext(tmpbot) + sext(tmptop); + accum = tmp + accum; + Rt1215 = accum:4; + Rd0811 = accum(4); +} + +:smlal^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbc & Rn0003; Rt1215 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + accum:8 = (sext(Rd0811) << 32) | zext(Rt1215); + val:8 = sext(Rn0003) * sext(Rm0003) + accum; + Rt1215 = val(0); + Rd0811 = val(4); +} + +:smlal^thXBIT^thYBIT^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & (op4=0xfbc & Rn0003; Rt1215 & Rd0811 & thc0607=2 & thYBIT & Rm0003) & thXBIT +{ + build ItCond; + tmp:4 = sext(thXBIT) * sext(thYBIT); + accum:8 = (zext(Rd0811) << 32) | zext(Rt1215); + val:8 = sext(tmp) + accum; + Rt1215 = val(0); + Rd0811 = val(4); +} + +:smlaw^thYBIT^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb3 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thYBIT & Rm0003 +{ + build ItCond; + local tmp:6 = (sext(Rn0003) * sext(thYBIT)); + local addend:6 = sext(Ra1215) << 16; + Q = scarry(tmp,addend) || Q; #this instruction never clears the Q flag + tmp = tmp + addend; + Rd0811 = tmp(2); +} + +:smlsd^thdXbot^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb4 & Rn0003; Ra1215 & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local rnbot:2 = tmpRn0003:2; + local rntop:2 = tmpRn0003(2); + local prod1:4 = sext(rnbot) * sext(thdXbot); + local prod2:4 = sext(rntop) * sext(thdXtop); + local diff = prod1 - prod2; + Q = scarry(diff,Ra1215) || Q; #instruction never clears Q flag + Rd0811 = diff + Ra1215; +} + +:smlsld^thdXbot^ItCond Rt1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbd & Rn0003; Rt1215 & Rd0811 & thc0507=6 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local rnbot:2 = tmpRn0003:2; + local rntop:2 = tmpRn0003(2); + local tmpbot:4 = sext(rnbot) * sext(thdXbot); + local tmptop:4 = sext(rntop) * sext(thdXtop); + local accum:8 = (sext(Rd0811) << 32) | zext(Rt1215); + local tmp:8 = sext(tmpbot) - sext(tmptop); + accum = tmp + accum; + Rt1215 = accum:4; + Rd0811 = accum(4); +} + +:smmla^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; Ra1215 & Rd0811 & thc0407=0 & Rm0003 +{ + build ItCond; + local val:8 = sext(Rn0003) * sext(Rm0003); + local accum:8 = (zext(Ra1215)) << 32; + val = val + accum; + Rd0811 = val(4); +} + +:smmlar^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; Ra1215 & Rd0811 & thc0407=1 & Rm0003 +{ + build ItCond; + local val:8 = sext(Rn0003) * sext(Rm0003); + local accum:8 = (zext(Ra1215)) << 32; + val = val + accum + 0x80000000; + Rd0811 = val(4); +} + +:smmls^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb6 & Rn0003; Ra1215 & Rd0811 & thc0407=0 & Rm0003 +{ + build ItCond; + local val:8 = sext(Rn0003) * sext(Rm0003); + val = (zext(Ra1215) << 32) - val; + Rd0811 = val(4); +} + +:smmlsr^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb6 & Rn0003; Ra1215 & Rd0811 & thc0407=1 & Rm0003 +{ + build ItCond; + local val:8 = sext(Rn0003) * sext(Rm0003); + val = (zext(Ra1215) << 32) - val; + val = val + 0x80000000; + Rd0811 = val(4); +} + +:smmul^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; thc1215=0xf & Rd0811 & thc0407=0 & Rm0003 +{ + build ItCond; + val:8 = sext(Rn0003) * sext(Rm0003); + Rd0811 = val(4); +} + +:smmulr^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb5 & Rn0003; thc1215=0xf & Rd0811 & thc0407=1 & Rm0003 +{ + build ItCond; + val:8 = sext(Rn0003) * sext(Rm0003); + val = val + 0x80000000; + Rd0811 = val(4); +} + +:smuad^thdXbot^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb2 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local rnbot:2 = tmpRn0003:2; + local rntop:2 = tmpRn0003(2); + local prod1:4 = sext(rnbot) * sext(thdXbot); + local prod2:4 = sext(rntop) * sext(thdXtop); + Q = scarry(prod1,prod2) || Q; #instruction does not clear the Q flag + Rd0811 = prod1 + prod2; +} + +:smulbb^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local tmpRm0003 = Rm0003; + op1:2 = tmpRn0003:2; + op2:2 = tmpRm0003:2; + Rd0811 = sext(op1) * sext(op2); +} + +:smulbt^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=1 & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local tmpRm0003 = Rm0003; + op1:2 = tmpRn0003:2; + op2:2 = tmpRm0003(2); + Rd0811 = sext(op1) * sext(op2); +} + +:smultb^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=2 & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local tmpRm0003 = Rm0003; + op1:2 = tmpRn0003(2); + op2:2 = tmpRm0003:2; + Rd0811 = sext(op1) * sext(op2); +} + +:smultt^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb1 & Rn0003; op12=15 & Rd0811 & sop0407=3 & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local tmpRm0003 = Rm0003; + op1:2 = tmpRn0003(2); + op2:2 = tmpRm0003(2); + Rd0811 = sext(op1) * sext(op2); +} + +:smull^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb8 & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + val:8 = sext(Rn0003) * sext(Rm0003); + Ra1215 = val(0); + Rd0811 = val(4); +} + +:smusd^thdXbot^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb4 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thdXbot & thdXtop & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + rnbot:2 = tmpRn0003:2; + rntop:2 = tmpRn0003(2); + tmpbot:4 = sext(rnbot) * sext(thdXbot); + tmptop:4 = sext(rntop) * sext(thdXtop); + tmp:8 = sext(tmpbot) - sext(tmptop); + Rd0811 = tmp:4; +} + +:smulw^thYBIT^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb3 & Rn0003; thc1215=0xf & Rd0811 & thc0507=0 & thYBIT & Rm0003 +{ + build ItCond; + tmp:8 = (sext(Rn0003) * sext(thYBIT)) s>> 16; + Rd0811 = tmp:4; +} + +:srsdb^ItCond sp^"!",thSRSMode is TMode=1 & ItCond & op6=0x3a0 & sp & thc0505=1 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode +{ + build ItCond; + # register list is always: r14, spsr + ptr:4 = sp - 4; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; + sp = ptr; +} + +:srsdb^ItCond sp,thSRSMode is TMode=1 & ItCond & op6=0x3a0 & sp & thc0505=0 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode +{ + build ItCond; + # register list is always: r14, spsr + ptr:4 = sp - 4; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; +} + +:srsib^ItCond sp^"!",thSRSMode is TMode=1 & ItCond & op6=0x3a6 & sp & thc0505=1 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode +{ + build ItCond; + # register list is always: r14, spsr + ptr:4 = sp + 4; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; + sp = ptr; +} + +:srsia^ItCond sp,thSRSMode is TMode=1 & ItCond & op6=0x3a6 & sp & thc0505=0 & thc0004=0xd; op8=0xc0 & sop0507=0 & thSRSMode +{ + build ItCond; + # register list is always: r14, spsr + ptr:4 = sp + 4; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +# ssat and ssat16 were defined elsewhere and moved here to preserve sort order + +# shift operands for ssat and usat: + +th2_shift0: is imm3_shft=0x0 & imm2_shft=0x0 { } +th2_shift0: ",lsl "^thLsbImm is imm3_shft & imm2_shft & thLsbImm { } +th2_shift1: ",asr "^thLsbImm is imm3_shft & imm2_shft & thLsbImm { } +th2_shift1: ",asr #32" is imm3_shft=0x0 & imm2_shft=0x0 { } + +:ssat Rt0811, thMsbImm, part2Rd0003^th2_shift0 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x0 & part2c0404=0x0 & part2Rd0003 ; + thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift0 & thMsbImm & thLsbImm +{ + # Shift bit is 0 + tmpRn:4 = part2Rd0003 << thLsbImm; + tmp:4 = SignedSaturate(tmpRn, thMsbImm); + Q = SignedDoesSaturate(tmpRn, thMsbImm); + Rt0811 = tmp; +} + +:ssat Rt0811, thMsbImm, part2Rd0003^th2_shift1 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003; + thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift1 & thMsbImm & thLsbImm +{ + # Shift bit is 1 + tmpRn:4 = part2Rd0003 s>> thLsbImm; + tmp:4 = SignedSaturate(tmpRn, thMsbImm); + Q = SignedDoesSaturate(tmpRn, thMsbImm); + Rt0811 = tmp; +} + +:ssat16 Rt0811, "#"^Immed4, part2Rd0003 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xc & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003; + op12=0x0 & Rt0811 & thc0407=0x0 & Immed4 +{ + tmp:4 = SignedSaturate(part2Rd0003, Immed4); + Q = SignedDoesSaturate(part2Rd0003, Immed4); + Rt0811 = tmp; +} + +:ssax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + sum:4 = sext(Rn0003[ 0,16]) + sext(Rm0003[16,16]); + diff:4 = sext(Rn0003[16,16]) - sext(Rm0003[ 0,16]); + Rd0811[ 0,16] = sum[0,16]; + Rd0811[16,16] = diff[0,16]; + GE1 = sum s>= 0; + GE2 = sum s>= 0; + GE3 = diff s>= 0; + GE4 = diff s>= 0; +} + +:ssub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + diff1:4 = sext(Rn0003[ 0,16]) - sext(Rm0003[ 0,16]); + diff2:4 = sext(Rn0003[16,16]) - sext(Rm0003[16,16]); + Rd0811[ 0,16] = diff1[0,16]; + Rd0811[16,16] = diff2[0,16]; + GE1 = diff1 s>= 0; + GE2 = diff1 s>= 0; + GE3 = diff2 s>= 0; + GE4 = diff2 s>= 0; +} + +:ssub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + diff1:4 = sext(Rn0003[ 0,8]) - sext(Rm0003[ 0,8]); + diff2:4 = sext(Rn0003[ 8,8]) - sext(Rm0003[ 8,8]); + diff3:4 = sext(Rn0003[16,8]) - sext(Rm0003[16,8]); + diff4:4 = sext(Rn0003[24,8]) - sext(Rm0003[24,8]); + Rd0811[ 0,8] = diff1[0,8]; + Rd0811[ 8,8] = diff2[0,8]; + Rd0811[16,8] = diff3[0,8]; + Rd0811[24,8] = diff4[0,8]; + GE1 = diff1 s>= 0; + GE2 = diff2 s>= 0; + GE3 = diff3 s>= 0; + GE4 = diff4 s>= 0; +} + +:umull^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfba & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + val:8 = zext(Rn0003) * zext(Rm0003); + Ra1215 = val(0); + Rd0811 = val(4); +} + +:umaal^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbe & Rn0003; Ra1215 & Rd0811 & sop0407=6 & Rm0003 +{ + build ItCond; + val:8 = zext(Rn0003) * zext(Rm0003) + zext(Ra1215) + zext(Rd0811); + Ra1215 = val(0); + Rd0811 = val(4); +} + +:umlal^ItCond Ra1215,Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbe & Rn0003; Ra1215 & Rd0811 & sop0407=0 & Rm0003 +{ + build ItCond; + accum:8 = (zext(Rd0811) << 32) | zext(Ra1215); + val:8 = zext(Rn0003) * zext(Rm0003) + accum; + Ra1215 = val(0); + Rd0811 = val(4); +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +@if defined(VERSION_6) + +thumbEndianNess: "LE" is op0=0xb650 { export 0:1; } +thumbEndianNess: "BE" is op0=0xb658 { export 1:1; } + +:setend^ItCond thumbEndianNess is TMode=1 & ItCond & (op0=0xb650 | op0=0xb658) & thumbEndianNess { setEndianState(thumbEndianNess); } + + +:sev^ItCond is TMode=1 & ItCond & op0=0xbf40 +{ + build ItCond; +} + +:sev^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=8004 +{ + build ItCond; +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:stc^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=0 & thL4=0; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_store(t_cpn,thCRd,taddrmode5); +} + +:stcl^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x76 & thN6=1 & thL4=0; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_storelong(t_cpn,thCRd,taddrmode5); +} + +:stc2^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=0 & thL4=0; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_store(t_cpn,thCRd,taddrmode5); +} + +:stc2l^ItCond thcpn,thCRd,taddrmode5 is (TMode=1 & ItCond & op9=0x7e & thN6=1 & thL4=0; thCRd & thcpn) & taddrmode5 +{ + build ItCond; + build taddrmode5; + t_cpn:4 = thcpn; + coprocessor_storelong(t_cpn,thCRd,taddrmode5); +} + +:stm^ItCond Rn0003,thstrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=0 & thc0404=0 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thstrlist_inc; +} + +:stm^ItCond^".w" Rn0003!,thstrlist_inc is TMode=1 & ItCond & op11=0x1d & thc0910=0 & sop0608=2 & thwbit=1 & thc0404=0 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_inc +{ + build ItCond; + mult_addr = Rn0003; + build thstrlist_inc; + Rn0003 = mult_addr; +} + +:stmdb^ItCond Rn0003!,thstrlist_dec is TMode=1 & ItCond & op4=0xe92 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thstrlist_dec; + Rn0003 = mult_addr + 4; +} + +:stmdb^ItCond Rn0003,thstrlist_dec is TMode=1 & ItCond & op4=0xe90 & Rn0003; thc1515=0 & thc1313=0 & thstrlist_dec +{ + build ItCond; + mult_addr = Rn0003-4; + build thstrlist_dec; +} + +@endif # defined(VERSION_6T2) || defined(VERSION_7) + +:stmia^ItCond Rn_exclaim,stbrace is TMode=1 & ItCond & op11=0x18 & Rn_exclaim & stbrace & Rn_exclaim_WB +{ + build ItCond; + build Rn_exclaim; + build stbrace; + build Rn_exclaim_WB; +} + +:str^ItCond Rd0002,RnIndirect4 is TMode=1 & ItCond & op11=0xc & RnIndirect4 & Rd0002 +{ + build ItCond; + *RnIndirect4 = Rd0002; +} + +:str^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x28 & RnRmIndirect & Rd0002 +{ + build ItCond; + *RnRmIndirect = Rd0002; +} + +:str^ItCond Rd0810,Sprel8Indirect is TMode=1 & ItCond & op11=0x12 & Sprel8Indirect & Rd0810 +{ + build ItCond; + *Sprel8Indirect = Rd0810; +} + + +:strb^ItCond Rd0002,RnIndirect1 is TMode=1 & ItCond & op11=0xe & RnIndirect1 & Rd0002 +{ + build ItCond; + local tmpRd0002 = Rd0002; + *RnIndirect1 = tmpRd0002:1; +} + +:strb^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x2a & RnRmIndirect & Rd0002 +{ + build ItCond; + local tmpRd0002 = Rd0002; + *RnRmIndirect = tmpRd0002:1; +} + +:strh^ItCond Rd0002,RnIndirect2 is TMode=1 & ItCond & op11=0x10 & RnIndirect2 & Rd0002 +{ + build ItCond; + local tmpRd0002 = Rd0002; + *RnIndirect2 = tmpRd0002:2; +} + +:strh^ItCond Rd0002,RnRmIndirect is TMode=1 & ItCond & op9=0x29 & RnRmIndirect & Rd0002 +{ + build ItCond; + local tmpRd0002 = Rd0002; + *RnRmIndirect = tmpRd0002:2; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:str.w^ItCond Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8c; Rt1215) & RnIndirect12 +{ + build ItCond; + *RnIndirect12 = Rt1215; +} + +:str.w^ItCond Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf84; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + *RnIndirectPUW = Rt1215; +} + +:str^ItCond^".w" Rt1215,[Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xf84 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405=0 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + Rm0003; + *tmp = Rt1215; +} + +:str^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf84 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + *tmp = Rt1215; +} + +:strb^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf88; Rt1215) & RnIndirect12 +{ + build ItCond; + build RnIndirect12; + local tmpRt1215 = Rt1215; + *RnIndirect12 = tmpRt1215:1; +} + +:strb^ItCond^".w" Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf80; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + local tmpRt1215 = Rt1215; + *RnIndirectPUW = tmpRt1215:1; +} + +:strb^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf80 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:1; +} + +:strbt^ItCond Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf80 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:1; +} + +:strd^ItCond Rt1215,Rt0811,RnIndirectPUW1 is TMode=1 & ItCond & (op9=0x74 & thc0910=0 & thc0606=1 & thc0404=0 & Rn0003; Rt1215 & Rt0811) & $(RN_INDIRECT_PUW1) +{ + build ItCond; + build RnIndirectPUW1; + local tmp = RnIndirectPUW1; + *tmp = Rt1215; + tmp = tmp + 4; + *tmp = Rt0811; +} + +:strh^ItCond^".w" Rt1215,RnIndirect12 is TMode=1 & ItCond & (op4=0xf8A; Rt1215) & RnIndirect12 +{ + build ItCond; + local tmpRt1215 = Rt1215; + *RnIndirect12 = tmpRt1215:2; +} + +:strh^ItCond Rt1215,RnIndirectPUW is TMode=1 & ItCond & (op4=0xf82; Rt1215 & thc1111=1) & $(RN_INDIRECT_PUW) +{ + build ItCond; + build RnIndirectPUW; + local tmpRt1215 = Rt1215; + *RnIndirectPUW = tmpRt1215:2; +} + +:strh^ItCond^".w" Rt1215,[Rn0003,Rm0003,"lsl #"^thc0405] is TMode=1 & ItCond & op4=0xf82 & Rn0003; Rt1215 & thc1111=0 & sop0610=0 & thc0405 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 << thc0405); + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:2; +} + +:strht^ItCond Rt1215,[Rn0003,"#"^Immed8] is TMode=1 & ItCond & op4=0xf82 & Rn0003; Rt1215 & thc0811=14 & Immed8 +{ + build ItCond; + local tmp = Rn0003 + Immed8; + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:2; +} + +:strex^ItCond Rd0811,Rt1215,[Rn0003,Immed8_4] is TMode=1 & ItCond & op4=0xe84 & Rn0003; Rt1215 & Rd0811 & Immed8_4 +{ + build ItCond; + local tmp = Rn0003 + Immed8_4; + access:1 = hasExclusiveAccess(tmp); + Rd0811 = 1; + if (!access) goto inst_next; + Rd0811 = 0; + *tmp = Rt1215; +} + +@endif # VERSION_6T2 || VERSION_7 + +@if defined(VERSION_7) + +:strexb^ItCond Rd0003,Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & thc0811=15 & thc0407=4 & Rd0003 +{ + build ItCond; + local tmp = Rn0003; + access:1 = hasExclusiveAccess(tmp); + Rd0003 = 1; + if (!access) goto inst_next; + Rd0003 = 0; + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:1; +} + +:strexh^ItCond Rd0003,Rt1215,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & thc0811=15 & thc0407=5 & Rd0003 +{ + build ItCond; + local tmp = Rn0003; + access:1 = hasExclusiveAccess(tmp); + Rd0003 = 1; + if (!access) goto inst_next; + Rd0003 = 0; + local tmpRt1215 = Rt1215; + *tmp = tmpRt1215:1; +} + +:strexd^ItCond Rd0003,Rt1215,Rt0811,[Rn0003] is TMode=1 & ItCond & op4=0xe8c & Rn0003; Rt1215 & Rt0811 & thc0407=7 & Rd0003 +{ + build ItCond; + local tmp = Rn0003; + access:1 = hasExclusiveAccess(tmp); + Rd0003 = 1; + if (!access) goto inst_next; + Rd0003 = 0; + *tmp = Rt1215; + tmp = tmp + 4; + *tmp = Rt0811; +} + +@endif # VERSION_7 + +:sub^CheckInIT_CZNO^ItCond Rd0002,Rn0305,Immed3 is TMode=1 & ItCond & op9=0xf & Immed3 & Rn0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_subflags(Rn0305,Immed3); + Rd0002 = Rn0305 - Immed3; + resflags(Rd0002); + build CheckInIT_CZNO; +} + +:sub^CheckInIT_CZNO^ItCond Rd0810,Immed8 is TMode=1 & ItCond & op11=7 & Rd0810 & Immed8 & CheckInIT_CZNO +{ + build ItCond; + th_subflags(Rd0810,Immed8); + Rd0810 = Rd0810 - Immed8; + resflags(Rd0810); + build CheckInIT_CZNO; +} + +:sub^CheckInIT_CZNO^ItCond Rd0002,Rn0305,Rm0608 is TMode=1 & ItCond & op9=0xd & Rm0608 & Rn0305 & Rd0002 & CheckInIT_CZNO +{ + build ItCond; + th_subflags(Rn0305,Rm0608); + Rd0002 = Rn0305 - Rm0608; + resflags(Rd0002); + build CheckInIT_CZNO; +} + +:sub^ItCond sp,Immed7_4 is TMode=1 & ItCond & op7=0x161 & sp & Immed7_4 +{ + build ItCond; + sp = sp - Immed7_4; +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:sub^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=13 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_subflags(Rn0003,ThumbExpandImm12); + Rd0811 = Rn0003-ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:subw^ItCond Rd0811,Rn0003,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & Rn0003; thc1515=0 & Rd0811) & Immed12 +{ + build ItCond; + th_subflags(Rn0003,Immed12); + Rd0811 = Rn0003-Immed12; + resflags(Rd0811); +} + +:sub^thSBIT_CZNO^ItCond^".w" Rd0811,Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=13 & thSBIT_CZNO & Rn0003; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + local tmp = thshift2; + th_subflags(Rn0003,tmp); + Rd0811 = Rn0003-tmp; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:sub^thSBIT_CZNO^ItCond^".w" Rd0811,sp,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=13 & thSBIT_CZNO & sp & sop0003=0xd; thc1515=0 & Rd0811) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + th_subflags(sp,ThumbExpandImm12); + Rd0811 = sp-ThumbExpandImm12; + resflags(Rd0811); + build thSBIT_CZNO; +} + +:sub^ItCond pc,lr,Immed8 is TMode=1 & ItCond & op4=0xf3d & pc & sop0003=0xe; op8=0x8f & lr & Immed8 +{ + build ItCond; + build Immed8; + th_subflags(lr,Immed8); + dest:4 = lr-Immed8; + resflags(dest); + cpsr=spsr; + SetThumbMode( ((cpsr >> 5) & 1) != 0 ); + pc = dest; + goto [pc]; +} + +:subw^ItCond Rd0811,sp,Immed12 is TMode=1 & ItCond & (op11=0x1e & thc0909=1 & sop0508=5 & thc0404=0 & sop0003=0xd & sp; thc1515=0 & Rd0811) & Immed12 +{ + build ItCond; + th_subflags(sp,Immed12); + Rd0811 = sp-Immed12; + resflags(Rd0811); +} + +:sub^thSBIT_CZNO^ItCond^".w" Rd0811,sp,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=13 & thSBIT_CZNO & sop0003=0xd & sp; thc1515=0 & Rd0811 & thshift2 +{ + build ItCond; + build thshift2; + local tmp = thshift2; + th_subflags(sp,tmp); + Rd0811 = sp-tmp; + resflags(Rd0811); + build thSBIT_CZNO; +} + +@endif # VERSION_6T2 || VERSION_7 + +:svc^ItCond immed8 is TMode=1 & ItCond & op8=0xdf & immed8 +{ + build ItCond; + tmp:4 = immed8; + software_interrupt(tmp); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:sxtab^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa4 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = sext(tmp:1) + Rn0003; +} + +:sxtab^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa4 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = sext(tmpRm0003:1) + Rn0003; +} + +:sxtab16^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa2 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + local tmpRn0003 = Rn0003; + tmpL:2 = sext(tmp:1) + tmpRn0003:2; + tmp = tmp >> 16; + tmpH:2 = sext(tmp:1) + tmpRn0003(2); + Rd0811 = zext(tmpL) + (zext(tmpH) << 16); +} + +:sxtab16^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa2 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRn0003 = Rn0003; + local tmpRm0003 = Rm0003; + tmpL:2 = sext(tmpRm0003:1) + tmpRn0003:2; + local tmp = tmpRm0003 >> 16; + tmpH:2 = sext(tmp:1) + tmpRn0003(2); + Rd0811 = zext(tmpL) + (zext(tmpH) << 16); +} + +:sxtah^ItCond Rd0811, Rn0003, Rm0003, ByteRotate is TMode=1 & ItCond & op4=0xfa0 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = sext(tmp:2) + Rn0003; +} + +:sxtah^ItCond Rd0811, Rn0003, Rm0003 is TMode=1 & ItCond & op4=0xfa0 & Rn0003; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = sext(tmpRm0003:2) + Rn0003; +} + +@endif # VERSION_6T2 || VERSION_7 + +@if defined(VERSION_6) + +:sxtb^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=0 & thc0606=1 & Rm0305 & Rd0002 +{ + build ItCond; + local tmpRm0305 = Rm0305; + Rd0002 = sext(tmpRm0305:1); +} + +:sxtb^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa4f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = sext(tmp:1); +} + +:sxtb^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa4f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = sext(tmpRm0003:1); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:sxtb16^ItCond Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa2f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 + +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + tmpL:2 = sext(tmp:1); + tmp = tmp >> 16; + tmpH:2 = sext(tmp:1); + Rd0811 = zext(tmpL) + (zext(tmpH) << 16); +} + +:sxtb16^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa2f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + tmpL:2 = sext(tmpRm0003:1); + tmp:4 = tmpRm0003 >> 16; + tmpH:2 = sext(tmp:1); + Rd0811 = zext(tmpL) + (zext(tmpH) << 16); +} + +@endif # VERSION_6T2 || VERSION_7 + +@if defined(VERSION_6) + +:sxth^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=0 & thc0606=0 & Rm0305 & Rd0002 +{ + build ItCond; + local tmpRm0305 = Rm0305; + Rd0002 = sext(tmpRm0305:2); +} + +:sxth^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa0f; op12=0xf & Rd0811 & thc0707=1 & thc0606=0 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = sext(tmp:2); +} + +:sxth^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa0f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = sext(tmpRm0003:2); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:tbb^ItCond [Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; op8=0xf0 & thc0507=0 & thc0404=0 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + Rm0003; + offs:1 = *tmp; + SetThumbMode(1); + pc = inst_next + (zext(offs) * 2); + goto [pc]; +} + +:tbh^ItCond [Rn0003,Rm0003] is TMode=1 & ItCond & op4=0xe8d & Rn0003; op8=0xf0 & thc0507=0 & thc0404=1 & Rm0003 +{ + build ItCond; + local tmp = Rn0003 + (Rm0003 * 2); + offs:2 = *tmp; + SetThumbMode(1); + pc = inst_next + (zext(offs) * 2); + goto [pc]; +} + +Pcrel: [cloc,Rm0003] is Rm0003 & thc0404=0 [ cloc = inst_next; ] +{ + local tmp = Rm0003; tmp = cloc + tmp; val:1 = *tmp; tmp = zext(val); export tmp; +} +Pcrel: [cloc,Rm0003] is Rm0003 & thc0404=1 [ cloc = inst_next; ] +{ + local tmp = Rm0003; tmp = cloc + (tmp * 2); val:2 = *tmp; tmp = zext(val); export tmp; +} + +:tbb^ItCond Pcrel is TMode=1 & ItCond & op4=0xe8d & thc0003=15; op8=0xf0 & thc0507=0 & thc0404=0 & Pcrel +{ + build ItCond; + SetThumbMode(1); + pc = inst_next + (Pcrel * 2); + goto [pc]; +} + +:tbh^ItCond Pcrel is TMode=1 & ItCond & op4=0xe8d & thc0003=15; op8=0xf0 & thc0507=0 & thc0404=1 & Pcrel +{ + build ItCond; + SetThumbMode(1); + pc = inst_next + (Pcrel * 2); + goto [pc]; +} + +@endif # VERSION_6T2 || VERSION_7 + +:tst^ItCond Rn0002,Rm0305 is TMode=1 & ItCond & op6=0x108 & Rm0305 & Rn0002 +{ + build ItCond; + local tmp = Rn0002 & Rm0305; + ZR = (tmp == 0); + NG = (tmp s< 0); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:teq^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=4 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + local tmp = Rn0003 ^ ThumbExpandImm12; + th_test_flags(tmp); +} + +:teq^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=4 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf & thshift2 +{ + build ItCond; + build thshift2; + local tmp = Rn0003 ^ thshift2; + th_test_flags(tmp); +} + +:tst^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=0 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf) & ThumbExpandImm12 +{ + build ItCond; + build ThumbExpandImm12; + local tmp = Rn0003 & ThumbExpandImm12; + th_test_flags(tmp); +} + +:tst^ItCond^".w" Rn0003,thshift2 is TMode=1 & ItCond & op11=0x1d & thc0910=1 & sop0508=0 & thc0404=1 & Rn0003; thc1515=0 & thc0811=0xf & thshift2 +{ + build ItCond; + build thshift2; + local tmp = Rn0003 & thshift2; + th_test_flags(tmp); +} + +:uadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]); + sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]); + GE1 = carry(Rn0003[0,16],Rm0003[0,16]); + GE2 = GE1; + GE3 = carry(Rn0003[16,16],Rm0003[16,16]); + GE4 = GE3; + Rd0811[ 0,16] = sum1[0,16]; + Rd0811[16,16] = sum2[0,16]; +} + +:uadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]); + sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]); + sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]); + sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]); + GE1 = carry(Rn0003[0,8],Rm0003[0,8]); + GE2 = carry(Rn0003[8,8],Rm0003[8,8]); + GE3 = carry(Rn0003[16,8],Rm0003[16,8]); + GE4 = carry(Rn0003[24,8],Rm0003[24,8]); + Rd0811[ 0,8] = sum1[0,8]; + Rd0811[ 8,8] = sum2[0,8]; + Rd0811[16,8] = sum3[0,8]; + Rd0811[24,8] = sum4[0,8]; +} + +:uasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]); + sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]); + GE1 = diff s>= 0; + GE2 = GE1; + GE3 = carry(Rn0003[16,16],Rm0003[0,16]); + GE4 = GE3; + Rd0811[ 0,16] = diff[0,16]; + Rd0811[16,16] = sum[0,16]; + } + +:uhadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]); + sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]); + Rd0811[ 0,16] = sum1[1,16]; + Rd0811[16,16] = sum2[1,16]; +} + +:uhadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]); + sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]); + sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]); + sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]); + Rd0811[ 0,8] = sum1[1,8]; + Rd0811[ 8,8] = sum2[1,8]; + Rd0811[16,8] = sum3[1,8]; + Rd0811[24,8] = sum4[1,8]; +} + +:uhasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]); + sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]); + Rd0811[ 0,16] = diff[1,16]; + Rd0811[16,16] = sum[1,16]; +} + +:uhsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]); + diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]); + Rd0811[ 0,16] = sum[1,16]; + Rd0811[16,16] = diff[1,16]; +} + +:uhsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]); + diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]); + Rd0811[ 0,16] = diff1[1,16]; + Rd0811[16,16] = diff2[1,16]; +} + +:uhsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x6 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]); + diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]); + diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]); + diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]); + Rd0811[ 0,8] = diff1[1,8]; + Rd0811[ 8,8] = diff2[1,8]; + Rd0811[16,8] = diff3[1,8]; + Rd0811[24,8] = diff4[1,8]; +} + +:uqadd16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa9 & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[ 0,16]); + sum2:4 = zext(Rn0003[16,16]) + zext(Rm0003[16,16]); + tmp1:4 = UnsignedSaturate(sum1, 16:2); + tmp2:4 = UnsignedSaturate(sum2, 16:2); + Rd0811[ 0,16] = tmp1[0,16]; + Rd0811[16,16] = tmp2[0,16]; +} + +:uqadd8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa8 & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + sum1:4 = zext(Rn0003[ 0,8]) + zext(Rm0003[ 0,8]); + sum2:4 = zext(Rn0003[ 8,8]) + zext(Rm0003[ 8,8]); + sum3:4 = zext(Rn0003[16,8]) + zext(Rm0003[16,8]); + sum4:4 = zext(Rn0003[24,8]) + zext(Rm0003[24,8]); + tmp1:4 = UnsignedSaturate(sum1, 8:2); + tmp2:4 = UnsignedSaturate(sum2, 8:2); + tmp3:4 = UnsignedSaturate(sum3, 8:2); + tmp4:4 = UnsignedSaturate(sum4, 8:2); + Rd0811[ 0,8] = tmp1[0,8]; + Rd0811[ 8,8] = tmp2[0,8]; + Rd0811[16,8] = tmp3[0,8]; + Rd0811[24,8] = tmp4[0,8]; +} + +:uqasx^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfaa & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + diff:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[16,16]); + sum:4 = zext(Rn0003[16,16]) + zext(Rm0003[ 0,16]); + tmpdiff:4 = UnsignedSaturate(diff, 16:2); + tmpsum:4 = UnsignedSaturate(sum, 16:2); + Rd0811[ 0,16] = tmpdiff[0,16]; + Rd0811[16,16] = tmpsum[0,16]; +} + +:uqsax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]); + diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]); + tmpsum:4 = UnsignedSaturate(sum, 16:2); + tmpdiff:4 = UnsignedSaturate(diff, 16:2); + Rd0811[ 0,16] = tmpsum[0,16]; + Rd0811[16,16] = tmpdiff[0,16]; +} + +:uqsub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]); + diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]); + tmp1:4 = UnsignedSaturate(diff1, 16:2); + tmp2:4 = UnsignedSaturate(diff2, 16:2); + Rd0811[ 0,16] = tmp1[0,16]; + Rd0811[16,16] = tmp2[0,16]; +} + +:uqsub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x5 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]); + diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]); + diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]); + diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]); + tmp1:4 = UnsignedSaturate(diff1, 8:2); + tmp2:4 = UnsignedSaturate(diff2, 8:2); + tmp3:4 = UnsignedSaturate(diff3, 8:2); + tmp4:4 = UnsignedSaturate(diff4, 8:2); + Rd0811[ 0,8] = tmp1[0,8]; + Rd0811[ 8,8] = tmp2[0,8]; + Rd0811[16,8] = tmp3[0,8]; + Rd0811[24,8] = tmp4[0,8]; +} + +:usad8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfb7 & Rn0003; op12=0xf & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]); + diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]); + diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]); + diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]); + absdiff1:4 = Absolute(diff1); + absdiff2:4 = Absolute(diff2); + absdiff3:4 = Absolute(diff3); + absdiff4:4 = Absolute(diff4); + Rd0811 = absdiff1 + absdiff2 + absdiff3 + absdiff4; +} + +:usada8^ItCond Rd0811,Rn0003,Rm0003,Ra1215 is TMode=1 & ItCond & op4=0xfb7 & Rn0003; Ra1215 & Rd0811 & thc0407=0x0 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]); + diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]); + diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]); + diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]); + absdiff1:4 = Absolute(diff1); + absdiff2:4 = Absolute(diff2); + absdiff3:4 = Absolute(diff3); + absdiff4:4 = Absolute(diff4); + # The manual specifies a zero extension of Ra to an unspecified + # intermediate precision, followed by truncation to 4 bytes. In this + # model, zext is retained, but it has no effect because the + # intermediate precision is 4 bytes. + Rd0811 = zext(Ra1215) + absdiff1 + absdiff2 + absdiff3 + absdiff4; +} + +# usat and ussat16 were defined elsewhere and moved here to preserve sort order + +:usat Rt0811, thMsbImm, part2Rd0003^th2_shift0 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x0 & part2c0404=0x0 & part2Rd0003 ; + thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift0 & thMsbImm & thLsbImm +{ + # Shift bit is 0 + tmpRn:4 = part2Rd0003 << thLsbImm; + tmp:4 = UnsignedSaturate(tmpRn, thMsbImm); + Q = UnsignedDoesSaturate(tmpRn, thMsbImm); + Rt0811 = tmp; +} + +:usat Rt0811, thMsbImm, part2Rd0003^th2_shift1 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003 ; + thc1515=0x0 & Rt0811 & thc0505=0x0 & th2_shift1 & thMsbImm & thLsbImm +{ + # Shift bit is 1 + tmpRn:4 = part2Rd0003 s>> thLsbImm; + tmp:4 = UnsignedSaturate(tmpRn, thMsbImm); + Q = UnsignedDoesSaturate(tmpRn, thMsbImm); + Rt0811 = tmp; +} + +:usat16 Rt0811, "#"^Immed4, part2Rd0003 is + TMode=1 & part2op=0x1e & part2S=0x0 & part2cond=0xe & part2c0505=0x1 & part2c0404=0x0 & part2Rd0003 ; + op12=0x0 & Rt0811 & thc0407=0x0 & Immed4 +{ + tmp:4 = UnsignedSaturate(part2Rd0003, Immed4); + Q = UnsignedDoesSaturate(part2Rd0003, Immed4); + Rt0811 = tmp; +} + +:usax^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfae & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + sum:4 = zext(Rn0003[ 0,16]) + zext(Rm0003[16,16]); + diff:4 = zext(Rn0003[16,16]) - zext(Rm0003[ 0,16]); + Rd0811[ 0,16] = sum[0,16]; + Rd0811[16,16] = diff[0,16]; + # this odd looking condition tests that the 16 bit sum overflowed, + # which would have made it a negative number. That's how it's + # documented, but to be consistent they might have used s< 0. + GE1 = sum s>= 0x10000; + GE2 = sum s>= 0x10000; + GE3 = diff s>= 0; + GE4 = diff s>= 0; +} + +:usub16^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfad & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,16]) - zext(Rm0003[ 0,16]); + diff2:4 = zext(Rn0003[16,16]) - zext(Rm0003[16,16]); + Rd0811[ 0,16] = diff1[0,16]; + Rd0811[16,16] = diff2[0,16]; + GE1 = diff1 s>= 0; + GE2 = diff1 s>= 0; + GE3 = diff2 s>= 0; + GE4 = diff2 s>= 0; +} + +:usub8^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfac & Rn0003; op12=0xf & Rd0811 & thc0407=0x4 & Rm0003 +{ + build ItCond; + diff1:4 = zext(Rn0003[ 0,8]) - zext(Rm0003[ 0,8]); + diff2:4 = zext(Rn0003[ 8,8]) - zext(Rm0003[ 8,8]); + diff3:4 = zext(Rn0003[16,8]) - zext(Rm0003[16,8]); + diff4:4 = zext(Rn0003[24,8]) - zext(Rm0003[24,8]); + Rd0811[ 0,8] = diff1[0,8]; + Rd0811[ 8,8] = diff2[0,8]; + Rd0811[16,8] = diff3[0,8]; + Rd0811[24,8] = diff4[0,8]; + GE1 = diff1 s>= 0; + GE2 = diff2 s>= 0; + GE3 = diff3 s>= 0; + GE4 = diff4 s>= 0; +} + +:ubfx^ItCond Rd0811,Rn0003,thLsbImm,thWidthMinus1 is TMode=1 & ItCond & op4=0xf3c & Rn0003; thc1515=0 & Rd0811 & thLsbImm & thc0505=0 & thWidthMinus1 +{ + build ItCond; + build thLsbImm; + build thWidthMinus1; + shift:4 = 31 - (thLsbImm + thWidthMinus1); # thMsbImm represents widthMinus1 + Rd0811 = Rn0003 << shift; + shift = 31 - thWidthMinus1; # msbImm represents widthMinus1 + Rd0811 = Rd0811 >> shift; +} + +:udiv^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfbb & Rn0003; op12=0xf & Rd0811 & thc0407=0xf & Rm0003 +{ + build ItCond; + result:8 = zext(Rn0003) / zext(Rm0003); + Rd0811 = result(0); +} + +:uxtab^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa5 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = Rn0003 + zext(tmp:1); +} + +:uxtab16^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa3 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ + build ItCond; + rotated:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + local tmp_b = rotated:1; + local tmpRn0003 = Rn0003; + tmpl:2 = tmpRn0003:2 + zext(tmp_b); + local tmph = (rotated >> 16); + tmp_b = tmph:1; + tmph = (tmpRn0003 >> 16) + zext(tmp_b); + Rd0811 = (tmph << 16) | zext(tmpl); +} + +:uxtah^ItCond Rd0811,Rn0003,Rm0003 is TMode=1 & ItCond & op4=0xfa1 & Rn0003; op12=15 & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = Rn0003 + zext(tmpRm0003:2); +} + +:uxtah^ItCond Rd0811,Rn0003,Rm0003,ByteRotate is TMode=1 & ItCond & op4=0xfa1 & Rn0003; op12=15 & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = Rn0003 + zext(tmp:2); +} + +@endif # VERSION_6T2 || VERSION_7 + +@if defined(VERSION_6) + +:uxtb^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=1 & thc0606=1 & Rm0305 & Rd0002 +{ + build ItCond; + local tmpRm0305 = Rm0305; + Rd0002 = zext(tmpRm0305:1); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:uxtb^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa5f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = zext(tmp:1); +} + +:uxtb^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa5f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = zext(tmpRm0003:1); +} + +:uxtb16^ItCond Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa3f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ + build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = tmp & 0x00ff00ff; +} + +:uxtb16^ItCond Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa3f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + Rd0811 = Rm0003 & 0x00ff00ff; +} + +@endif # VERSION_6T2 || VERSION_7 + +@if defined(VERSION_6) + +:uxth^ItCond Rd0002, Rm0305 is TMode=1 & ItCond & op8=0xb2 & thc0707=1 & thc0606=0 & Rm0305 & Rd0002 +{ + build ItCond; + local tmpRm0305 = Rm0305; + Rd0002 = zext(tmpRm0305:2); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:uxth^ItCond^".w" Rd0811, Rm0003, ByteRotate is TMode=1 & ItCond & op0=0xfa1f; op12=0xf & Rd0811 & thc0707=1 & ByteRotate & Rm0003 +{ build ItCond; + tmp:4 = (Rm0003 >> ByteRotate) | Rm0003 << ( 32 - ByteRotate); + Rd0811 = zext(tmp:2); +} + +:uxth^ItCond^".w" Rd0811, Rm0003 is TMode=1 & ItCond & op0=0xfa1f; op12=0xf & Rd0811 & thc0707=1 & throt=0 & Rm0003 +{ + build ItCond; + local tmpRm0003 = Rm0003; + Rd0811 = zext(tmpRm0003:2); +} + +@endif # VERSION_6T2 || VERSION_7 + +# V* see ARMneon.sinc + +@if defined(VERSION_6) + +:wfe^ItCond is TMode=1 & ItCond & op0=0xbf20 +{ + WaitForEvent(); +} + +:wfi^ItCond is TMode=1 & ItCond & op0=0xbf30 +{ + WaitForInterrupt(); +} + +:yield^ItCond is TMode=1 & ItCond & op0=0xbf10 +{ + HintYield(); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) || defined(VERSION_7) + +:wfe^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8002 +{ + WaitForEvent(); +} + +:wfi^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8003 +{ + WaitForInterrupt(); +} + +:yield^ItCond^".w" is TMode=1 & ItCond & op0=0xf3af; op0=0x8001 +{ + HintYield(); +} + +} # End with : ARMcondCk=1 +@endif # VERSION_6T2 || VERSION_7 diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.cspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.cspec new file mode 100644 index 00000000..5b6a05aa --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.cspec @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ; + offset = *:1 (lr + r3); + r3 = zext(offset); + + + if (inbounds) goto ; + offset = *:1 (lr + r12); + r3 = zext(offset); + + + r3 = r3 * 2; + + r12 = lr + r3; + + ISAModeSwitch = (r12 & 1) != 1; + TB = ISAModeSwitch; + pc = r12 & 0xfffffffe; + goto [pc]; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.pspec new file mode 100644 index 00000000..865bb586 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM_v45.pspec @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARM_win.cspec b/src/third-party/sleigh/processors/ARM/data/languages/ARM_win.cspec new file mode 100644 index 00000000..f4e1dc2d --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARM_win.cspec @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMinstructions.sinc b/src/third-party/sleigh/processors/ARM/data/languages/ARMinstructions.sinc new file mode 100644 index 00000000..e46a5be7 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMinstructions.sinc @@ -0,0 +1,6441 @@ +# Specification for the ARM Version 4, 4T, 5, 5T, 5E +# The following boolean defines control specific support: T_VARIANT, VERSION_5, VERSION_5E + +# +# WARNING NOTE: Be very careful taking a subpiece or truncating a register with :# or (#) +# The LEBE hybrid language causes endian issues if you do not assign the register to a temp +# variable and then take a subpiece or truncate. +# + +@if defined(SIMD) || defined(VFPv2) || defined(VFPv3) +@define INCLUDE_NEON "" # Neon instructions included with SIMD, VFPv2 or VFPv3 +@endif + +@if defined(T_VARIANT) +@define AMODE "TMode=0" # T_VARIANT must restrict ARM instruction decoding and require TMode=0 +@else +@define AMODE "epsilon" # THUMB instructions not supported - ARM only +@endif + +@if defined(T_VARIANT) +@define VERSION_5_or_T "" +@endif +@if defined(VERSION_5) +@define VERSION_5_or_T "" +@endif + +define token prefix (32) + pref=(0,31) +; + +define token instrArm (32) + cond=(28,31) + I25=(25,25) + P24=(24,24) + H24=(24,24) + L24=(24,24) + U23=(23,23) + B22=(22,22) + N22=(22,22) + S22=(22,22) + op=(21,24) + W21=(21,21) + S20=(20,20) + L20=(20,20) + Rn=(16,19) + RnLo=(0,3) + msb=(16,20) + satimm5=(16,20) + satimm4=(16,19) + mask=(16,19) + Rd=(12,15) + Rd2=(12,15) + CRd=(12,15) + CRn=(16,19) + CRm=(0,3) + RdHi=(16,19) + RdLo=(12,15) + smRd=(16,19) + smRa=(12,15) + smRm=(8,11) + smRn=(0,3) + immed12=(8,19) + Rs=(8,11) + rotate=(8,11) + immedH=(8,11) + cpn=(8,11) + opc1=(21,23) + opcode1=(20,23) + opc2=(5,7) + opcode2=(5,7) + opcode3=(4,7) + lsb=(7,11) + sftimm=(7,11) + sh=(6,6) + shft=(5,6) + immed24=(0,23) + addr24=(0,23) signed + offset_12=(0,11) + immed=(0,7) + srsMode=(0,4) + immedL=(0,3) + immed4=(0,3) + dbOption=(0,3) + ibOption=(0,3) + Rm=(0,3) + RmHi=(8,11) + Rm2=(0,3) + x=(5,5) + r=(5,5) + y=(6,6) + + # Advanced SIMD and VFP instruction fields + D22=(22,22) + N7=(7,7) + L7=(7,7) + Q6=(6,6) + M5=(5,5) + Qn0=(16,19) + Qd0=(12,15) + Qm0=(0,3) + Qn1=(16,19) + Qd1=(12,15) + Qm1=(0,3) + Dn0=(16,19) + Dd0=(12,15) + Dm0=(0,3) + Dn1=(16,19) + Dd1=(12,15) + Dm1=(0,3) + Dm_3=(0,2) + Dm_4=(0,3) + Sn0=(16,19) + Sd0=(12,15) + Sm0=(0,3) + Sm0next=(0,3) + Sn1=(16,19) + Sd1=(12,15) + Sm1=(0,3) + Sm1next=(0,3) + cmode=(8,11) + + + + # Arbitrary bit fields + bit31=(31,31) + bit30=(30,30) + bit29=(29,29) + bit28=(28,28) + c2831=(28,31) + c2627=(26,27) + c2531=(25,31) + c2527=(25,27) + c2525=(25,25) + c2427=(24,27) + c2424=(24,24) + c2331=(23,31) + c2327=(23,27) + c2324=(23,24) + c2323=(23,23) + c2222=(22,22) + c2131=(21,31) + c2127=(21,27) + c2124=(21,24) + c2123=(21,23) + c2122=(21,22) + c2121=(21,21) + c2027=(20,27) + c2024=(20,24) + c2022=(20,22) + c2021=(20,21) + c2020=(20,20) + c1921=(19,21) + c1919=(19,19) + c1821=(18,21) + c1819=(18,19) + c1818=(18,18) + c1721=(17,21) + c1719=(17,19) + c1718=(17,18) + c1717=(17,17) + c1631=(16,31) + c1627=(16,27) + c1621=(16,21) + c1620=(16,20) + c1619=(16,19) + c1618=(16,18) + c1617=(16,17) + c1616=(16,16) + c1515=(15,15) + c1415=(14,15) + c1414=(14,14) + c1315=(13,15) + c1313=(13,13) + c1215=(12,15) + c1212=(12,12) + c1115=(11,15) + c1111=(11,11) + c1015=(10,15) + c1011=(10,11) + c1010=(10,10) + c0916=(9,16) + c0915=(9,15) + c0911=(9,11) + c0909=(9,9) + c0815=(8,15) + c0811=(8,11) + c0809=(8,9) + c0808=(8,8) + c0715=(7,15) + c0711=(7,11) + c0709=(7,9) + c0708=(7,8) + c0707=(7,7) + c0615=(6,15) + c0611=(6,11) + c0607=(6,7) + c0606=(6,6) + c0515=(5,15) + c0508=(5,8) + c0507=(5,7) + c0506=(5,6) + c0505=(5,5) + c0431=(4,31) + c0427=(4,27) + c0415=(4,15) + c0411=(4,11) + c0409=(4,9) + c0408=(4,8) + c0407=(4,7) + c0406=(4,6) + c0405=(4,5) + c0404=(4,4) + c0315=(3,15) + c0303=(3,3) + c0215=(2,15) + c0202=(2,2) + c0115=(1,15) + c0101=(1,1) + c0031=(0,31) + c0027=(0,27) + c0014=(0,14) + c0013=(0,13) + c0012=(0,12) + c0011=(0,11) + c0010=(0,10) + c0009=(0,9) + c0008=(0,8) + c0007=(0,7) + c0006=(0,6) + c0005=(0,5) + c0004=(0,4) + c0003=(0,3) + c0002=(0,2) + c0001=(0,1) + c0000=(0,0) + +# +# 32-bit Thumb fields which correspond closely with ARM fields for +# certain coprocessor instructions +# + +@if ENDIAN == "little" + + # Advanced SIMD and VFP instruction fields for 32-bit Little Endian Thumb + thv_D22=(6,6) + thv_N7=(23,23) + thv_L7=(23,23) + thv_Q6=(22,22) + thv_M5=(21,21) + thv_Qn0=(0,3) + thv_Qd0=(28,31) + thv_Qm0=(16,19) + thv_Qn1=(0,3) + thv_Qd1=(28,31) + thv_Qm1=(16,19) + thv_Dn0=(0,3) + thv_Dd0=(28,31) + thv_Dd_1=(28,31) + thv_Dd_2=(28,31) + thv_Dd_3=(28,31) + thv_Dd_4=(28,31) + thv_Dd_5=(28,31) + thv_Dd_6=(28,31) + thv_Dd_7=(28,31) + thv_Dd_8=(28,31) + thv_Dd_9=(28,31) + thv_Dd_10=(28,31) + thv_Dd_11=(28,31) + thv_Dd_12=(28,31) + thv_Dd_13=(28,31) + thv_Dd_14=(28,31) + thv_Dd_15=(28,31) + thv_Dd_16=(28,31) + thv_Dm0=(16,19) + thv_Dn1=(0,3) + thv_Dd1=(28,31) + thv_Dm1=(16,19) + thv_Dm_3=(16,18) + thv_Dm_4=(16,19) + thv_Sn0=(0,3) + thv_Sd0=(28,31) + thv_Sm0=(16,19) + thv_Sm0next=(16,19) + thv_Sn1=(0,3) + thv_Sd1=(28,31) + thv_Sm1=(16,19) + thv_Sm1next=(16,19) + thv_cmode=(24,27) + + thv_Rd=(28,31) + thv_Rt=(28,31) + thv_Rn=(0,3) + thv_Rm=(16,19) + thv_Rt2=(24,27) + thv_immed=(16,23) + + # Arbitrary bit fields for 32-bit Little Endian Thumb + + thv_bit31=(15,15) + thv_bit30=(14,14) + thv_bit29=(13,13) + thv_bit28=(12,12) + thv_bit23=(7,7) + thv_bit21=(5,5) + thv_bit20=(4,4) + thv_bit07=(23,23) + thv_bit06=(22,22) + thv_bit00=(16,16) + thv_c2931=(13,15) + thv_c2831=(12,15) + thv_c2828=(12,12) + thv_c2627=(10,11) + thv_c2531=(9,15) + thv_c2527=(9,11) + thv_c2525=(9,9) + thv_c2427=(8,11) + thv_c2424=(8,8) + thv_c2331=(7,15) + thv_c2327=(7,11) + thv_c2324=(7,8) + thv_c2323=(7,7) + thv_c2222=(6,6) + thv_c2131=(5,15) + thv_c2127=(5,11) + thv_c2124=(5,8) + thv_c2123=(5,7) + thv_c2122=(5,6) + thv_c2121=(5,5) + thv_c2031=(4,15) + thv_c2027=(4,11) + thv_c2024=(4,8) + thv_c2022=(4,6) + thv_c2021=(4,5) + thv_c2020=(4,4) + thv_c1921=(3,5) + thv_c1919=(3,3) + thv_c1821=(2,5) + thv_c1819=(2,3) + thv_c1818=(2,2) + thv_c1721=(1,5) + thv_c1719=(1,3) + thv_c1718=(1,2) + thv_c1717=(1,1) + thv_c1631=(0,15) + thv_c1627=(0,11) + thv_c1621=(0,5) + thv_c1620=(0,4) + thv_c1619=(0,3) + thv_c1618=(0,2) + thv_c1617=(0,1) + thv_c1616=(0,0) + thv_c1515=(31,31) + thv_c1415=(30,31) + thv_c1414=(30,30) + thv_c1313=(29,29) + thv_c1215=(28,31) + thv_c1212=(28,28) + thv_c1111=(27,27) + thv_c1011=(26,27) + thv_c1010=(26,26) + thv_c0911=(25,27) + thv_c0909=(25,25) + thv_c0811=(24,27) + thv_c0809=(24,25) + thv_c0808=(24,24) + thv_c0711=(23,27) + thv_c0709=(23,25) + thv_c0708=(23,24) + thv_c0707=(23,23) + thv_c0611=(22,27) + thv_c0607=(22,23) + thv_c0606=(22,22) + thv_c0508=(21,24) + thv_c0507=(21,23) + thv_c0506=(21,22) + thv_c0505=(21,21) + thv_c0431=(4,31) + thv_c0427=(4,27) + thv_c0411=(20,27) + thv_c0409=(20,25) + thv_c0407=(20,23) + thv_c0406=(20,22) + thv_c0405=(20,21) + thv_c0404=(20,20) + thv_c0303=(19,19) + thv_c0215=(18,31) + thv_c0202=(18,18) + thv_c0101=(17,17) + thv_c0104=(17,20) + thv_c0031=(0,31) + thv_c0027=(0,27) + thv_c0015=(16,31) + thv_c0011=(16,27) + thv_c0010=(16,26) + thv_c0008=(16,24) + thv_c0007=(16,23) + thv_c0006=(16,22) + thv_c0004=(16,20) + thv_c0003=(16,19) + thv_c0001=(16,17) + thv_c0000=(16,16) + thv_option=(16,19) + +@else # ENDIAN == "big" + + # Advanced SIMD and VFP instruction fields for 32-bit Big Endian Thumb + thv_D22=(22,22) + thv_N7=(7,7) + thv_L7=(7,7) + thv_Q6=(6,6) + thv_M5=(5,5) + thv_Qn0=(16,19) + thv_Qd0=(12,15) + thv_Qm0=(0,3) + thv_Qn1=(16,19) + thv_Qd1=(12,15) + thv_Qm1=(0,3) + thv_Dn0=(16,19) + thv_Dd0=(12,15) + thv_Dd_1=(12,15) + thv_Dd_2=(12,15) + thv_Dd_3=(12,15) + thv_Dd_4=(12,15) + thv_Dd_5=(12,15) + thv_Dd_6=(12,15) + thv_Dd_7=(12,15) + thv_Dd_8=(12,15) + thv_Dd_9=(12,15) + thv_Dd_10=(12,15) + thv_Dd_11=(12,15) + thv_Dd_12=(12,15) + thv_Dd_13=(12,15) + thv_Dd_14=(12,15) + thv_Dd_15=(12,15) + thv_Dd_16=(12,15) + thv_Dm0=(0,3) + thv_Dn1=(16,19) + thv_Dd1=(12,15) + thv_Dm1=(0,3) + thv_Dm_3=(0,2) + thv_Dm_4=(0,3) + thv_Sn0=(16,19) + thv_Sd0=(12,15) + thv_Sm0=(0,3) + thv_Sm0next=(0,3) + thv_Sn1=(16,19) + thv_Sd1=(12,15) + thv_Sm1=(0,3) + thv_Sm1next=(0,3) + thv_cmode=(8,11) + + thv_Rd=(12,15) + thv_Rt=(12,15) + thv_Rn=(16,19) + thv_Rm=(0,3) + thv_Rt2=(8,11) + thv_immed=(0,7) + + # Arbitrary bit fields for 32-bit Big Endian Thumb + thv_bit31=(31,31) + thv_bit30=(30,30) + thv_bit29=(29,29) + thv_bit28=(28,28) + thv_bit23=(23,23) + thv_bit21=(21,21) + thv_bit20=(20,20) + thv_bit07=(7,7) + thv_bit06=(6,6) + thv_bit00=(0,0) + thv_c2931=(29,31) + thv_c2831=(28,31) + thv_c2828=(28,28) + thv_c2627=(26,27) + thv_c2531=(25,31) + thv_c2527=(25,27) + thv_c2525=(25,25) + thv_c2427=(24,27) + thv_c2424=(24,24) + thv_c2331=(23,31) + thv_c2327=(23,27) + thv_c2324=(23,24) + thv_c2323=(23,23) + thv_c2222=(22,22) + thv_c2131=(21,31) + thv_c2127=(21,27) + thv_c2124=(21,24) + thv_c2123=(21,23) + thv_c2122=(21,22) + thv_c2121=(21,21) + thv_c2031=(20,31) + thv_c2027=(20,27) + thv_c2024=(20,24) + thv_c2022=(20,22) + thv_c2021=(20,21) + thv_c2020=(20,20) + thv_c1921=(19,21) + thv_c1919=(19,19) + thv_c1821=(18,21) + thv_c1819=(18,19) + thv_c1818=(18,18) + thv_c1721=(17,21) + thv_c1719=(17,19) + thv_c1718=(17,18) + thv_c1717=(17,17) + thv_c1631=(16,31) + thv_c1627=(16,27) + thv_c1621=(16,21) + thv_c1620=(16,20) + thv_c1619=(16,19) + thv_c1618=(16,18) + thv_c1617=(16,17) + thv_c1616=(16,16) + thv_c1515=(15,15) + thv_c1415=(14,15) + thv_c1414=(14,14) + thv_c1313=(13,13) + thv_c1215=(12,15) + thv_c1212=(12,12) + thv_c1111=(11,11) + thv_c1011=(10,11) + thv_c1010=(10,10) + thv_c0911=(9,11) + thv_c0909=(9,9) + thv_c0811=(8,11) + thv_c0809=(8,9) + thv_c0808=(8,8) + thv_c0711=(7,11) + thv_c0709=(7,9) + thv_c0708=(7,8) + thv_c0707=(7,7) + thv_c0611=(6,11) + thv_c0607=(6,7) + thv_c0606=(6,6) + thv_c0508=(5,8) + thv_c0507=(5,7) + thv_c0506=(5,6) + thv_c0505=(5,5) + thv_c0431=(4,31) + thv_c0427=(4,27) + thv_c0411=(4,11) + thv_c0409=(4,9) + thv_c0407=(4,7) + thv_c0406=(4,6) + thv_c0405=(4,5) + thv_c0404=(4,4) + thv_c0303=(3,3) + thv_c0215=(2,15) + thv_c0202=(2,2) + thv_c0101=(1,1) + thv_c0104=(1,4) + thv_c0031=(0,31) + thv_c0027=(0,27) + thv_c0015=(0,15) + thv_c0011=(0,11) + thv_c0010=(0,10) + thv_c0008=(0,8) + thv_c0007=(0,7) + thv_c0006=(0,6) + thv_c0004=(0,4) + thv_c0003=(0,3) + thv_c0001=(0,1) + thv_c0000=(0,0) + thv_option=(0,3) + +@endif # ENDIAN = "big" + +; + +attach variables [ Rn Rd Rs Rm RdHi RdLo smRd smRn smRm smRa RmHi RnLo ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ]; +attach variables [ Rd2 Rm2 ] [ r1 _ r3 _ r5 _ r7 _ r9 _ r11 _ sp _ _ _ ]; # see LDREXD +attach variables [ CRd CRn CRm ] [ cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15 ]; +attach variables [ thv_Rd thv_Rn thv_Rt thv_Rt2 ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ]; + +attach names [ cpn ] [ p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 ]; +attach names [ ibOption ] [ opt0 opt1 opt2 opt3 opt4 opt5 opt6 opt7 opt8 opt9 opt10 opt11 opt12 opt13 opt14 SY ]; +attach names [ dbOption ] [ opt0 opt1 OSHST OSH opt4 opt5 NSHST NSH opt8 opt9 ISHST ISH opt12 opt13 ST SY ]; + +macro addflags(op1,op2) { + tmpCY = carry(op1,op2); + tmpOV = scarry(op1,op2); +} + +# NOTE: unlike x86, carry flag is SET if there is NO borrow +macro subflags(op1,op2) { + tmpCY = op2 <= op1; + tmpOV = sborrow(op1,op2); +} + +macro logicflags() { + tmpCY = shift_carry; + tmpOV = OV; +} + +macro CVunaffected() { + tmpCY = CY; + tmpOV = OV; +} + +macro resultflags(result) { + tmpNG = result s< 0; + tmpZR = result == 0; +} + +rn: pc is pc & c1619=15 { tmp:4 = inst_start+8; export tmp; } +rn: Rn is Rn { export Rn; } + +rm: pc is pc & Rm=15 { tmp:4 = inst_start+8; export tmp; } +rm: Rm is Rm { export Rm; } + +rs: pc is pc & Rs=15 { tmp:4 = inst_start+8; export tmp; } +rs: Rs is Rs { export Rs; } + +cc: "eq" is cond=0 { export ZR; } +cc: "ne" is cond=1 { tmp:1 = !ZR; export tmp; } +cc: "cs" is cond=2 { export CY; } +cc: "cc" is cond=3 { tmp:1 = !CY; export tmp; } +cc: "mi" is cond=4 { export NG; } +cc: "pl" is cond=5 { tmp:1 = !NG; export tmp; } +cc: "vs" is cond=6 { export OV; } +cc: "vc" is cond=7 { tmp:1 = !OV; export tmp; } +cc: "hi" is cond=8 { tmp:1 = CY && (!ZR); export tmp; } +cc: "ls" is cond=9 { tmp:1 = (!CY) || ZR; export tmp; } +cc: "ge" is cond=10 { tmp:1 = (NG==OV); export tmp; } +cc: "lt" is cond=11 { tmp:1 = (NG!=OV); export tmp; } +cc: "gt" is cond=12 { tmp:1 = (!ZR) && (NG==OV); export tmp; } +cc: "le" is cond=13 { tmp:1 = ZR || (NG!=OV); export tmp; } + +COND: cc is $(AMODE) & cc { if (!cc) goto inst_next; } # Execute conditionally +COND: is $(AMODE) & cond=14 { } # Always execute +#COND: is $(AMODE) & cond=15 { } # Always execute - deprecated, should not be used. + +@if defined(INCLUDE_NEON) # Unconditional Neon Thumb instructions share many Conditional Neon ARM constructors +COND: ItCond is TMode=1 & thv_c2831=14 & cond & ItCond { } # ItCond execute +#COND: ItCond is TMode=1 & thv_c2831=15 & cond & ItCond { } # ItCond execute +@endif + +SBIT_CZNO: is S20=0 { } # Do nothing to the flag bits +SBIT_CZNO: "s" is S20=1 { CY = tmpCY; ZR = tmpZR; NG = tmpNG; OV = tmpOV; } +SBIT_ZN: is S20=0 { } # Do nothing to the flag bits +SBIT_ZN: "s" is S20=1 { ZR = tmpZR; NG = tmpNG; } + +Addr24: reloc is addr24 [ reloc = (inst_next+4) + (4*addr24); ] { export *[ram]:4 reloc; } + +# see blx(1) instruction +@if defined(T_VARIANT) && defined(VERSION_5) + +HAddr24: reloc is addr24 & H24 + [ reloc = ((inst_next+4) + (4*addr24) + (2*H24)) & 0xFFFFFFFF; TMode=1; globalset(reloc,TMode); ] + { export *[ram]:4 reloc; } +@endif # T_VARIANT && VERSION_5 + +@if defined(VERSION_5E) + +XBIT: "b" is x=0 & smRn { local tmpRn = smRn; tmp:2 = tmpRn:2; export tmp; } +XBIT: "t" is x=1 & smRn { local tmpRn = smRn; tmp:2 = tmpRn(2); export tmp; } + +YBIT: "b" is y=0 & smRm { local tmpRm = smRm; tmp:2 = tmpRm:2; export tmp; } +YBIT: "t" is y=1 & smRm { local tmpRm = smRm; tmp:2 = tmpRm(2); export tmp; } + +@endif # VERSION_5E + + + +##################### +###### shift1 ###### +##################### + +shift1: "#"^value is I25=1 & immed & rotate + [ value=((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff; ] +{ + local tmp:4 = (value >> 31); shift_carry = ((rotate == 0:1) && CY) || ((rotate != 0:1) && tmp(0)); export *[const]:4 value; +} + +#################### +define pcodeop coproc_moveto_Main_ID; +define pcodeop coproc_moveto_Cache_Type; +define pcodeop coproc_moveto_TCM_Status; +define pcodeop coproc_moveto_TLB_Type; +define pcodeop coproc_moveto_Control; +define pcodeop coproc_moveto_Auxiliary_Control; +define pcodeop coproc_moveto_Coprocessor_Access_Control; +define pcodeop coproc_moveto_Secure_Configuration; +define pcodeop coproc_moveto_Secure_Debug_Enable; +define pcodeop coproc_moveto_NonSecure_Access_Control; +define pcodeop coproc_moveto_Translation_table_base_0; +define pcodeop coproc_moveto_Translation_table_base_1; +define pcodeop coproc_moveto_Translation_table_control; +define pcodeop coproc_moveto_Domain_Access_Control; +define pcodeop coproc_moveto_Data_Fault_Status; +define pcodeop coproc_moveto_Instruction_Fault_Status; +define pcodeop coproc_moveto_Instruction_Fault_Address; +define pcodeop coproc_moveto_Fault_Address; +define pcodeop coproc_moveto_Instruction_Fault; +define pcodeop coproc_moveto_Wait_for_interrupt; +define pcodeop coproc_moveto_Invalidate_Entire_Instruction; +define pcodeop coproc_moveto_Invalidate_Instruction_Cache_by_MVA; +define pcodeop coproc_moveto_Flush_Prefetch_Buffer; +define pcodeop coproc_moveto_Invalidate_Entire_Data_cache; +define pcodeop coproc_moveto_Invalidate_Entire_Data_by_MVA; +define pcodeop coproc_moveto_Invalidate_Entire_Data_by_Index; +define pcodeop coproc_moveto_Clean_Entire_Data_Cache; +define pcodeop coproc_moveto_Clean_Data_Cache_by_MVA; +define pcodeop coproc_moveto_Clean_Data_Cache_by_Index; +define pcodeop coproc_moveto_Data_Synchronization; +define pcodeop coproc_moveto_Data_Memory_Barrier; +define pcodeop coproc_moveto_Invalidate_Entire_Data_Cache; +define pcodeop coproc_moveto_Invalidate_Data_Cache_by_MVA; +define pcodeop coproc_moveto_Invalidate_unified_TLB_unlocked; +define pcodeop coproc_moveto_Invalidate_unified_TLB_by_MVA; +define pcodeop coproc_moveto_Invalidate_unified_TLB_by_ASID_match; +define pcodeop coproc_moveto_FCSE_PID; +define pcodeop coproc_moveto_Context_ID; +define pcodeop coproc_moveto_User_RW_Thread_and_Process_ID; +define pcodeop coproc_moveto_User_R_Thread_and_Process_ID; +define pcodeop coproc_moveto_Privileged_only_Thread_and_Process_ID; +define pcodeop coproc_moveto_Peripherial_Port_Memory_Remap; +define pcodeop coproc_moveto_Feature_Identification; +define pcodeop coproc_moveto_ISA_Feature_Identification; +define pcodeop coproc_moveto_Peripheral_Port_Memory_Remap; +define pcodeop coproc_moveto_Control_registers; +define pcodeop coproc_moveto_Security_world_control; +define pcodeop coproc_moveto_Translation_table; +define pcodeop coproc_moveto_Instruction_cache; +define pcodeop coproc_moveto_Data_cache_operations; +define pcodeop coproc_moveto_Identification_registers; +define pcodeop coproc_moveto_Peripheral_System; + +define pcodeop coproc_movefrom_Main_ID; +define pcodeop coproc_movefrom_Cache_Type; +define pcodeop coproc_movefrom_TCM_Status; +define pcodeop coproc_movefrom_TLB_Type; +define pcodeop coproc_movefrom_Control; +define pcodeop coproc_movefrom_Auxiliary_Control; +define pcodeop coproc_movefrom_Coprocessor_Access_Control; +define pcodeop coproc_movefrom_Secure_Configuration; +define pcodeop coproc_movefrom_Secure_Debug_Enable; +define pcodeop coproc_movefrom_NonSecure_Access_Control; +define pcodeop coproc_movefrom_Translation_table_base_0; +define pcodeop coproc_movefrom_Translation_table_base_1; +define pcodeop coproc_movefrom_Translation_table_control; +define pcodeop coproc_movefrom_Domain_Access_Control; +define pcodeop coproc_movefrom_Data_Fault_Status; +define pcodeop coproc_movefrom_Instruction_Fault; +define pcodeop coproc_movefrom_Fault_Address; +define pcodeop coproc_movefrom_Instruction_Fault_Status; +define pcodeop coproc_movefrom_Instruction_Fault_Address; +define pcodeop coproc_movefrom_Wait_for_interrupt; +define pcodeop coproc_movefrom_Invalidate_Entire_Instruction; +define pcodeop coproc_movefrom_Invalidate_Instruction_Cache_by_MVA; +define pcodeop coproc_movefrom_Flush_Prefetch_Buffer; +define pcodeop coproc_movefrom_Invalidate_Entire_Data_cache; +define pcodeop coproc_movefrom_Invalidate_Entire_Data_by_MVA; +define pcodeop coproc_movefrom_Invalidate_Entire_Data_by_Index; +define pcodeop coproc_movefrom_Clean_Entire_Data_Cache; +define pcodeop coproc_movefrom_Clean_Data_Cache_by_MVA; +define pcodeop coproc_movefrom_Clean_Data_Cache_by_Index; +define pcodeop coproc_movefrom_Data_Synchronization; +define pcodeop coproc_movefrom_Data_Memory_Barrier; +define pcodeop coproc_movefrom_Invalidate_Entire_Data_Cache; +define pcodeop coproc_movefrom_Invalidate_Data_Cache_by_MVA; +define pcodeop coproc_movefrom_Invalidate_unified_TLB_unlocked; +define pcodeop coproc_movefrom_Invalidate_unified_TLB_by_MVA; +define pcodeop coproc_movefrom_Invalidate_unified_TLB_by_ASID_match; +define pcodeop coproc_movefrom_FCSE_PID; +define pcodeop coproc_movefrom_Context_ID; +define pcodeop coproc_movefrom_User_RW_Thread_and_Process_ID; +define pcodeop coproc_movefrom_User_R_Thread_and_Process_ID; +define pcodeop coproc_movefrom_Privileged_only_Thread_and_Process_ID; +define pcodeop coproc_movefrom_Peripherial_Port_Memory_Remap; +define pcodeop coproc_movefrom_Feature_Identification; +define pcodeop coproc_movefrom_ISA_Feature_Identification; +define pcodeop coproc_movefrom_Peripheral_Port_Memory_Remap; +define pcodeop coproc_movefrom_Control_registers; +define pcodeop coproc_movefrom_Security_world_control; +define pcodeop coproc_movefrom_Translation_table; +define pcodeop coproc_movefrom_Instruction_cache; +define pcodeop coproc_movefrom_Data_cache_operations; +define pcodeop coproc_movefrom_Identification_registers; +define pcodeop coproc_movefrom_Peripheral_System; + +mcrOperands: cpn,opc1,Rd,CRn,CRm,opc2 is CRm & opc2 & cpn & CRn & opc1 & Rd { } + +##################### +###### shift2 ###### +##################### + +shift2: rm is I25=0 & sftimm=0 & c0406=0 & rm +{ + shift_carry = CY; export rm; +} + +shift2: rm, "lsl #"^sftimm is I25=0 & sftimm & c0406=0 & rm +{ + local tmp1=(rm>>(32-sftimm))&1; shift_carry=tmp1(0); local tmp2=rm<>31); shift_carry=tmp1(0); tmp2:4=0; export tmp2; +} + +shift2: rm, "lsr #"^sftimm is I25=0 & sftimm & c0406=2 & rm +{ + local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm>>sftimm; export tmp2; +} + +shift2: rm, "asr #32" is I25=0 & sftimm=0 & c0406=4 & rm +{ + local tmp1=(rm>>31); shift_carry=tmp1(0); local tmp2 = rm s>> 32; export tmp2; +} + +shift2: rm, "asr #"^sftimm is I25=0 & sftimm & c0406=4 & rm +{ + local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm s>> sftimm; export tmp2; +} + +shift2: rm, "rrx" is I25=0 & c0411=6 & rm +{ + local tmp1=rm&1; shift_carry=tmp1(0); local tmp2 = (zext(CY)<<31)|(rm>>1); export tmp2; +} + +shift2: rm, "ror #"^sftimm is I25=0 & sftimm & c0406=6 & rm +{ + local tmp1=(rm>>sftimm)|(rm<<(32-sftimm)); local tmp2=(tmp1>>31)&1; shift_carry=tmp2(0); export tmp1; +} + +##################### +###### shift3 ###### +##################### + +shift3: rm, "lsl "^rs is I25=0 & rs & c0407=1 & rm +{ + local sa=rs&0xff; local tmp1=(rm>>(32-sa))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm<>(sa-1))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm>>sa; export tmp2; +} + +shift3: rm, "asr "^rs is I25=0 & rs & c0407=5 & rm +{ + local sa=rs&0xff; local tmp1=(rm s>>(sa-1))&1; shift_carry=((sa==0:4)&&CY) || ((sa!=0:4)&&tmp1(0)); local tmp2=rm s>> sa; export tmp2; +} + +shift3: rm, "ror "^rs is I25=0 & rs & c0407=7 & rm +{ + local sa=rs&0x1f; local tmp1=(rm>>sa)|(rm<<(32-sa)); local tmp2=tmp1>>31; shift_carry=(((rs&0xff)==0:4)&&CY) || (((rs&0xff)!=0:4)&&tmp2(0)); export tmp1; +} + + +##################### +###### shift4 ###### +##################### +@if defined(VERSION_6) + +shift4: rm is sftimm=0 & sh=0 & rm +{ + shift_carry = CY; export rm; +} + +shift4: rm, "lsl #"^sftimm is sftimm & sh=0 & rm +{ + local tmp1=(rm>>(32-sftimm))&1; shift_carry=tmp1(0); local tmp2=rm<>31); shift_carry=tmp1(0); local tmp2 = rm s>> 32; export tmp2; +} + +shift4: rm, "asr #"^sftimm is sftimm & sh=1 & rm +{ + local tmp1=(rm>>(sftimm-1))&1; shift_carry=tmp1(0); local tmp2=rm s>> sftimm; export tmp2; +} + +@endif # VERSION_6 + +##################### +###### ror1 ###### +##################### +@if defined(VERSION_6) + +ror1: rm is c1011=0 & rm +{ + local tmp = rm; + export tmp; +} + +ror1: rm, "ror #8" is c1011=1 & rm +{ + local tmp = (rm <<24)| (rm >> 8); + export tmp; +} + +ror1: rm, "ror #16" is c1011=2 & rm +{ + local tmp = (rm << 16) | (rm >> 16); + export tmp; +} + +ror1: rm, "ror #24" is c1011=3 & rm +{ + local tmp = (rm << 8) | (rm >> 24); + export tmp; +} + +@endif # VERSION_6 + +##################### +# addrmode2 is the resulting address for Addressing Mode 2 +# it takes care of bits 27-0, except for the B and L flags and the Rd register +# the Rn register is taken care of including any possible write-back +# it returns a varnode containing the address +##################### + +# addr2shift is the register rm shifting portion of Addressing Mode 2 +addr2shift: rm is c0411=0 & rm { export rm; } +addr2shift: rm,"lsl #"^sftimm is sftimm & shft=0 & c0404=0 & rm { local tmp = rm << sftimm; export tmp; } +addr2shift: rm,"lsr #"^sftimm is sftimm & shft=1 & c0404=0 & rm { local tmp = rm >> sftimm; export tmp; } +addr2shift: rm,"lsr #32" is sftimm=0 & shft=1 & c0404=0 & rm { tmp:4 = 0; export tmp; } +addr2shift: rm,"asr #"^sftimm is sftimm & shft=2 & c0404=0 & rm { local tmp = rm s>> sftimm; export tmp; } +addr2shift: rm,"asr #32" is sftimm=0 & shft=2 & c0404=0 & rm { local tmp = rm s>> 32; export tmp; } +addr2shift: rm,"ror #"^sftimm is sftimm & shft=3 & c0404=0 & rm { local tmp = (rm>>sftimm) | (rm<<(32-sftimm)); export tmp; } +addr2shift: rm,"rrx" is sftimm=0 & shft=3 & c0404=0 & rm { tmp:4 = zext(CY); tmp = (tmp<<31) | (rm>>1); export tmp; } + + # no writeback + +addrmode2: [reloff] is I25=0 & P24=1 & U23=1 & W21=0 & c1619=15 & offset_12 + [ reloff = inst_start + 8 + offset_12; ] +{ + export *[const]:4 reloff; +} + +addrmode2: [reloff] is I25=0 & P24=1 & U23=0 & W21=0 & c1619=15 & offset_12 + [ reloff = inst_start + 8 - offset_12; ] +{ + export *[const]:4 reloff; +} + +addrmode2: [rn,"#"^offset_12] is I25=0 & P24=1 & U23=1 & W21=0 & rn & offset_12 { local tmp = rn + offset_12; export tmp; } +addrmode2: [rn,"#"^noff] is I25=0 & P24=1 & U23=0 & W21=0 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn + noff; export tmp; } +addrmode2: [rn,addr2shift] is I25=1 & P24=1 & U23=1 & W21=0 & rn & addr2shift { local tmp = rn + addr2shift; export tmp; } +addrmode2: [rn,-addr2shift] is I25=1 & P24=1 & U23=0 & W21=0 & rn & addr2shift { local tmp = rn - addr2shift; export tmp; } + # pre-indexed writeback +addrmode2: [rn,"#"^offset_12]! is I25=0 & P24=1 & U23=1 & W21=1 & rn & offset_12 { rn = rn + offset_12; export rn; } +addrmode2: [rn,"#"^noff]! is I25=0 & P24=1 & U23=0 & W21=1 & rn & offset_12 [ noff = -offset_12; ] { rn = rn + noff; export rn; } +addrmode2: [rn,addr2shift]! is I25=1 & P24=1 & U23=1 & W21=1 & rn & addr2shift { rn = rn + addr2shift; export rn; } +addrmode2: [rn,-addr2shift]! is I25=1 & P24=1 & U23=0 & W21=1 & rn & addr2shift { rn = rn - addr2shift; export rn; } + # post-indexed writeback +addrmode2: [rn],"#"^offset_12 is I25=0 & P24=0 & U23=1 & W21=0 & rn & offset_12 { local tmp = rn; rn = rn + offset_12; export tmp; } +addrmode2: [rn],"#"^noff is I25=0 & P24=0 & U23=0 & W21=0 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn; rn = rn + noff; export tmp; } +addrmode2: [rn],addr2shift is I25=1 & P24=0 & U23=1 & W21=0 & rn & addr2shift { local tmp = rn; rn = rn + addr2shift; export tmp; } +addrmode2: [rn],-addr2shift is I25=1 & P24=0 & U23=0 & W21=0 & rn & addr2shift { local tmp = rn; rn = rn - addr2shift; export tmp; } + # special-form post-indexed writeback for ldrbt, ldrt, strbt, etc. +addrmode2: [rn],"#"^offset_12 is I25=0 & P24=0 & U23=1 & W21=1 & rn & offset_12 { local tmp = rn; rn = rn + offset_12; export tmp; } +addrmode2: [rn],"#"^noff is I25=0 & P24=0 & U23=0 & W21=1 & rn & offset_12 [ noff = -offset_12; ] { local tmp = rn; rn = rn + noff; export tmp; } +addrmode2: [rn],addr2shift is I25=1 & P24=0 & U23=1 & W21=1 & rn & addr2shift { local tmp = rn; rn = rn + addr2shift; export tmp; } +addrmode2: [rn],-addr2shift is I25=1 & P24=0 & U23=0 & W21=1 & rn & addr2shift { local tmp = rn; rn = rn - addr2shift; export tmp; } + +########################### +# addrmode3 is the resulting address for Addressing Mode 3 +# it takes care of bits 27-0, except for the L, S, and H flags and the Rd register +# the Rn register is taken care of including any possible write-back +# it returns a varnode containing the address +########################### + +addrmode3: [reloff] is P24=1 & U23=1 & c2122=2 & c1619=15 & immedH & c0707=1 & c0404=1 & immedL + [ reloff=inst_start+8+((immedH<<4) | immedL);] +{ + export *:4 reloff; +} + +addrmode3: [reloff] is P24=1 & U23=0 & c2122=2 & c1619=15 & immedH & c0707=1 & c0404=1 & immedL + [ reloff=inst_start+8-((immedH<<4) | immedL);] +{ + export *:4 reloff; +} + +addrmode3: [rn,"#"^off8] is P24=1 & U23=1 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL + [ off8=(immedH<<4)|immedL;] +{ + local tmp = rn + off8; export tmp; +} + +addrmode3: [rn,"#"^noff8] is P24=1 & U23=0 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL + [ noff8=-((immedH<<4)|immedL);] +{ + local tmp = rn + noff8; export tmp; +} + +addrmode3: [rn,rm] is P24=1 & U23=1 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + local tmp = rn + rm; export tmp; +} + +addrmode3: [rn,-rm] is P24=1 & U23=0 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + local tmp = rn - rm; export tmp; +} + +addrmode3: [rn,"#"^off8]! is P24=1 & U23=1 & c2122=3 & rn & immedH & c0707=1 & c0404=1 & immedL + [ off8=(immedH<<4)|immedL;] +{ + rn=rn + off8; export rn; +} + +addrmode3: [rn,"#"^noff8]! is P24=1 & U23=0 & c2122=3 & rn & immedH & c0707=1 & c0404=1 & immedL + [ noff8=-((immedH<<4)|immedL);] +{ + rn=rn + noff8; export rn; +} + +addrmode3: [rn,rm]! is P24=1 & U23=1 & c2122=1 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + rn = rn+rm; export rn; +} + +addrmode3: [rn,-rm]! is P24=1 & U23=0 & c2122=1 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + rn = rn - rm; export rn; +} + +addrmode3: [rn],"#"^off8 is P24=0 & U23=1 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL + [ off8=(immedH<<4)|immedL;] +{ + local tmp=rn; rn=rn + off8; export tmp; +} + +addrmode3: [rn],"#"^noff8 is P24=0 & U23=0 & c2122=2 & rn & immedH & c0707=1 & c0404=1 & immedL + [ noff8=-((immedH<<4)|immedL);] +{ + local tmp=rn; rn=rn + noff8; export tmp; +} + +addrmode3: [rn],rm is P24=0 & U23=1 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + local tmp=rn; rn=rn+rm; export tmp; +} + +addrmode3: [rn],-rm is P24=0 & U23=0 & c2122=0 & rn & c0811=0 & c0707=1 & c0404=1 & rm +{ + local tmp=rn; rn=rn-rm; export tmp; +} + +############################ +# Addressing Mode 4. These 4 types take care of the register_list argument in Addressing Mode 4. +############################ + + +# ldlist_inc is the list of registers to be loaded using IA or IB in Addressing Mode 4 +linc15: r0 is c0000=1 & r0 { r0 = * mult_addr; mult_addr = mult_addr + 4; } +linc15: is c0000=0 { } +linc14: linc15 r1 is c0101=1 & linc15 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; } +linc14: r1 is c0101=1 & c0000=0 & r1 { r1 = * mult_addr; mult_addr = mult_addr + 4; } +linc14: linc15 is c0101=0 & linc15 { } +linc13: linc14 r2 is c0202=1 & linc14 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; } +linc13: r2 is c0202=1 & c0001=0 & r2 { r2 = * mult_addr; mult_addr = mult_addr + 4; } +linc13: linc14 is c0202=0 & linc14 { } +linc12: linc13 r3 is c0303=1 & linc13 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; } +linc12: r3 is c0303=1 & c0002=0 & r3 { r3 = * mult_addr; mult_addr = mult_addr + 4; } +linc12: linc13 is c0303=0 & linc13 { } +linc11: linc12 r4 is c0404=1 & linc12 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; } +linc11: r4 is c0404=1 & c0003=0 & r4 { r4 = * mult_addr; mult_addr = mult_addr + 4; } +linc11: linc12 is c0404=0 & linc12 { } +linc10: linc11 r5 is c0505=1 & linc11 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; } +linc10: r5 is c0505=1 & c0004=0 & r5 { r5 = * mult_addr; mult_addr = mult_addr + 4; } +linc10: linc11 is c0505=0 & linc11 { } +linc9: linc10 r6 is c0606=1 & linc10 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; } +linc9: r6 is c0606=1 & c0005=0 & r6 { r6 = * mult_addr; mult_addr = mult_addr + 4; } +linc9: linc10 is c0606=0 & linc10 { } +linc8: linc9 r7 is c0707=1 & linc9 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; } +linc8: r7 is c0707=1 & c0006=0 & r7 { r7 = * mult_addr; mult_addr = mult_addr + 4; } +linc8: linc9 is c0707=0 & linc9 { } +linc7: linc8 r8 is c0808=1 & linc8 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; } +linc7: r8 is c0808=1 & c0007=0 & r8 { r8 = * mult_addr; mult_addr = mult_addr + 4; } +linc7: linc8 is c0808=0 & linc8 { } +linc6: linc7 r9 is c0909=1 & linc7 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; } +linc6: r9 is c0909=1 & c0008=0 & r9 { r9 = * mult_addr; mult_addr = mult_addr + 4; } +linc6: linc7 is c0909=0 & linc7 { } +linc5: linc6 r10 is c1010=1 & linc6 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; } +linc5: r10 is c1010=1 & c0009=0 & r10 { r10 = * mult_addr; mult_addr = mult_addr + 4; } +linc5: linc6 is c1010=0 & linc6 { } +linc4: linc5 r11 is c1111=1 & linc5 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; } +linc4: r11 is c1111=1 & c0010=0 & r11 { r11 = * mult_addr; mult_addr = mult_addr + 4; } +linc4: linc5 is c1111=0 & linc5 { } +linc3: linc4 r12 is c1212=1 & linc4 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; } +linc3: r12 is c1212=1 & c0011=0 & r12 { r12 = * mult_addr; mult_addr = mult_addr + 4; } +linc3: linc4 is c1212=0 & linc4 { } +linc2: linc3 sp is c1313=1 & linc3 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; } +linc2: sp is c1313=1 & c0012=0 & sp { sp = * mult_addr; mult_addr = mult_addr + 4; } +linc2: linc3 is c1313=0 & linc3 { } +linc1: linc2 lr is c1414=1 & linc2 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; } +linc1: lr is c1414=1 & c0013=0 & lr { lr = * mult_addr; mult_addr = mult_addr + 4; } +linc1: linc2 is c1414=0 & linc2 { } +linc0: linc1 pc is c1515=1 & linc1 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; } +linc0: pc is c1515=1 & c0014=0 & pc { pc = * mult_addr; mult_addr = mult_addr + 4; } +linc0: linc1 is c1515=0 & linc1 { } +ldlist_inc: {linc0} is linc0 { } + +# stlist_inc is the list of registers to be stored using IA or IB in Addressing Mode 4 +sinc15: r0 is c0000=1 & r0 { * mult_addr = r0; mult_addr = mult_addr + 4; } +sinc15: is c0000=0 { } +sinc14: sinc15 r1 is c0101=1 & sinc15 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; } +sinc14: r1 is c0101=1 & c0000=0 & r1 { * mult_addr = r1; mult_addr = mult_addr + 4; } +sinc14: sinc15 is c0101=0 & sinc15 { } +sinc13: sinc14 r2 is c0202=1 & sinc14 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; } +sinc13: r2 is c0202=1 & c0001=0 & r2 { * mult_addr = r2; mult_addr = mult_addr + 4; } +sinc13: sinc14 is c0202=0 & sinc14 { } +sinc12: sinc13 r3 is c0303=1 & sinc13 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; } +sinc12: r3 is c0303=1 & c0002=0 & r3 { * mult_addr = r3; mult_addr = mult_addr + 4; } +sinc12: sinc13 is c0303=0 & sinc13 { } +sinc11: sinc12 r4 is c0404=1 & sinc12 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; } +sinc11: r4 is c0404=1 & c0003=0 & r4 { * mult_addr = r4; mult_addr = mult_addr + 4; } +sinc11: sinc12 is c0404=0 & sinc12 { } +sinc10: sinc11 r5 is c0505=1 & sinc11 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; } +sinc10: r5 is c0505=1 & c0004=0 & r5 { * mult_addr = r5; mult_addr = mult_addr + 4; } +sinc10: sinc11 is c0505=0 & sinc11 { } +sinc9: sinc10 r6 is c0606=1 & sinc10 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; } +sinc9: r6 is c0606=1 & c0005=0 & r6 { * mult_addr = r6; mult_addr = mult_addr + 4; } +sinc9: sinc10 is c0606=0 & sinc10 { } +sinc8: sinc9 r7 is c0707=1 & sinc9 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; } +sinc8: r7 is c0707=1 & c0006=0 & r7 { * mult_addr = r7; mult_addr = mult_addr + 4; } +sinc8: sinc9 is c0707=0 & sinc9 { } +sinc7: sinc8 r8 is c0808=1 & sinc8 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; } +sinc7: r8 is c0808=1 & c0007=0 & r8 { * mult_addr = r8; mult_addr = mult_addr + 4; } +sinc7: sinc8 is c0808=0 & sinc8 { } +sinc6: sinc7 r9 is c0909=1 & sinc7 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; } +sinc6: r9 is c0909=1 & c0008=0 & r9 { * mult_addr = r9; mult_addr = mult_addr + 4; } +sinc6: sinc7 is c0909=0 & sinc7 { } +sinc5: sinc6 r10 is c1010=1 & sinc6 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; } +sinc5: r10 is c1010=1 & c0009=0 & r10 { * mult_addr = r10; mult_addr = mult_addr + 4; } +sinc5: sinc6 is c1010=0 & sinc6 { } +sinc4: sinc5 r11 is c1111=1 & sinc5 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; } +sinc4: r11 is c1111=1 & c0010=0 & r11 { * mult_addr = r11; mult_addr = mult_addr + 4; } +sinc4: sinc5 is c1111=0 & sinc5 { } +sinc3: sinc4 r12 is c1212=1 & sinc4 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; } +sinc3: r12 is c1212=1 & c0011=0 & r12 { * mult_addr = r12; mult_addr = mult_addr + 4; } +sinc3: sinc4 is c1212=0 & sinc4 { } +sinc2: sinc3 sp is c1313=1 & sinc3 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; } +sinc2: sp is c1313=1 & c0012=0 & sp { * mult_addr = sp; mult_addr = mult_addr + 4; } +sinc2: sinc3 is c1313=0 & sinc3 { } +sinc1: sinc2 lr is c1414=1 & sinc2 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; } +sinc1: lr is c1414=1 & c0013=0 & lr { * mult_addr = lr; mult_addr = mult_addr + 4; } +sinc1: sinc2 is c1414=0 & sinc2 { } +sinc0: sinc1 pc is c1515=1 & sinc1 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr + 4; } +sinc0: pc is c1515=1 & c0014=0 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr + 4; } +sinc0: sinc1 is c1515=0 & sinc1 { } +stlist_inc: { sinc0 } is sinc0 { } + + +# ldlist_dec is the list of registers to be loaded using DA or DB in Addressing Mode 4 +ldec15: pc is c1515=1 & pc { pc = * mult_addr; mult_addr = mult_addr - 4; } +ldec15: is c1515=0 { } +ldec14: lr ldec15 is c1414=1 & ldec15 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; } +ldec14: lr is c1414=1 & c1515=0 & lr { lr = * mult_addr; mult_addr = mult_addr - 4; } +ldec14: ldec15 is c1414=0 & ldec15 { } +ldec13: sp ldec14 is c1313=1 & ldec14 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; } +ldec13: sp is c1313=1 & c1415=0 & sp { sp = * mult_addr; mult_addr = mult_addr - 4; } +ldec13: ldec14 is c1313=0 & ldec14 { } +ldec12: r12 ldec13 is c1212=1 & ldec13 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; } +ldec12: r12 is c1212=1 & c1315=0 & r12 { r12 = * mult_addr; mult_addr = mult_addr - 4; } +ldec12: ldec13 is c1212=0 & ldec13 { } +ldec11: r11 ldec12 is c1111=1 & ldec12 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; } +ldec11: r11 is c1111=1 & c1215=0 & r11 { r11 = * mult_addr; mult_addr = mult_addr - 4; } +ldec11: ldec12 is c1111=0 & ldec12 { } +ldec10: r10 ldec11 is c1010=1 & ldec11 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; } +ldec10: r10 is c1010=1 & c1115=0 & r10 { r10 = * mult_addr; mult_addr = mult_addr - 4; } +ldec10: ldec11 is c1010=0 & ldec11 { } +ldec9: r9 ldec10 is c0909=1 & ldec10 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; } +ldec9: r9 is c0909=1 & c1015=0 & r9 { r9 = * mult_addr; mult_addr = mult_addr - 4; } +ldec9: ldec10 is c0909=0 & ldec10 { } +ldec8: r8 ldec9 is c0808=1 & ldec9 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; } +ldec8: r8 is c0808=1 & c0915=0 & r8 { r8 = * mult_addr; mult_addr = mult_addr - 4; } +ldec8: ldec9 is c0808=0 & ldec9 { } +ldec7: r7 ldec8 is c0707=1 & ldec8 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; } +ldec7: r7 is c0707=1 & c0815=0 & r7 { r7 = * mult_addr; mult_addr = mult_addr - 4; } +ldec7: ldec8 is c0707=0 & ldec8 { } +ldec6: r6 ldec7 is c0606=1 & ldec7 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; } +ldec6: r6 is c0606=1 & c0715=0 & r6 { r6 = * mult_addr; mult_addr = mult_addr - 4; } +ldec6: ldec7 is c0606=0 & ldec7 { } +ldec5: r5 ldec6 is c0505=1 & ldec6 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; } +ldec5: r5 is c0505=1 & c0615=0 & r5 { r5 = * mult_addr; mult_addr = mult_addr - 4; } +ldec5: ldec6 is c0505=0 & ldec6 { } +ldec4: r4 ldec5 is c0404=1 & ldec5 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; } +ldec4: r4 is c0404=1 & c0515=0 & r4 { r4 = * mult_addr; mult_addr = mult_addr - 4; } +ldec4: ldec5 is c0404=0 & ldec5 { } +ldec3: r3 ldec4 is c0303=1 & ldec4 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; } +ldec3: r3 is c0303=1 & c0415=0 & r3 { r3 = * mult_addr; mult_addr = mult_addr - 4; } +ldec3: ldec4 is c0303=0 & ldec4 { } +ldec2: r2 ldec3 is c0202=1 & ldec3 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; } +ldec2: r2 is c0202=1 & c0315=0 & r2 { r2 = * mult_addr; mult_addr = mult_addr - 4; } +ldec2: ldec3 is c0202=0 & ldec3 { } +ldec1: r1 ldec2 is c0101=1 & ldec2 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; } +ldec1: r1 is c0101=1 & c0215=0 & r1 { r1 = * mult_addr; mult_addr = mult_addr - 4; } +ldec1: ldec2 is c0101=0 & ldec2 { } +ldec0: r0 ldec1 is c0000=1 & ldec1 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; } +ldec0: r0 is c0000=1 & c0115=0 & r0 { r0 = * mult_addr; mult_addr = mult_addr - 4; } +ldec0: ldec1 is c0000=0 & ldec1 { } +ldlist_dec: { ldec0 } is ldec0 { } + +# stlist_dec is the list of registers to be stored using DA or DB in Addressing Mode 4 +sdec15: pc is c1515=1 & pc { *:4 mult_addr = (inst_start + 8); mult_addr = mult_addr - 4; } +sdec15: is c1515=0 { } +sdec14: lr sdec15 is c1414=1 & sdec15 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; } +sdec14: lr is c1414=1 & c1515=0 & lr { * mult_addr=lr; mult_addr = mult_addr - 4; } +sdec14: sdec15 is c1414=0 & sdec15 { } +sdec13: sp sdec14 is c1313=1 & sdec14 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; } +sdec13: sp is c1313=1 & c1415=0 & sp { * mult_addr=sp; mult_addr = mult_addr - 4; } +sdec13: sdec14 is c1313=0 & sdec14 { } +sdec12: r12 sdec13 is c1212=1 & sdec13 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; } +sdec12: r12 is c1212=1 & c1315=0 & r12 { * mult_addr=r12; mult_addr = mult_addr - 4; } +sdec12: sdec13 is c1212=0 & sdec13 { } +sdec11: r11 sdec12 is c1111=1 & sdec12 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; } +sdec11: r11 is c1111=1 & c1215=0 & r11 { * mult_addr=r11; mult_addr = mult_addr - 4; } +sdec11: sdec12 is c1111=0 & sdec12 { } +sdec10: r10 sdec11 is c1010=1 & sdec11 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; } +sdec10: r10 is c1010=1 & c1115=0 & r10 { * mult_addr=r10; mult_addr = mult_addr - 4; } +sdec10: sdec11 is c1010=0 & sdec11 { } +sdec9: r9 sdec10 is c0909=1 & sdec10 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; } +sdec9: r9 is c0909=1 & c1015=0 & r9 { * mult_addr=r9; mult_addr = mult_addr - 4; } +sdec9: sdec10 is c0909=0 & sdec10 { } +sdec8: r8 sdec9 is c0808=1 & sdec9 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; } +sdec8: r8 is c0808=1 & c0915=0 & r8 { * mult_addr=r8; mult_addr = mult_addr - 4; } +sdec8: sdec9 is c0808=0 & sdec9 { } +sdec7: r7 sdec8 is c0707=1 & sdec8 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; } +sdec7: r7 is c0707=1 & c0815=0 & r7 { * mult_addr=r7; mult_addr = mult_addr - 4; } +sdec7: sdec8 is c0707=0 & sdec8 { } +sdec6: r6 sdec7 is c0606=1 & sdec7 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; } +sdec6: r6 is c0606=1 & c0715=0 & r6 { * mult_addr=r6; mult_addr = mult_addr - 4; } +sdec6: sdec7 is c0606=0 & sdec7 { } +sdec5: r5 sdec6 is c0505=1 & sdec6 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; } +sdec5: r5 is c0505=1 & c0615=0 & r5 { * mult_addr=r5; mult_addr = mult_addr - 4; } +sdec5: sdec6 is c0505=0 & sdec6 { } +sdec4: r4 sdec5 is c0404=1 & sdec5 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; } +sdec4: r4 is c0404=1 & c0515=0 & r4 { * mult_addr=r4; mult_addr = mult_addr - 4; } +sdec4: sdec5 is c0404=0 & sdec5 { } +sdec3: r3 sdec4 is c0303=1 & sdec4 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; } +sdec3: r3 is c0303=1 & c0415=0 & r3 { * mult_addr=r3; mult_addr = mult_addr - 4; } +sdec3: sdec4 is c0303=0 & sdec4 { } +sdec2: r2 sdec3 is c0202=1 & sdec3 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; } +sdec2: r2 is c0202=1 & c0315=0 & r2 { * mult_addr=r2; mult_addr = mult_addr - 4; } +sdec2: sdec3 is c0202=0 & sdec3 { } +sdec1: r1 sdec2 is c0101=1 & sdec2 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; } +sdec1: r1 is c0101=1 & c0215=0 & r1 { * mult_addr=r1; mult_addr = mult_addr - 4; } +sdec1: sdec2 is c0101=0 & sdec2 { } + +sdec0: r0 sdec1 is c0000=1 & sdec1 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; } +sdec0: r0 is c0000=1 & c0115=0 & r0 { * mult_addr=r0; mult_addr = mult_addr - 4; } +sdec0: sdec1 is c0000=0 & sdec1 { } + +stlist_dec: {sdec0} is sdec0 { } + +# reglist deals with Addressing Mode 4 +# it takes care of bits 0-27 +# we assume that alignment checking is turned on +reglist: rn,ldlist_inc is P24=0 & U23=1 & S22=0 & W21=0 & L20=1 & rn & ldlist_inc +{ + mult_addr=rn; build ldlist_inc; +} + +reglist: rn,ldlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=0 & L20=1 & rn & ldlist_inc +{ + mult_addr=rn; build ldlist_inc; +} + +reglist: rn!,ldlist_inc is P24=0 & U23=1 & S22=0 & W21=1 & L20=1 & rn & ldlist_inc +{ + mult_addr=rn; build ldlist_inc; rn=mult_addr; +} + +reglist: rn!,ldlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=1 & L20=1 & rn & ldlist_inc +{ + mult_addr=rn; build ldlist_inc; rn=mult_addr; +} + +reglist: rn,ldlist_inc is P24=1 & U23=1 & S22=0 & W21=0 & L20=1 & rn & ldlist_inc +{ + mult_addr=(rn+4); build ldlist_inc; +} + +reglist: rn,ldlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=0 & L20=1 & rn & ldlist_inc +{ + mult_addr=(rn+4); build ldlist_inc; +} + +reglist: rn!,ldlist_inc is P24=1 & U23=1 & S22=0 & W21=1 & L20=1 & rn & ldlist_inc +{ + mult_addr=(rn+4); build ldlist_inc; rn=mult_addr-4; +} + +reglist: rn!,ldlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=1 & L20=1 & rn & ldlist_inc +{ + mult_addr=(rn+4); build ldlist_inc; rn=mult_addr-4; +} + +reglist: rn,ldlist_dec is P24=0 & U23=0 & S22=0 & W21=0 & L20=1 & rn & ldlist_dec +{ + mult_addr=rn; build ldlist_dec; +} + +reglist: rn,ldlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=0 & L20=1 & rn & ldlist_dec +{ + mult_addr=rn; build ldlist_dec; +} + +reglist: rn!,ldlist_dec is P24=0 & U23=0 & S22=0 & W21=1 & L20=1 & rn & ldlist_dec +{ + mult_addr=rn; build ldlist_dec; rn=mult_addr; +} + +reglist: rn!,ldlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=1 & L20=1 & rn & ldlist_dec +{ + mult_addr=rn; build ldlist_dec; rn=mult_addr; +} + +reglist: rn,ldlist_dec is P24=1 & U23=0 & S22=0 & W21=0 & L20=1 & rn & ldlist_dec +{ + mult_addr=(rn-4); build ldlist_dec; +} + +reglist: rn,ldlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=0 & L20=1 & rn & ldlist_dec +{ + mult_addr=(rn-4); build ldlist_dec; +} + +reglist: rn!,ldlist_dec is P24=1 & U23=0 & S22=0 & W21=1 & L20=1 & rn & ldlist_dec +{ + mult_addr=(rn-4); build ldlist_dec; rn=mult_addr+4; +} + +reglist: rn!,ldlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=1 & L20=1 & rn & ldlist_dec +{ + mult_addr=(rn-4); build ldlist_dec; rn=mult_addr+4; +} + +reglist: rn,stlist_inc is P24=0 & U23=1 & S22=0 & W21=0 & L20=0 & rn & stlist_inc +{ + mult_addr=rn; build stlist_inc; +} + +reglist: rn,stlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=0 & L20=0 & rn & stlist_inc +{ + mult_addr=rn; build stlist_inc; +} + +## This is here to allow old versions of this instruction to decode. +## The W-Bit21 is specified as (0) in the manual meaning should be 0 but is unpredictable if 1 +## Some older processors did not specify that Writeback was not available if the P24=0 and S22=0, +## which is a system interrupt instruction. +## I AM ASSUMING, that the W-bit is honored on these processors and does update the register!!!! +## This is probably an arbitrary decision, but keeps with what old processor did. +reglist: rn,stlist_inc"^" is P24=0 & U23=1 & S22=1 & W21=1 & L20=0 & rn & stlist_inc +{ + mult_addr=rn; build stlist_inc; rn=mult_addr; +} + + +reglist: rn!,stlist_inc is P24=0 & U23=1 & S22=0 & W21=1 & L20=0 & rn & stlist_inc +{ + mult_addr=rn; build stlist_inc; rn=mult_addr; +} + +reglist: rn,stlist_inc is P24=1 & U23=1 & S22=0 & W21=0 & L20=0 & rn & stlist_inc +{ + mult_addr=(rn+4); build stlist_inc; +} + +reglist: rn,stlist_inc"^" is P24=1 & U23=1 & S22=1 & W21=0 & L20=0 & rn & stlist_inc +{ + mult_addr=(rn+4); build stlist_inc; +} + +reglist: rn!,stlist_inc is P24=1 & U23=1 & S22=0 & W21=1 & L20=0 & rn & stlist_inc +{ + mult_addr=(rn+4); build stlist_inc; rn=mult_addr-4; +} + +reglist: rn,stlist_dec is P24=0 & U23=0 & S22=0 & W21=0 & L20=0 & rn & stlist_dec +{ + mult_addr=rn; build stlist_dec; +} + +reglist: rn,stlist_dec"^" is P24=0 & U23=0 & S22=1 & W21=0 & L20=0 & rn & stlist_dec +{ + mult_addr=rn; build stlist_dec; +} + +reglist: rn!,stlist_dec is P24=0 & U23=0 & S22=0 & W21=1 & L20=0 & rn & stlist_dec +{ + mult_addr=rn; build stlist_dec; rn=mult_addr; +} + +reglist: rn,stlist_dec is P24=1 & U23=0 & S22=0 & W21=0 & L20=0 & rn & stlist_dec +{ + mult_addr=(rn-4); build stlist_dec; +} + +reglist: rn,stlist_dec"^" is P24=1 & U23=0 & S22=1 & W21=0 & L20=0 & rn & stlist_dec +{ + mult_addr=(rn-4); build stlist_dec; +} + +reglist: rn!,stlist_dec is P24=1 & U23=0 & S22=0 & W21=1 & L20=0 & rn & stlist_dec +{ + mult_addr=(rn-4); build stlist_dec; rn=mult_addr+4; +} + +# mdir is for attaching the load/store multiple addressing mode mnemonic to the mnemonic +mdir: "ia" is P24=0 & U23=1 { } +mdir: "ib" is P24=1 & U23=1 { } +mdir: "da" is P24=0 & U23=0 { } +mdir: "db" is P24=1 & U23=0 { } + +# addrmode5 is the parameter in Addressing Mode5 +# it takes care of bits 27-0 except for the N and L flags and CRd and cp# +# it takes care of possible writebacks to Rn +addrmode5: [rn,"#"^off8] is P24=1 & U23=1 & W21=0 & rn & immed [ off8=immed*4; ] { local tmp = rn + off8; export tmp; } +addrmode5: [rn,"#"^noff8] is P24=1 & U23=0 & W21=0 & rn & immed [ noff8=-(immed*4); ] { local tmp = rn + noff8; export tmp; } +addrmode5: [rn,"#"^off8]! is P24=1 & U23=1 & W21=1 & rn & immed [ off8=immed*4; ] { rn = rn + off8; export rn; } +addrmode5: [rn,"#"^noff8]! is P24=1 & U23=0 & W21=1 & rn & immed [ noff8=-(immed*4); ] { rn = rn + noff8; export rn; } +addrmode5: [rn],"#"^off8 is P24=0 & U23=1 & W21=1 & rn & immed [ off8=immed*4; ] { local tmp = rn; rn = rn+off8; export tmp; } +addrmode5: [rn],"#"^noff8 is P24=0 & U23=0 & W21=1 & rn & immed [ noff8=-(immed*4); ] { local tmp = rn; rn = rn + noff8; export tmp; } +addrmode5: [rn],{immed} is P24=0 & U23=1 & W21=0 & rn & immed { export rn; } + +# cpsrmask is the resulting cpsr mask for the msr instruction + +cpsrmask: is mask=0 { export 0:4; } +cpsrmask: "cpsr_c" is mask=1 { export 0xff:4; } +cpsrmask: "cpsr_x" is mask=2 { export 0xff00:4; } +cpsrmask: "cpsr_cx" is mask=3 { export 0xffff:4; } +cpsrmask: "cpsr_s" is mask=4 { export 0xff0000:4; } +cpsrmask: "cpsr_cs" is mask=5 { export 0xff00ff:4; } +cpsrmask: "cpsr_xs" is mask=6 { export 0xffff00:4; } +cpsrmask: "cpsr_cxs" is mask=7 { export 0xffffff:4; } +cpsrmask: "cpsr_f" is mask=8 { export 0xff000000:4; } +cpsrmask: "cpsr_cf" is mask=9 { export 0xff0000ff:4; } +cpsrmask: "cpsr_xf" is mask=10 { export 0xff00ff00:4; } +cpsrmask: "cpsr_cxf" is mask=11 { export 0xff00ffff:4; } +cpsrmask: "cpsr_sf" is mask=12 { export 0xffff0000:4; } +cpsrmask: "cpsr_csf" is mask=13 { export 0xffff00ff:4; } +cpsrmask: "cpsr_xsf" is mask=14 { export 0xffffff00:4; } +cpsrmask: "cpsr_cxsf" is mask=15 { export 0xffffffff:4; } + +# spsrmask is the mask for spsr in the msr instruction + +spsrmask: is mask=0 { export 0:4; } +spsrmask: "spsr_c" is mask=1 { export 0xff:4; } +spsrmask: "spsr_x" is mask=2 { export 0xff00:4; } +spsrmask: "spsr_cx" is mask=3 { export 0xffff:4; } +spsrmask: "spsr_s" is mask=4 { export 0xff0000:4; } +spsrmask: "spsr_cs" is mask=5 { export 0xff00ff:4; } +spsrmask: "spsr_xs" is mask=6 { export 0xffff00:4; } +spsrmask: "spsr_cxs" is mask=7 { export 0xffffff:4; } +spsrmask: "spsr_f" is mask=8 { export 0xff000000:4; } +spsrmask: "spsr_cf" is mask=9 { export 0xff0000ff:4; } +spsrmask: "spsr_xf" is mask=10 { export 0xff00ff00:4; } +spsrmask: "spsr_cxf" is mask=11 { export 0xff00ffff:4; } +spsrmask: "spsr_sf" is mask=12 { export 0xffff0000:4; } +spsrmask: "spsr_csf" is mask=13 { export 0xffff00ff:4; } +spsrmask: "spsr_xsf" is mask=14 { export 0xffffff00:4; } +spsrmask: "spsr_cxsf" is mask=15 { export 0xffffffff:4; } + +##################### +###### immediate bit-number data for unsigned/signed saturated instructions +##################### +@if defined(VERSION_6) + +sSatImm5: "#"^satimm is satimm5 [ satimm = satimm5 + 1; ] { export *[const]:2 satimm; } +sSatImm4: "#"^satimm is satimm4 [ satimm = satimm4 + 1; ] { export *[const]:2 satimm; } +uSatImm5: "#"^satimm5 is satimm5 { export *[const]:2 satimm5; } +uSatImm4: "#"^satimm4 is satimm4 { export *[const]:2 satimm4; } + +@endif # VERSION_6 + +@if defined(VERSION_6K) || defined(VERSION_6T2) +optionImm: "#"^immed4 is immed4 { export *[const]:4 immed4; } +@endif + +@if defined(VERSION_6T2) || defined(VERSION_7) + +lsbImm: "#"^lsb is lsb { export *[const]:4 lsb; } +msbImm: "#"^msb is msb { export *[const]:4 msb; } +widthMinus1: "#"^width is msb [ width = msb + 1; ] { export *[const]:4 msb; } +bitWidth: "#"^w is lsb & msb [ w = msb - lsb + 1; ] { export *[const]:4 w; } + +@endif # VERSION_6T2 || VERSION_7 + +# +# Modes for SRS instructions +# +@if defined(VERSION_6) +SRSMode: "usr" is srsMode=8 & c0004 { export *[const]:1 c0004; } +SRSMode: "fiq" is srsMode=9 & c0004 { export *[const]:1 c0004; } +SRSMode: "irq" is srsMode=10 & c0004 { export *[const]:1 c0004; } +SRSMode: "svc" is srsMode=11 & c0004 { export *[const]:1 c0004; } +SRSMode: "mon" is srsMode=14 & c0004 { export *[const]:1 c0004; } +SRSMode: "abt" is srsMode=15 & c0004 { export *[const]:1 c0004; } +SRSMode: "und" is srsMode=19 & c0004 { export *[const]:1 c0004; } +SRSMode: "sys" is srsMode=23 & c0004 { export *[const]:1 c0004; } +SRSMode: "#"^srsMode is srsMode { export *[const]:1 srsMode; } +@endif # VERSION_6 + +# Add a hat instruction to set the ARMcond context variable which +# tells whether this is a legal conditional instruction (for v7 and +# later). + +@if defined(VERSION_6T2) || defined(VERSION_7) +:^instruction is ARMcondCk=0 & itmode=0 & TMode=0 & (bit31=0|bit30=0|bit29=0|bit28=0) & instruction [ ARMcondCk=1; ARMcond=1; ] {} +:^instruction is ARMcondCk=0 & instruction [ ARMcondCk=1; ARMcond=0; ] {} + +# Ensure one of the recursive rules above is applied for assembly +with : ARMcondCk=1 { + +@endif + +################################################# +# +# Include the SIMD/VFP instructions before the +# other ARM instructions to avoid incorrect +# constructor matching for those that use the +# COND subconstructor. This also ensures +# that the various VFP instructions supersede the +# CDP/MCR/MRC general coprocessor instructions +# +################################################# +@if defined(INCLUDE_NEON) +@include "ARMneon.sinc" +@endif + +################################################# +# +# Do the same now for ARMv8, which also has neon +# +################################################# +@if defined(VERSION_8) +@include "ARMv8.sinc" +@endif # VERSION_8 + +################################################ +# +# These instructions must come first because the cond pattern match +# is more specific than the subconstructor COND. If a base intruction +# matches and then COND fails (cond=14 or cond=15) then the disassembly +# will fail +# +################################################ + +@if defined(VERSION_5) + +# Exception Generation and UDF + +# immed12_4 used in Exception Generation and Media instructions class + +immed12_4: "#"^tmp is $(AMODE) & immed12 & immed4 [tmp = (immed12 << 4) | immed4; ] { export *[const]:4 tmp; } + +:hlt immed12_4 is $(AMODE) & cond=0xe & c2027=0x10 & c0407=0x7 & immed12_4 +{ + software_hlt(immed12_4); +} + +:bkpt immed12_4 is $(AMODE) & cond=0xe & c2027=0x12 & c0407=0x7 & immed12_4 +{ + software_bkpt(immed12_4); +} + +:hvc immed12_4 is $(AMODE) & cond=0xe & c2027=0x14 & c0407=0x7 & immed12_4 +{ + software_hvc(immed12_4); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) + +define pcodeop SG; + +:sg is TMode=1 & thv_c0031=0xe97fe97f +{ + SG(); +} +@endif + +# Requires Security Extensions +:smc^COND immed4 is $(AMODE) & COND & c2027=0x16 & c0407=0x7 & immed4 +{ + build COND; + software_smc(immed4:4); +} + +@if defined(VERSION_6T2) || defined(VERSION_7) +define pcodeop TT; + +:tt^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=0 & thv_bit06=0 & thv_Rt2 & thv_Rn +{ + thv_Rt2 = TT(thv_Rn); +} + +define pcodeop TTA; + +:tta^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=1 & thv_bit06=0 & thv_Rt2 & thv_Rn +{ + thv_Rt2 = TTA(thv_Rn); +} + +define pcodeop TTAT; + +:ttat^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=1 & thv_bit06=1 & thv_Rt2 & thv_Rn +{ + thv_Rt2 = TTAT(thv_Rn); +} + +define pcodeop TTT; + +:ttt^ItCond thv_Rt2, thv_Rn is TMode=1 & ItCond & thv_c2031=0b111010000100 & thv_c1215=0b1111 & thv_bit07=0 & thv_bit06=1 & thv_Rt2 & thv_Rn +{ + thv_Rt2 = TTT(thv_Rn); +} + +@endif + +:udf immed12_4 is $(AMODE) & cond=0xe & c2027=0x7f & c0407=0xf & immed12_4 +{ + local excaddr:4 = inst_start; + local target:4 = software_udf(immed12_4:4, excaddr); + goto [target]; +} + +@endif # VERSION_5 + +@if defined(VERSION_6) + +AFLAG: "a" is c0808=1 & c1819=2 { enableDataAbortInterrupts(); } +AFLAG: "a" is c0808=1 { disableDataAbortInterrupts(); } +AFLAG: is c0808=0 { } +IFLAG: "i" is c0707=1 & c1819=2 { enableIRQinterrupts(); } +IFLAG: "i" is c0707=1 { disableIRQinterrupts(); } +IFLAG: is c0707=0 { } +FFLAG: "f" is c0606=1 & c1819=2 { enableFIQinterrupts(); } +FFLAG: "f" is c0606=1 { disableFIQinterrupts(); } +FFLAG: is c0606=0 { } +IFLAGS: AFLAG^IFLAG^FFLAG is AFLAG & IFLAG & FFLAG { } + +SetMode: "#"^16 is c0004=0x10 { setUserMode(); } +SetMode: "#"^17 is c0004=0x11 { setFIQMode(); } +SetMode: "#"^18 is c0004=0x12 { setIRQMode(); } +SetMode: "#"^19 is c0004=0x13 { setSupervisorMode(); } +SetMode: "#"^22 is c0004=0x16 { setMonitorMode(); } +SetMode: "#"^23 is c0004=0x17 { setAbortMode(); } +SetMode: "#"^27 is c0004=0x1b { setUndefinedMode(); } +SetMode: "#"^31 is c0004=0x1f { setSystemMode(); } + +:cps SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=0 & c1717=1 & c0916=0 & c0508=0 & SetMode { } +:cpsie IFLAGS is $(AMODE) & cond=15 & c2027=16 & c1819=2 & c1717=0 & c0916=0 & c0505=0 & c0004=0 & IFLAGS { } +:cpsid IFLAGS is $(AMODE) & cond=15 & c2027=16 & c1819=3 & c1717=0 & c0916=0 & c0505=0 & c0004=0 & IFLAGS { } +:cpsie IFLAGS, SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=2 & c1717=1 & c0916=0 & c0505=0 & IFLAGS & SetMode { } +:cpsid IFLAGS, SetMode is $(AMODE) & cond=15 & c2027=16 & c1819=3 & c1717=1 & c0916=0 & c0505=0 & IFLAGS & SetMode { } + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:pld addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=5 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + HintPreloadData(addrmode2); +} + +# prevent literal form getting matched by pldw +:pld addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=5 & c1619=0xf & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + HintPreloadData(addrmode2); +} + +@endif # VERSION_5E + +@if defined(VERSION_7) + +:pldw addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=1 & c2022=1 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + HintPreloadDataForWrite(addrmode2); +} + +:pli addrmode2 is $(AMODE) & cond=0xf & c2627=1 & c2424=0 & c2022=5 & c1215=0xf & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + HintPreloadInstruction(addrmode2); +} + +@endif # VERSION_7 + + +@if defined(VERSION_6) + +:rfeia rn is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = rn; + cpsr = *ptr; + ptr = ptr + 4; + pc = *ptr; + return [pc]; +} + +:rfeib rn is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = rn + 4; + cpsr = *ptr; + ptr = ptr + 4; + pc = *ptr; + return [pc]; +} + +:rfeda rn is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = rn; + cpsr = *ptr; + ptr = ptr - 4; + pc = *ptr; + return [pc]; +} + +:rfedb rn is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & S22=0 & W21=0 & L20=1 & rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = rn - 4; + cpsr = *ptr; + ptr = ptr - 4; + pc = *ptr; + return [pc]; +} + +:rfeia Rn! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = Rn; + cpsr = *ptr; + ptr = ptr + 4; + pc = *ptr; + Rn = ptr + 4; + return [pc]; +} + +:rfeib Rn! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = Rn + 4; + cpsr = *ptr; + ptr = ptr + 4; + pc = *ptr; + Rn = ptr; + return [pc]; +} + +:rfeda Rn! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = Rn; + cpsr = *ptr; + ptr = ptr - 4; + pc = *ptr; + Rn = ptr - 4; + return [pc]; +} + +:rfedb Rn! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & S22=0 & W21=1 & L20=1 & Rn & c1215=0 & c0811=10 & c0007=0 +{ + # register list is always: pc, cpsr + ptr:4 = Rn - 4; + cpsr = *ptr; + ptr = ptr - 4; + pc = *ptr; + Rn = ptr; + return [pc]; +} + +:srsia SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=1 & W21=0 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; + ptr = ptr + 4; +} + +:srsib SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp + 4; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; +} + +:srsda SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; + ptr = ptr - 4; +} + +:srsdb SRSMode is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & W21=0 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp - 4; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; +} + +:srsia SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=1 & S22=1 & W21=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; + ptr = ptr + 4; + sp = ptr; +} + +:srsib SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=1 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp + 4; + *ptr = lr; + ptr = ptr + 4; + *ptr = spsr; + sp = ptr; +} + +:srsda SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=0 & U23=0 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; + ptr = ptr - 4; + sp = ptr; +} + +:srsdb SRSMode! is $(AMODE) & cond=15 & c2527=4 & P24=1 & U23=0 & W21=1 & S22=1 & L20=0 & c1215=0 & c0811=5 & c0507=0 & SRSMode +{ + # register list is always: r14, spsr + ptr:4 = sp; + ptr = ptr - 4; + *ptr = lr; + ptr = ptr - 4; + *ptr = spsr; + sp = ptr; +} + +@endif # VERSION_6 + +@if defined(VERSION_5) + +:stc2 cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=0 +{ + t_cpn:4 = cpn; + coprocessor_store2(t_cpn,CRd,addrmode5); +} + +:stc2l cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=0 +{ + t_cpn:4 = cpn; + coprocessor_storelong2(t_cpn,CRd,addrmode5); +} + +@endif # VERSION_5 + +################################################# +# +# Here are the rest of instructions in alphabetical order +# +################################################# + +#See ARM Architecture reference section "Pseudocode details of addition and subtraction" +macro add_with_carry_flags(op1,op2){ + local CYz = zext(CY); + local result = op1 + op2; + tmpCY = carry( op1, op2) || carry( result, CYz ); + tmpOV = scarry( op1, op2 ) ^^ scarry( result, CYz ); +} + +#Note: used for subtraction op1 - (op2 + !CY) +#sets tmpCY if there is NO borrow +macro sub_with_carry_flags(op1, op2){ + local result = op1 - op2; + tmpCY = (op1 > op2) || (result < zext(CY)); + tmpOV = sborrow(op1,op2) ^^ sborrow(result,zext(!CY)); +} + + +:adc^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + add_with_carry_flags(rn,shift1); + Rd = rn+shift1+zext(CY); + resultflags(Rd); + build SBIT_CZNO; +} + +:adc^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + add_with_carry_flags(rn,shift2); + Rd = rn+shift2+zext(CY); + resultflags(Rd); + build SBIT_CZNO; +} + +:adc^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=5 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + add_with_carry_flags(rn,shift3); + Rd = rn+shift3+zext(CY); + resultflags(Rd); + build SBIT_CZNO; +} + +:adc^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + add_with_carry_flags(rn,shift1); + dest:4 = rn + shift1 + zext(CY); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:adc^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + add_with_carry_flags(rn,shift2); + dest:4 = rn + shift2 + zext(CY); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:adc^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=5 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + add_with_carry_flags(rn,shift3); + dest:4 = rn + shift3 + zext(CY); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +ArmPCRelImmed12: reloff is U23=1 & immed & rotate + [ reloff = inst_start + 8 + ( ((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff); ] +{ + export *[const]:4 reloff; +} + +ArmPCRelImmed12: reloff is U23=0 & immed & rotate + [ reloff = inst_start + 8 - ( ((immed<<(32-rotate*2))|(immed>>(rotate*2))) $and 0xffffffff); ] +{ + export *[const]:4 reloff; +} + +# +# ADR constructors must appear before ADD constructors to give ADR parsing precedence +# + +:adr^COND Rd,ArmPCRelImmed12 is $(AMODE) & COND & c2527=1 & (c2024=8 | c2024=4) & Rn=15 & Rd & ArmPCRelImmed12 +{ + build COND; + Rd = ArmPCRelImmed12; +} + +:adr^COND pc,ArmPCRelImmed12 is $(AMODE) & COND & c2527=1 & (c2024=8 | c2024=4) & Rn=15 & Rd=15 & pc & ArmPCRelImmed12 +{ + build COND; + dest:4 = ArmPCRelImmed12; + ALUWritePC(dest); + goto [pc]; +} + + +:add^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + addflags(rn,shift1); + Rd = rn + shift1; + resultflags(Rd); + build SBIT_CZNO; +} + +:add^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + addflags(rn,shift2); + Rd = rn + shift2; + resultflags(Rd); + build SBIT_CZNO; +} + +:add^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=4 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + addflags(rn,shift3); + Rd = rn + shift3; + resultflags(Rd); + build SBIT_CZNO; +} + +:add^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + addflags(rn,shift1); + dest:4 = rn + shift1; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:add^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + addflags(rn,shift2); + dest:4 = rn + shift2; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:add^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=4 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + addflags(rn,shift3); + dest:4 = rn + shift3; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:and^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + Rd = rn & shift1; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:and^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + Rd = rn & shift2; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:and^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=0 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + Rd = rn & shift3; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:and^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + dest:4 = rn & shift1; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:and^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + dest:4 = rn & shift2; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:and^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=0 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + dest:4 = rn & shift3; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +# must match first! before conditional goto + +:b Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=0 & Addr24 +{ + goto Addr24; +} + +:b^cc Addr24 is $(AMODE) & cc & c2527=5 & L24=0 & Addr24 +{ + if (cc) goto Addr24; +} + + + +@if defined(VERSION_6T2) + +:bfc^COND Rd,lsbImm,bitWidth is $(AMODE) & COND & c2127=0x3e & msbImm & Rd & lsbImm & bitWidth & c0006=0x1f { + build COND; + build lsbImm; + build msbImm; + build bitWidth; + clearMask:4 = (-1 << (msbImm + 1)) | (-1 >> (32 - lsbImm)); + Rd = Rd & clearMask; +} + +:bfi^COND Rd,Rm,lsbImm,bitWidth is $(AMODE) & COND & c2127=0x3e & msbImm & Rd & Rm & lsbImm & bitWidth & c0406=1 { + build COND; + build lsbImm; + build msbImm; + build bitWidth; + clearMask:4 = (-1 << (msbImm + 1)) | (-1 >> (32 - lsbImm)); + bits:4 = (Rm << lsbImm) & ~clearMask; + Rd = (Rd & clearMask) | bits; +} + +@endif # VERSION_6T2 + +:bic^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + Rd = rn&(~shift1); + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:bic^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + Rd = rn&(~shift2); + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:bic^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=14 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + Rd = rn&(~shift3); + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:bic^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + dest:4 = rn&(~shift1); + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:bic^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + dest:4 = rn&(~shift2); + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:bic^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=14 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + dest:4 = rn&(~shift3); + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +# bl used as a PIC instruction to get at current PC in lr +:bl Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=1 & immed24=0xffffff & Addr24 +{ + lr = inst_next; + goto Addr24; +} + +:bl Addr24 is $(AMODE) & cond=14 & c2527=5 & L24=1 & Addr24 +{ + lr = inst_next; + call Addr24; +} + +:bl^COND Addr24 is $(AMODE) & CALLoverride=0 & COND & c2527=5 & L24=1 & Addr24 +{ + build COND; + build Addr24; + lr = inst_next; + call Addr24; +} + +:bl^COND Addr24 is $(AMODE) & CALLoverride=1 & COND & c2527=5 & L24=1 & Addr24 +{ + build COND; + build Addr24; + lr = inst_next; + goto Addr24; +} + +# blx(1) instruction +@if defined(T_VARIANT) && defined(VERSION_5) + +# Two forms of blx needed to distinguish from b +:blx HAddr24 is $(AMODE) & CALLoverride=0 & cond=15 & c2527=5 & H24=0 & HAddr24 +{ + lr = inst_next; + SetThumbMode(1); + call HAddr24; + # don't do causes decompiler trouble TB = 0; +} # Always changes to THUMB mode + +:blx HAddr24 is $(AMODE) & CALLoverride=1 & cond=15 & c2527=5 & H24=0 & HAddr24 +{ + lr = inst_next; + SetThumbMode(1); + goto HAddr24; +} # Always changes to THUMB mode + + +:blx HAddr24 is $(AMODE) & CALLoverride=0 & cond=15 & c2527=5 & H24=1 & HAddr24 +{ + lr = inst_next; + SetThumbMode(1); + call HAddr24; + # don't do causes decompiler trouble TB = 0; +} # Always changes to THUMB mode + +:blx HAddr24 is $(AMODE) & CALLoverride=1 & cond=15 & c2527=5 & H24=1 & HAddr24 +{ + lr = inst_next; + SetThumbMode(1); + goto HAddr24; +} # Always changes to THUMB mode + +@endif # T_VARIANT && VERSION_5 + +@if defined(VERSION_5) + +:blx^COND rm is $(AMODE) & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=3 & rm +{ + build COND; + build rm; + BXWritePC(rm); + lr=inst_next; + call [pc]; +# don't do causes decompiler trouble TB = 0; +} # Optional THUMB + +:blx^COND rm is $(AMODE) & CALLoverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=3 & rm +{ + build COND; + build rm; + BXWritePC(rm); + lr=inst_next; + goto [pc]; +} # Optional THUMB + +@endif # VERSION_5 + +@if defined(VERSION_5_or_T) + +# if branching using lr, assume return +:bx^COND rm is $(AMODE) & REToverride=0 & LRset=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm=14 +{ + build COND; + build rm; + BXWritePC(rm); + return [pc]; +} # Optional change to THUMB + +:bx^COND rm is $(AMODE) & REToverride=0 & LRset=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm +{ + build COND; + build rm; + BXWritePC(rm); + goto [pc]; +} # Optional change to THUMB + +# if lr has just been set, assume call +:bx^COND rm is $(AMODE) & REToverride=0 & LRset=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm & Rm +{ + build COND; + build rm; + BXWritePC(rm); + call [pc]; +} # Optional change to THUMB + +:bx^COND rm is $(AMODE) & REToverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm +{ + build COND; + build rm; + BXWritePC(rm); + goto [pc]; +} # Optional change to THUMB + +#:bx^COND lr is $(AMODE) & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & Rm=14 & lr +#{ +# build COND; +# TB=(lr&0x00000001)!=0; +# tmp = lr & 0xfffffffe; +# return [tmp]; +#} # Optional change to THUMB + +@endif # VERSION_5_or_T + +@if defined(VERSION_6) + +# bxj behaves like bx except that Jazelle state is enabled if available (added with Version-5 J-variant) + +:bxj^COND rm is $(AMODE) & REToverride=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm +{ + build COND; + build rm; + success:1 = jazelle_branch(); + if (success) goto ; + BXWritePC(rm); + return [pc]; + +} # Optional change to THUMB + +# if branching using "ip" then is a goto +:bxj^COND rm is $(AMODE) & REToverride=0 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm & Rm=12 +{ + build COND; + build rm; + success:1 = jazelle_branch(); + if (success) goto ; + BXWritePC(rm); + goto [pc]; + +} # Optional change to THUMB + +:bxj^COND rm is $(AMODE) & REToverride=1 & COND & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=2 & rm +{ + build COND; + build rm; + success:1 = jazelle_branch(); + if (success) goto ; + BXWritePC(rm); + goto [pc]; + +} # Optional change to THUMB + +@endif # VERSION_6 + +@if defined(VERSION_5) + +:cdp2 cpn,opcode1,CRd,CRn,CRm,opcode2 is $(AMODE) & cond=15 & c2427=14 & opcode1 & CRn & CRd & cpn & opcode2 & c0404=0 & CRm +{ + t_cpn:4 = cpn; + t_op1:4 = opcode1; + t_op2:4 = opcode2; + coprocessor_function2(t_cpn,t_op1,t_op2,CRd,CRn,CRm); +} + +@endif # VERSION_5 + +:cdp^COND cpn,opcode1,CRd,CRn,CRm,opcode2 is $(AMODE) & COND & c2427=14 & opcode1 & CRn & CRd & cpn & opcode2 & c0404=0 & CRm +{ + build COND; + t_cpn:4 = cpn; + t_op1:4 = opcode1; + t_op2:4 = opcode2; + coprocessor_function(t_cpn,t_op1,t_op2,CRd,CRn,CRm); +} + +@if defined(VERSION_6K) || defined(VERSION_7) + +:clrex is $(AMODE) & c0031=0xf57ff01f { + ClearExclusiveLocal(); +} + +@endif # VERSION_6K + +@if defined(VERSION_5) + +:clz^COND Rd,rm is $(AMODE) & COND & c2027=22 & c1619=15 & Rd & c0811=15 & c0407=1 & rm +{ + build COND; + build rm; + Rd = count_leading_zeroes(rm); +} + +@endif # VERSION_5 + +:cmn^COND rn,shift1 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + addflags(rn,shift1); + local tmp = rn + shift1; + resultflags(tmp); + affectflags(); +} + +:cmn^COND rn,shift2 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + addflags(rn,shift2); + local tmp = rn + shift2; + resultflags(tmp); + affectflags(); +} + +:cmn^COND rn,shift3 is $(AMODE) & COND & c2024=23 & rn & c1215=0 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + addflags(rn,shift3); + local tmp = rn + shift3; + resultflags(tmp); + affectflags(); +} + +:cmp^COND rn,shift1 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(rn,shift1); + local tmp = rn - shift1; + resultflags(tmp); + affectflags(); +} + +:cmp^COND rn,shift2 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + subflags(rn,shift2); + local tmp = rn - shift2; + resultflags(tmp); + affectflags(); +} + +:cmp^COND rn,shift3 is $(AMODE) & COND & c2024=21 & rn & c1215=0 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + subflags(rn,shift3); + local tmp = rn - shift3; + resultflags(tmp); + affectflags(); +} + +@if defined(VERSION_6) + +# cpy is a pre-UAL synonym for mov +:cpy^COND pc,rm is $(AMODE) & COND & pc & c2027=0x1a & c1619=0 & c0411=0 & Rd=15 & rm +{ + build COND; + build rm; + BXWritePC(rm); + goto [pc]; +} + +:cpy^COND lr,rm is $(AMODE) & COND & c2027=0x1a & c1619=0 & c0411=0 & Rd=14 & lr & rm & Rm2=15 + [ LRset=1; globalset(inst_next,LRset); ] +{ + build COND; + lr = rm; +} + +:cpy^COND Rd,rm is $(AMODE) & COND & c2027=0x1a & c1619=0 & c0411=0 & Rd & rm +{ + build COND; + build rm; + Rd = rm; +} + +@endif # VERSION_6 + +@if defined(VERSION_6K) || defined(VERSION_6T2) + +:dbg^COND optionImm is $(AMODE) & COND & c0427=0x320f0f & optionImm { +@if defined(VERSION_7) + build COND; + build optionImm; + HintDebug(optionImm); +@endif # VERSION_7 +} + +@endif # VERSION_6K || VERSION_6T2 + +@if defined(VERSION_7) + + + +:dmb dbOption is $(AMODE) & c0431=0xf57ff05 & dbOption { + DataMemoryBarrier(dbOption:1); +} + +:dsb dbOption is $(AMODE) & c0431=0xf57ff04 & dbOption { + DataSynchronizationBarrier(dbOption:1); +} + +@endif # VERSION_7 + +:eor^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + Rd = rn^shift1; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:eor^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + Rd = rn^shift2; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:eor^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=1 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + Rd = rn^shift3; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:eor^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + dest:4 = rn^shift1; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:eor^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + dest:4 = rn^shift2; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:eor^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=1 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + dest:4 = rn^shift3; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +@if defined(VERSION_7) + + +:isb ibOption is $(AMODE) & c0431=0xf57ff06 & ibOption { + InstructionSynchronizationBarrier(ibOption:1); +} + +@endif # VERSION_7 + +### These must come first, because of cond=15 match +@if defined(VERSION_5) + +:ldc2 cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=1 +{ + t_cpn:4 = cpn; + coprocessor_load2(t_cpn,CRd,addrmode5); +} + +:ldc2l cpn,CRd,addrmode5 is $(AMODE) & cond=15 & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=1 +{ + t_cpn:4 = cpn; + coprocessor_loadlong2(t_cpn,CRd,addrmode5); +} + +@endif # VERSION_5 +######## cond=15 match + +:ldc^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=1 +{ + build COND; + build addrmode5; + t_cpn:4 = cpn; + coprocessor_load(t_cpn,CRd,addrmode5); +} + +:ldcl^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=1 +{ + build COND; + build addrmode5; + t_cpn:4 = cpn; + coprocessor_loadlong(t_cpn,CRd,addrmode5); +} + +:ldm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=1 & c1515=0 & reglist +{ + build COND; + build reglist; +} + +:ldm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=1 & c1515=1 & reglist +{ + build COND; + build reglist; + LoadWritePC(pc); + return [pc]; +} + +#:ldr^COND Rd,addrmode2 is $(AMODE) & COND & B22=0 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +#{ +# build COND; +# build addrmode2; +# tmp:4=addrmode2&0xfffffffc; +# tmp2:4=(addrmode2&3)<<3; +# Rd=*tmp; +# Rd = (Rd >> tmp2) | (Rd << (32-tmp2)); +#} + +# The following form of ldr assumes alignment checking is on +:ldr^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + Rd = *addrmode2; +} + +# Two forms of ldr with destination=pc needed to distinguish from ldrt +:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & LRset=1 & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=1 & (I25=0 | (I25=1 & c0404=0)) & addrmode2 + [ LRset=0; globalset(inst_next,LRset); ] +{ + build COND; + build addrmode2; + dest:4=*addrmode2; + SetThumbMode((dest&0x00000001)!=0); + pc=dest&0xfffffffe; + call [pc]; + SetThumbMode(0); +} # No unaligned address + +:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & LRset=1 & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=0 & W21=0 & (I25=0 | (I25=1 & c0404=0)) & addrmode2 + [ LRset=0; globalset(inst_next,LRset); ] +{ + build COND; + build addrmode2; + dest:4=*addrmode2; + SetThumbMode((dest&0x00000001)!=0); + pc=dest&0xfffffffe; + call [pc]; + SetThumbMode(0); +} # No unaligned address + +# Two forms of ldr with destination=pc needed to distinguish from ldrt +:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=1 & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + dest:4=*addrmode2; + BXWritePC(dest); + goto [pc]; +} # No unaligned address + +:ldr^COND pc,addrmode2 is $(AMODE) & pc & COND & c2627=1 & B22=0 & L20=1 & Rd=15 & P24=0 & W21=0 & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + dest:4=*addrmode2; + BXWritePC(dest); + goto [pc]; +} # No unaligned address + +:ldrb^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + Rd = zext( *:1 addrmode2); +} + +:ldrbt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=1 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + Rd = zext( *:1 addrmode2); +} + +@if defined(VERSION_5E) + +:ldrd^COND Rd,Rd2,addrmode3 is $(AMODE) & COND & c2527=0 & c0407=13 & c1212=0 & L20=0 & Rd & Rd2 & addrmode3 +{ + build COND; + build addrmode3; + Rd = *(addrmode3); + Rd2 = *(addrmode3+4); +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:ldrex^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x19 & Rn & Rd & c0011=0xf9f +{ + build COND; + Rd = *Rn; +} + +@endif # VERSION_6 + +@if defined(VERSION_6K) + +:ldrexb^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x1d & Rn & Rd & c0011=0xf9f +{ + build COND; + Rd = zext(*:1 Rn); +} + +:ldrexd^COND Rd,Rd2,[Rn] is $(AMODE) & COND & c2027=0x1b & Rn & Rd & Rd2 & c0011=0xf9f +{ + build COND; + Rd = *(Rn); + Rd2 = *(Rn + 4); +} + +:ldrexh^COND Rd,[Rn] is $(AMODE) & COND & c2027=0x1f & Rn & Rd & c0011=0xf9f +{ + build COND; + Rd = zext(*:2 Rn); +} + +@endif # VERSION_6K + +:ldrh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=11 & Rd & addrmode3 +{ + build COND; + build addrmode3; + Rd = zext( *:2 addrmode3); +} + +@if defined(VERSION_6T2) + +:ldrht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=11 & Rd & addrmode3 { + build COND; + build addrmode3; + Rd = zext( *:2 addrmode3); +} + +@endif # VERSION_6T2 + +:ldrsb^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=13 & Rd & addrmode3 +{ + build COND; + build addrmode3; + Rd = sext( *:1 addrmode3); +} + +@if defined(VERSION_6T2) + +:ldrsbt^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=13 & Rd & addrmode3 { + build COND; + build addrmode3; + Rd = sext( *:1 addrmode3); +} + +@endif # VERSION_6T2 + +:ldrsh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=1 & c0407=15 & Rd & addrmode3 +{ + build COND; + build addrmode3; + Rd = sext( *:2 addrmode3); +} + +@if defined(VERSION_6T2) + +:ldrsht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=1 & c0407=15 & Rd & addrmode3 { + build COND; + build addrmode3; + Rd = sext( *:2 addrmode3); +} + +@endif # VERSION_6T2 + +# The following form of ldr assumes alignment checking is on +:ldrt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=1 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + Rd = *addrmode2; +} + + +###### must come first cond=15 +@if defined(VERSION_5) +:mcr2 cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & cond=15 & c2427=14 & opc1 & c2020=0 & CRn & Rd & cpn & opc2 & c0404=1 & CRm +{ + t_cpn:4 = cpn; + t_op1:4 = opc1; + t_op2:4 = opc2; + coprocessor_moveto(t_cpn,t_op1,t_op2,Rd,CRn,CRm); +} +@endif # VERSION_5 +###### must come first cond=15 + + +# ===== START mcr + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Main_ID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Cache_Type(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_TCM_Status(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_TLB_Type(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Auxiliary_Control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Coprocessor_Access_Control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Secure_Configuration(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Secure_Debug_Enable(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_NonSecure_Access_Control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Translation_table_base_0(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Translation_table_base_1(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Translation_table_control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=3 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Domain_Access_Control(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=5 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Data_Fault_Status(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=5 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Instruction_Fault(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=6 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Fault_Address(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=6 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Instruction_Fault(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Wait_for_interrupt(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Entire_Instruction(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Instruction_Cache_by_MVA(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Flush_Prefetch_Buffer(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Entire_Data_cache(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Entire_Data_by_MVA(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Entire_Data_by_Index(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Clean_Entire_Data_Cache(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Clean_Data_Cache_by_MVA(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Clean_Data_Cache_by_Index(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Data_Synchronization(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=5 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Data_Memory_Barrier(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=14 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Entire_Data_Cache(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=14 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_Data_Cache_by_MVA(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_unified_TLB_unlocked(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_unified_TLB_by_MVA(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=8 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Invalidate_unified_TLB_by_ASID_match(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_FCSE_PID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Context_ID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_User_RW_Thread_and_Process_ID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_User_R_Thread_and_Process_ID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=13 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Privileged_only_Thread_and_Process_ID(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=2 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=15 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + coproc_moveto_Peripherial_Port_Memory_Remap(Rd); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opt2:4=opc2; + coproc_moveto_Feature_Identification(Rd,t_opt2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=2 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opt2:4=opc2; + coproc_moveto_ISA_Feature_Identification(Rd,t_opt2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=4 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=2 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Peripheral_Port_Memory_Remap(Rd,t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Control_registers(Rd, t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Security_world_control(Rd, t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=2 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Translation_table(Rd,t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Instruction_cache(Rd,t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + coproc_moveto_Data_cache_operations(Rd,t_opc2); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=0 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; t_crm:4 = CRm; + coproc_moveto_Identification_registers(Rd,t_opc2,t_crm); +} + + +:mcr^COND mcrOperands is + $(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=15 & c2020=0 & opc1 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; t_crm:4 = CRm; t_op1:4 = opc1; + coproc_moveto_Peripheral_System(Rd,t_opc2,t_crm,t_op1); +} + + +# ===== END mcr + +:mcr^COND cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & COND & c2427=14 & opc1 & c2020=0 & CRn & Rd & cpn & opc2 & c0404=1 & CRm +{ + build COND; + t_cpn:4 = cpn; + t_op1:4 = opc1; + t_op2:4 = opc2; + coprocessor_moveto(t_cpn,t_op1,t_op2,Rd,CRn,CRm); +} + +##### must come first cond=15 +@if defined(VERSION_6) +:mcrr2 cpn,opcode3,Rd,Rn,CRm is $(AMODE) & cond=15 & c2027=0xc4 & cpn & opcode3 & Rd & Rn & CRm +{ + t_cpn:4 = cpn; + t_op:4 = opcode3; + coprocessor_moveto2(t_cpn,t_op,Rd,Rn,CRm); +} + +:mrrc2 cpn,opcode3,Rd,Rn,CRm is $(AMODE) & cond=15 & c2027=0xc5 & cpn & opcode3 & Rd & Rn & CRm +{ + t_cpn:4 = cpn; + t_op:4 = opcode3; + Rd = coprocessor_movefromRt(t_cpn,t_op,CRm); + Rn = coprocessor_movefromRt2(t_cpn,t_op,CRm); +} +@endif # VERSION_6 +##### must come first cond=15 + + +@if defined(VERSION_5E) + +:mcrr^COND cpn,opcode3,Rd,Rn,CRm is $(AMODE) & c2027=0xc4 & COND & cpn & opcode3 & Rd & Rn & CRm +{ + build COND; + t_cpn:4 = cpn; + t_op:4 = opcode3; + coprocessor_moveto2(t_cpn,t_op,Rd,Rn,CRm); +} + +:mrrc^COND cpn,opcode3,Rd,Rn,CRm is $(AMODE) & c2027=0xc5 & COND & cpn & opcode3 & Rd & Rn & CRm +{ + build COND; + t_cpn:4 = cpn; + t_op:4 = opcode3; + Rd = coprocessor_movefromRt(t_cpn,t_op,CRm); + Rn = coprocessor_movefromRt2(t_cpn,t_op,CRm); +} + +@endif # VERSION_5E + +:mla^COND^SBIT_ZN Rn,Rm,Rs,Rd is $(AMODE) & COND & c2527=0 & c2124=1 & SBIT_ZN & Rn & Rd & Rs & c0407=9 & Rm +{ + build COND; + Rn = Rm*Rs + Rd; + resultflags(Rn); + build SBIT_ZN; +} + +@if defined(VERSION_6T2) + +:mls^COND Rn,Rm,Rs,Rd is $(AMODE) & COND & c2027=0x06 & Rn & Rd & Rs & c0407=9 & Rm { + build COND; + Rn = Rd - Rm*Rs; +} + +@endif # VERSION_6T2 + +:mov^COND^SBIT_CZNO Rd,shift1 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift1 +{ + build COND; + build shift1; + Rd = shift1; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mov^COND^SBIT_CZNO Rd,shift2 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift2 +{ + build COND; + build shift2; + Rd = shift2; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mov lr,pc is $(AMODE) & c0031=0xe1a0e00f & lr & pc + [ LRset=1; globalset(inst_next,LRset); ] +{ + lr = inst_next + 4; + resultflags(lr); + logicflags(); +} + +:mov^COND^SBIT_CZNO Rd,shift3 is $(AMODE) & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift3 +{ + build COND; + build shift3; + Rd = shift3; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mov^COND^SBIT_CZNO pc,shift1 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift1 +{ + build COND; + build shift1; + SetThumbMode((shift1&0x00000001)!=0); + local tmp=shift1&0xfffffffe; + resultflags(tmp); + logicflags(); + build SBIT_CZNO; + ALUWritePC(tmp); + goto [pc]; +} + +:mov^COND^SBIT_CZNO pc,shift2 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2 +{ + build COND; + build shift2; + SetThumbMode((shift2&0x00000001)!=0); + local tmp=shift2&0xfffffffe; + resultflags(tmp); + logicflags(); + build SBIT_CZNO; + ALUWritePC(tmp); + goto [pc]; +} +:mov^COND^SBIT_CZNO pc,shift2 is $(AMODE) & LRset=1 & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2 +{ + build COND; + build shift2; + SetThumbMode((shift2&0x00000001)!=0); + local tmp=shift2&0xfffffffe; + resultflags(tmp); + logicflags(); + build SBIT_CZNO; + ALUWritePC(tmp); + call [pc]; +} + +:mov^COND^SBIT_CZNO pc,shift3 is $(AMODE) & pc & COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift3 +{ + build COND; + build shift3; + SetThumbMode((shift3&0x00000001)!=0); + local tmp=shift3&0xfffffffe; + resultflags(tmp); + logicflags(); + build SBIT_CZNO; + ALUWritePC(tmp); + goto [pc]; +} + +:mov lr,rm is $(AMODE) & cond=15 & c2527=0 & S20=0 & c2124=13 & c1619=0 & rm & Rm2=15 & sftimm=0 & c0406=0 & Rd=14 & lr + [ LRset=1; globalset(inst_next,LRset); ] +{ + lr = rm; +} + +:mov^COND pc,lr is $(AMODE) & pc & COND & c2527=0 & S20=0 & c2124=13 & c1619=0 & Rd=15 & sftimm=0 & c0406=0 & Rm=14 & lr +{ + build COND; + dest:4 = lr; + ALUWritePC(dest); + return [pc]; +} + +@if defined(VERSION_6T2) + +:movw^COND Rd,"#"^val is $(AMODE) & COND & c2027=0x30 & c1619 & Rd & c0011 [ val = (c1619 << 12) | c0011; ] { + build COND; + Rd = val; +} + +:movt^COND Rd,"#"^val is $(AMODE) & COND & c2027=0x34 & c1619 & Rd & c0011 [ val = (c1619 << 12) | c0011; ] { + build COND; + Rd = (val << 16) | (Rd & 0xffff); +} + +@endif # VERSION_6T2 + +###### must come before next instruction because cond=15 +@if defined(VERSION_5) + + +:mrc2 cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & cond=15 & c2427=14 & opc1 & c2020=1 & CRn & Rd & cpn & opc2 & c0404=1 & CRm +{ + t_cpn:4 = cpn; + t_op1:4 = opc1; + t_op2:4 = opc2; + Rd = coprocessor_movefromRt(t_cpn,t_op1,t_op2,CRn,CRm); +} +@endif # VERSION_5 + +# ===== Start mrc + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Main_ID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Cache_Type(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_TCM_Status(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_TLB_Type(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Auxiliary_Control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Coprocessor_Access_Control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Secure_Configuration(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Secure_Debug_Enable(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_NonSecure_Access_Control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Translation_table_base_0(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Translation_table_base_1(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Translation_table_control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=3 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Domain_Access_Control(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=5 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Instruction_Fault_Status(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=5 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Data_Fault_Status(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=6 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Fault_Address(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=6 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Instruction_Fault_Address(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Wait_for_interrupt(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Entire_Instruction(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Instruction_Cache_by_MVA(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Flush_Prefetch_Buffer(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Entire_Data_cache(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Entire_Data_by_MVA(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=6 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Entire_Data_by_Index(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Clean_Entire_Data_Cache(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Clean_Data_Cache_by_MVA(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Clean_Data_Cache_by_Index(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Data_Synchronization(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2=5 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Data_Memory_Barrier(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=14 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Entire_Data_Cache(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=14 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_Data_Cache_by_MVA(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_unified_TLB_unlocked(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_unified_TLB_by_MVA(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=7 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=8 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Invalidate_unified_TLB_by_ASID_match(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=0 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_FCSE_PID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=1 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Context_ID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=2 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_User_RW_Thread_and_Process_ID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=3 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_User_R_Thread_and_Process_ID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=13 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Privileged_only_Thread_and_Process_ID(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=2 & c0404=1 & opc2=4 & cpn=15 & Rd & CRn=15 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + Rd = coproc_movefrom_Peripherial_Port_Memory_Remap(); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opt2:4=opc2; + Rd = coproc_movefrom_Feature_Identification(t_opt2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=2 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_ISA_Feature_Identification(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=4 & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=2 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Peripheral_Port_Memory_Remap(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Control_registers(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=1 & c0404=1 & opc2 & cpn=15 & Rd & CRn=1 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Security_world_control(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=0 & c0404=1 & opc2 & cpn=15 & Rd & CRn=2 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Translation_table(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=5 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Instruction_cache(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm=10 & c0404=1 & opc2 & cpn=15 & Rd & CRn=7 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; + Rd = coproc_movefrom_Data_cache_operations(t_opc2); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=0 & c2020=1 & opc1=0 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; t_crm:4 = CRm; + Rd = coproc_movefrom_Identification_registers(t_opc2,t_crm); +} + + + +:mrc^COND mcrOperands is + $(AMODE) & CRm & c0404=1 & opc2 & cpn=15 & Rd & CRn=15 & c2020=1 & opc1 & c2427=14 & COND & + mcrOperands +{ + build COND; + t_opc2:4 = opc2; t_crm:4 = CRm; t_op1:4 = opc1; + Rd = coproc_movefrom_Peripheral_System(t_opc2,t_crm,t_op1); +} + + + +# ===== End mrc + +:mrc^COND cpn,opc1,Rd,CRn,CRm,opc2 is $(AMODE) & COND & c2427=14 & opc1 & c2020=1 & CRn & Rd & cpn & opc2 & c0404=1 & CRm +{ + build COND; + t_cpn:4 = cpn; + t_op1:4 = opc1; + t_opc2:4 = opc2; + Rd = coprocessor_movefromRt(t_cpn,t_op1,t_opc2,CRn,CRm); +} + + +:mrs^COND Rd,cpsr is $(AMODE) & COND & c2027=16 & c1619=15 & Rd & offset_12=0 & cpsr +{ +# TODO: GE bits have not been included + build COND; + Rd = zext( (NG<<4) | (ZR<<3) | (CY<<2) | (OV<<1) | (Q) ) << 27; +} + +:mrs^COND Rd,spsr is $(AMODE) & COND & c2027=20 & c1619=15 & Rd & offset_12=0 & spsr +{ + build COND; + Rd = spsr; +} + +:msr^COND cpsrmask,shift1 is $(AMODE) & COND & c2027=50 & cpsrmask & c1215=15 & c2627=0 & shift1 +{ + build COND; + build cpsrmask; + build shift1; + cpsr = (cpsr& ~cpsrmask) | (shift1 & cpsrmask); +} + +:msr^COND cpsrmask,rm is $(AMODE) & COND & c2027=18 & cpsrmask & c1215=15 & c0811=0 & c0407=0 & rm +{ +# TODO: GE bits have not been included + build COND; + build cpsrmask; + cpsr = (cpsr& ~cpsrmask) | (rm & cpsrmask); + local tmp = cpsr >> 27 & 0x1f; + Q = ((tmp ) & 0x1) != 0; + OV = ((tmp >> 1) & 0x1) != 0; + CY = ((tmp >> 2) & 0x1) != 0; + ZR = ((tmp >> 3) & 0x1) != 0; + NG = ((tmp >> 4) & 0x1) != 0; +} + +:msr^COND spsrmask,shift1 is $(AMODE) & COND & c2027=54 & spsrmask & c1215=15 & c2627=0 & shift1 +{ + build COND; + build spsrmask; + build shift1; + spsr = (spsr& ~spsrmask) | (shift1 & spsrmask); +} + +:msr^COND spsrmask,rm is $(AMODE) & COND & c2027=22 & spsrmask & c1215=15 & c0811=0 & c0407=0 & rm +{ + build COND; + build spsrmask; + spsr = (spsr& ~spsrmask) | (rm & spsrmask); +} + +:mul^COND^SBIT_ZN rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=0 & SBIT_ZN & rn & c1215=0 & rs & c0407=9 & rm +{ + build COND; + build rm; + build rs; + rn = rm*rs; + resultflags(rn); + build SBIT_ZN; +} + +:mvn^COND^SBIT_CZNO Rd,shift1 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift1 +{ + build COND; + build shift1; + Rd=~shift1; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mvn^COND^SBIT_CZNO Rd,shift2 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift2 +{ + build COND; + build shift2; + Rd=~shift2; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mvn^COND^SBIT_CZNO Rd,shift3 is $(AMODE) & COND & c2124=15 & SBIT_CZNO & c1619=0 & Rd & c2627=0 & shift3 +{ + build COND; + build shift3; + Rd=~shift3; + resultflags(Rd); + logicflags(); + build SBIT_CZNO; +} + +:mvn^COND^SBIT_ZN pc,shift1 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift1 +{ + build COND; + build shift1; + dest:4 = ~shift1; + resultflags(dest); + build SBIT_ZN; + ALUWritePC(dest); + goto [pc]; +} + +:mvn^COND^SBIT_ZN pc,shift2 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift2 +{ + build COND; + build shift2; + dest:4 = ~shift2; + resultflags(dest); + build SBIT_ZN; + ALUWritePC(dest); + goto [pc]; +} + +:mvn^COND^SBIT_ZN pc,shift3 is $(AMODE) & pc & COND & c2124=15 & SBIT_ZN & c1619=0 & Rd=15 & c2627=0 & shift3 +{ + build COND; + build shift3; + dest:4 = ~shift3; + resultflags(dest); + build SBIT_ZN; + ALUWritePC(dest); + goto [pc]; +} + +@if defined(VERSION_6K) || defined(VERSION_6T2) || defined(VERSION_7) + +:nop^COND is $(AMODE) & COND & c0027=0x320f000 { +} + +@endif # VERSION_6K + +:orr^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + Rd = rn|shift1; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:orr^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + Rd = rn|shift2; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:orr^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=12 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + Rd = rn|shift3; + logicflags(); + resultflags(Rd); + build SBIT_CZNO; +} + +:orr^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + dest:4 = rn|shift1; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:orr^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + dest:4 = rn|shift2; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:orr^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=12 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + dest:4 = rn|shift3; + logicflags(); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +@if defined(VERSION_6) + +:pkhbt^COND Rd,rn,shift4 is $(AMODE) & COND & c2027=0x68 & c0406=1 & Rd & rn & shift4 +{ + build COND; + build rn; + build shift4; + Rd = (rn & 0xffff) + (shift4 & 0xffff0000); +} + +:pkhtb^COND Rd,rn,shift4 is $(AMODE) & COND & c2027=0x68 & c0406=5 & Rd & rn & shift4 +{ + build COND; + build rn; + build shift4; + Rd = (shift4 & 0xffff) + (rn & 0xffff0000); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:qadd^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x10 & Rn & Rd & c0811=0 & c0407=5 & Rm +{ + build COND; + local sum1 = Rm + Rn; + sum1 = SignedSaturate(sum1,32:2); + Q = SignedDoesSaturate(sum1,32:2); + Rd = sum1; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:qadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=1 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + sum1:2 = lRn:2 + lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 + uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +:qadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=9 & Rn & Rd & Rm +{ + build COND; + local rn1 = Rn & 0xff; + local rm1 = Rm & 0xff; + local rn2 = (Rn >> 8) & 0xff; + local rm2 = (Rm >> 8) & 0xff; + local rn3 = (Rn >> 16) & 0xff; + local rm3 = (Rm >> 16) & 0xff; + local rn4 = (Rn >> 24) & 0xff; + local rm4 = (Rm >> 24) & 0xff; + sum1:1 = rn1:1 + rm1:1; + sum1 = SignedSaturate(sum1,8:2); + sum2:1 = rn2:1 + rm2:1; + sum2 = SignedSaturate(sum2,8:2); + sum3:1 = rn3:1 + rm3:1; + sum3 = SignedSaturate(sum3,8:2); + sum4:1 = rn4:1 + rm4:1; + sum4 = SignedSaturate(sum4,8:2); + Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +# qaddsubx +:qasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=3 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + sum1:2 = lRn:2 - lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 + uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:qdadd^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x14 & Rn & Rd & c0811=0 & c0407=5 & Rm +{ + build COND; + tmp:4 = Rn * 2; + tmp = SignedSaturate(tmp,32:2); + Q = SignedDoesSaturate(tmp,32:2); + tmp = tmp + Rm; + tmp = SignedSaturate(tmp,32:2); + Q = Q | SignedDoesSaturate(tmp,32:2); + Rd = tmp; +} + +:qdsub^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x16 & Rn & Rd & c0811=0 & c0407=5 & Rm +{ + build COND; + tmp:4 = Rn * 2; + tmp = SignedSaturate(tmp); + Q = SignedDoesSaturate(tmp,32:2); + tmp = Rm - tmp; + tmp = SignedSaturate(tmp,32:2); + Q = Q | SignedDoesSaturate(tmp,32:2); + Rd = tmp; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +# qsubaddx +:qsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=5 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + sum1:2 = lRn:2 + lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 - uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:qsub^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=0x12 & Rn & Rd & c0811=0 & c0407=5 & Rm +{ + build COND; + tmp:4 = Rm - Rn; + tmp = SignedSaturate(tmp,32:2); + Q = SignedDoesSaturate(tmp,32:2); + Rd = tmp; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:qsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=7 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + sum1:2 = lRn:2 - lRm:2; + sum1 = SignedSaturate(sum1,16:2); + sum2:2 = uRn:2 - uRm:2; + sum2 = SignedSaturate(sum2,16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +:qsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x62 & c0811=15 & c0407=15 & Rn & Rd & Rm +{ + build COND; + local rn1 = Rn & 0xff; + local rm1 = Rm & 0xff; + local rn2 = (Rn >> 8) & 0xff; + local rm2 = (Rm >> 8) & 0xff; + local rn3 = (Rn >> 16) & 0xff; + local rm3 = (Rm >> 16) & 0xff; + local rn4 = (Rn >> 24) & 0xff; + local rm4 = (Rm >> 24) & 0xff; + sum1:1 = rn1:1 - rm1:1; + sum1 = SignedSaturate(sum1,8:2); + sum2:1 = rn2:1 - rm2:1; + sum2 = SignedSaturate(sum2,8:2); + sum3:1 = rn3:1 - rm3:1; + sum3 = SignedSaturate(sum3,8:2); + sum4:1 = rn4:1 - rm4:1; + sum4 = SignedSaturate(sum4,8:2); + Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +@endif # VERSION_6 + +@if defined(VERSION_6T2) + +macro BitReverse_arm(val) { + tval:1 = val; + result:1 = 0; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + result = (result << 1) | (tval & 1); + tval = tval >> 1; + val = result; +} + + +:rbit^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=3 & c1619=15 & c0811=15 & Rd & rm +{ + build COND; + build rm; + local t:4 = rm & 0xff; + local b1:1 = t:1; + t = (rm >> 8) & 0xff; + local b2:1 = t:1; + t = (rm >> 16) & 0xff; + local b3:1 = t:1; + t = (rm >> 24) & 0xff; + local b4:1 = t:1; + BitReverse_arm(b1); + BitReverse_arm(b2); + BitReverse_arm(b3); + BitReverse_arm(b4); + Rd = (zext(b1) << 24) | (zext(b2) << 16) | (zext(b3) << 8) | zext(b4); +} + +@endif # VERSION_6T2 + +@if defined(VERSION_6) + +:rev^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=3 & c1619=15 & c0811=15 & Rd & rm +{ + build COND; + build rm; + local tmp1 = rm & 0xff; + local tmp2 = (rm >> 8) & 0xff; + local tmp3 = (rm >> 16) & 0xff; + local tmp4 = (rm >> 24) & 0xff; + Rd = (tmp1 << 24) | (tmp2 << 16) | (tmp3 << 8) | tmp4; +} + +:rev16^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=11 & Rd & rm +{ + build COND; + build rm; + local tmp1 = rm & 0xff; + local tmp2 = (rm >> 8) & 0xff; + local tmp3 = (rm >> 16) & 0xff; + local tmp4 = (rm >> 24) & 0xff; + Rd = (tmp3 << 24) | (tmp4 << 16) | (tmp1 << 8) | tmp2; +} + +:revsh^COND Rd, rm is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=11 & Rd & rm +{ + build COND; + build rm; + local tmp1 = rm & 0xff; + local tmp2 = (rm >> 8) & 0xff; + tmp3:2 = zext(tmp1:1) << 8 | zext(tmp2:1); + Rd = sext(tmp3); +} + +@endif # VERSION_6 + +:rsb^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(shift1,rn); + Rd = shift1-rn; + resultflags(Rd); + build SBIT_CZNO; +} + +:rsb^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + subflags(shift2,rn); + Rd = shift2-rn; + resultflags(Rd); + build SBIT_CZNO; +} + +:rsb^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=3 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + subflags(shift3,rn); + Rd = shift3-rn; + resultflags(Rd); + build SBIT_CZNO; +} + +:rsb^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(shift1,rn); + dest:4 = shift1-rn; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:rsb^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + subflags(shift2,rn); + dest:4 = shift2-rn; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:rsb^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=3 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + subflags(shift3,rn); + dest:4 = shift3-rn; + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:rsc^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + sub_with_carry_flags(shift1,rn); + Rd=shift1-(rn+zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:rsc^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + sub_with_carry_flags(shift2,rn); + Rd=shift2-(rn+zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:rsc^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=7 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + sub_with_carry_flags(shift3,rn); + Rd=shift3-(rn+zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:rsc^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + sub_with_carry_flags(shift1,rn); + local dest:4=shift1-(rn+zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:rsc^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + sub_with_carry_flags(shift2,rn); + local dest:4=shift2-(rn + zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:rsc^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=7 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + sub_with_carry_flags(shift3,rn); + local dest:4=shift3-(rn + zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +@if defined(VERSION_6) + +:sadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=1 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn & 0xffff; + local tmpRm = Rm & 0xffff; + local sum1 = sext(tmpRn:2) + sext(tmpRm:2); + GE1 = sum1 s>= 0; + GE2 = sum1 s>= 0; + tmpRn = (Rn >> 16) & 0xffff; + tmpRm = (Rm >> 16) & 0xffff; + local sum2 = sext(tmpRn:2) + sext(tmpRm:2); + GE3 = sum2 s>= 0; + GE4 = sum2 s>= 0; + Rd = ((sum2 & 0xffff) << 16) | (sum1 & 0xffff); +} + +:sadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=9 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn & 0xff; + local tmpRm = Rm & 0xff; + local sum1 = sext(tmpRn:1) + sext(tmpRm:1); + GE1 = sum1 s>= 0; + tmpRn = (Rn >> 8) & 0xff; + tmpRm = (Rm >> 8) & 0xff; + local sum2 = sext(tmpRn:1) + sext(tmpRm:1); + GE2 = sum2 s>= 0; + tmpRn = (Rn >> 16) & 0xff; + tmpRm = (Rm >> 16) & 0xff; + local sum3 = sext(tmpRn:1) + sext(tmpRm:1); + GE3 = sum3 s>= 0; + tmpRn = (Rn >> 24) & 0xff; + tmpRm = (Rm >> 24) & 0xff; + local sum4 = sext(tmpRn:1) + sext(tmpRm:1); + GE4 = sum4 s>= 0; + Rd = ((sum4 & 0xff) << 24) | ((sum3 & 0xff) << 16) | ((sum2 & 0xff) << 8) | (sum1 & 0xff); +} + +# saddsubx +:sasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=3 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + local sum1 = sext(uRn:2) + sext(lRm:2); + GE3 = sum1 s>= 0; + GE4 = sum1 s>= 0; + local diff = sext(lRn:2) - sext(uRm:2); + GE1 = diff s>= 0; + GE2 = diff s>= 0; + + Rd = ((sum1 & 0xffff) << 16) | (diff & 0xffff); +} + +@endif # VERSION_6 + +:sbc^SBIT_CZNO^COND Rd,rn,shift1 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + sub_with_carry_flags(rn,shift1); + Rd = rn-(shift1+zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:sbc^SBIT_CZNO^COND Rd,rn,shift2 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + sub_with_carry_flags(rn,shift2); + Rd = rn-(shift2 + zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:sbc^SBIT_CZNO^COND Rd,rn,shift3 is $(AMODE) & COND & c2124=6 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + sub_with_carry_flags(rn,shift3); + Rd = rn-(shift3+zext(!CY)); + resultflags(Rd); + build SBIT_CZNO; +} + +:sbc^SBIT_CZNO^COND pc,rn,shift1 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + sub_with_carry_flags(rn,shift1); + local dest:4 = rn-(shift1 + zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:sbc^SBIT_CZNO^COND pc,rn,shift2 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + sub_with_carry_flags(rn,shift2); + local dest:4 = rn-(shift2+zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +:sbc^SBIT_CZNO^COND pc,rn,shift3 is $(AMODE) & pc & COND & c2124=6 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + sub_with_carry_flags(rn,shift3); + local dest:4 = rn-(shift3 + zext(!CY)); + resultflags(dest); + build SBIT_CZNO; + ALUWritePC(dest); + goto [pc]; +} + +@if defined(VERSION_6) + +@if defined(VERSION_6T2) + +:sbfx^COND Rd,Rm,lsbImm,widthMinus1 is $(AMODE) & COND & c2127=0x3d & widthMinus1 & Rd & lsbImm & c0406=5 & Rm +{ + build COND; + build lsbImm; + build widthMinus1; + shift:4 = 31 - (lsbImm + widthMinus1); + Rd = Rm << shift; + shift = 31 - widthMinus1; + Rd = Rd s>> shift; +} + +@endif # VERSION_6T2 + +@if defined(VERSION_7) + +# Warning: note the non-standard use of Rd, Rm, Rn +:sdiv^COND RdHi,RnLo,RmHi is $(AMODE) & COND & c2027=0x71 & RdHi & c1215=0xf & RmHi & c0407=0x1 & RnLo +{ + build COND; + local result = RnLo / RmHi; + RdHi = result; +} + +@endif # VERSION_7 + +:sel^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x68 & Rn & Rd & c0811=15 & c0407=11 & Rm +{ + build COND; + local rD1 = ((zext(GE1) * Rn) + (zext(!GE1) * Rm)) & 0x0ff; + local rD2 = ((zext(GE2) * Rn) + (zext(!GE2) * Rm)) & 0x0ff00; + local rD3 = ((zext(GE3) * Rn) + (zext(!GE3) * Rm)) & 0x0ff0000; + local rD4 = ((zext(GE4) * Rn) + (zext(!GE4) * Rm)) & 0x0ff000000; + Rd = rD1 | rD2 | rD3 | rD4; +} + +@if defined(VERSION_6K) + +:sev^COND is $(AMODE) & COND & c0027=0x320f004 +{ + build COND; + SendEvent(); +} + +@endif # VERSION_6K + +# Hopefully we never encounter this instruction since we can not change the effective endianess of the language +armEndianNess: "LE" is c0031=0xf1010000 { export 0:1; } +armEndianNess: "BE" is c0031=0xf1010200 { export 1:1; } + +:setend armEndianNess is $(AMODE) & (c0031=0xf1010000 | c0031=0xf1010200) & armEndianNess { setEndianState(armEndianNess); } + + +:shadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=1 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + sum1:4 = (sext(tmpRn:2) + sext(tmpRm:2)) >> 1; + sum2:4 = ((tmpRn s>> 16) + (tmpRm s>> 16)) >> 1; + Rd = (sum2 << 16) + (sum1 & 0xffff); +} + +:shadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=9 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + sum1:4 = (sext(tmpRn:1) + sext(tmpRm:1)) >> 1; + local tmpn = tmpRn >> 8; + local tmpm = tmpRm >> 8; + sum2:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1; + tmpn = tmpRn >> 16; + tmpm = tmpRm >> 16; + sum3:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1; + tmpn = tmpRn >> 24; + tmpm = tmpRm >> 24; + sum4:4 = (sext(tmpn:1) + sext(tmpm:1)) >> 1; + Rd = (sum4 << 24) + ((sum3 & 0xff) << 16) + ((sum2 & 0xff) << 8) + (sum1 & 0xff); +} + +# shaddsubx +:shasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=3 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + local diff:4 = sext(tmpRn[ 0,16]) - sext(tmpRm[16,16]); + local sum:4 = sext(tmpRn[16,16]) + sext(tmpRm[ 0,16]); + Rd[0,16] = diff[1,16]; + Rd[16,16] = sum[1,16]; +} + +# shsubbaddx +:shsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=5 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + local sum:4 = sext(tmpRn[ 0,16]) + sext(tmpRm[16,16]); + local diff:4 = sext(tmpRn[16,16]) - sext(tmpRm[ 0,16]); + Rd[ 0,16] = sum[1,16]; + Rd[16,16] = diff[1,16]; +} + +:shsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=7 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + sum1:4 = (sext(tmpRn:2) - sext(tmpRm:2)) >> 1; + sum2:4 = ((tmpRn s>> 16) - (tmpRm s>> 16)) >> 1; + Rd = (sum2 << 16) + (sum1 & 0xffff); +} + +:shsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x63 & Rn & Rd & c0811=15 & c0407=15 & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + sum1:4 = (sext(tmpRn:1) - sext(tmpRm:1)) >> 1; + local tmpn = tmpRn >> 8; + local tmpm = tmpRm >> 8; + sum2:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1; + tmpn = tmpRn >> 16; + tmpm = tmpRm >> 16; + sum3:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1; + tmpn = tmpRn >> 24; + tmpm = tmpRm >> 24; + sum4:4 = (sext(tmpn:1) - sext(tmpm:1)) >> 1; + Rd = (sum4 << 24) + ((sum3 & 0xff) << 16) + ((sum2 & 0xff) << 8) + (sum1 & 0xff); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:smla^XBIT^YBIT^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x10 & smRd & smRn & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRa +{ + build COND; + local tmp:4 = sext(XBIT) * sext(YBIT); + Q = scarry(tmp,smRa) || Q; #Q flag is sticky + smRd = tmp+smRa; +} + +@endif + +@if defined(VERSION_6) + +:smlad^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & c0407=1 & smRd & smRa & smRm & smRn +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + local tmpLRn = tmpRn:2; + local tmpURn = tmpRn >> 16; + local tmpLRm = tmpRm:2; + local tmpURm = tmpRm >> 16; + local product1 = sext(tmpLRn) * sext(tmpLRm); + local product2 = sext(tmpURn:2) * sext(tmpURm:2); + local tmpprod = product1 + product2; + Q = scarry(smRa, tmpprod) || Q; #Q is sticky + smRd = smRa + tmpprod; +} + +:smladx^COND smRd, smRn, smRm, smRa is $(AMODE) & COND & c2027=0x70 & c0407=3 & smRd & smRn & smRm & smRa +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + local tmpLRn = tmpRn:2; + local tmpURn = tmpRn >> 16; + local tmpLRm = tmpRm:2; + local tmpURm = tmpRm >> 16; + local product1 = sext(tmpLRn) * sext(tmpURm:2); + local product2 = sext(tmpURn:2) * sext(tmpLRm); + local tmpprod = product1 + product2; + Q = scarry(smRa, tmpprod) || Q; #Q is sticky + smRd = smRa + tmpprod; +} + +@endif # VERSION_6 + +:smlal^COND^SBIT_ZN RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2527=0 & c2124=7 & SBIT_ZN & RdLo & RdHi & smRn & c0407=9 & smRm +{ + build COND; + tmp:8 = (zext(RdHi) << 32) | zext(RdLo); + rs64:8 = sext(smRm); + rm64:8 = sext(smRn); + tmp = rs64 * rm64 + tmp; + resultflags(tmp); + RdLo = tmp(0); + RdHi = tmp(4); + build SBIT_ZN; +} + +@if defined(VERSION_5E) + +:smlal^XBIT^YBIT^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x14 & RdLo & RdHi & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRn +{ + build COND; + local prod:8 = sext(XBIT) * sext(YBIT); + local result:8 = (zext(RdHi) << 32) | zext(RdLo); + result = result + prod; + RdLo = result(0); + RdHi = result(4); +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:smlald^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdLo & RdHi & c0607=0 & c0405=1 & smRn & smRm +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + prod1:8 = sext(tmpRn:2) * sext(tmpRm:2); + rmHi:2 = tmpRm(2); + rnHi:2 = tmpRn(2); + prod2:8 = sext(rmHi) * sext(rnHi); + result:8 = zext(RdLo) + (zext(RdHi) << 32) + prod1 + prod2; + RdLo = result:4; + RdHi = result(4); +} + +:smlaldx^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdLo & RdHi & c0607=0 & c0405=3 & smRn & smRm +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + rmHi:2 = tmpRm(2); + rnHi:2 = tmpRn(2); + prod1:8 = sext(tmpRn:2) * sext(rmHi); + prod2:8 = sext(rnHi) * sext(tmpRm:2); + result:8 = zext(RdLo) + (zext(RdHi) << 32) + prod1 + prod2; + RdLo = result:4; + RdHi = result(4); +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:smlaw^YBIT^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x12 & smRd & smRn & smRm & c0707=1 & YBIT & x=0 & c0404=0 & smRa +{ + build COND; + local tmp64:6 = sext(smRn) * sext(YBIT); + local tmp32:4 = tmp64(2); + Q = scarry(tmp32, smRa) || Q; #Q flag is sticky + smRd = tmp32 + smRa; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:smlsd^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & smRd & smRn & c0607=1 & x=0 & c0404=1 & smRm & smRa +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + prod1:4 = sext(tmpRn:2) * sext(tmpRm:2); + rnHi:2 = tmpRn(2); + rmHi:2 = tmpRm(2); + prod2:4 = sext(rnHi) * sext(rmHi); + diff:4 = prod1 - prod2; + Q = scarry(diff, smRa) || Q; #Q is sticky + smRd = smRa + diff; +} + +:smlsdx^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x70 & smRd & smRn & c0607=1 & x=1 & c0404=1 & smRm & smRa +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + rnHi:2 = tmpRn(2); + rmHi:2 = tmpRm(2); + prod1:4 = sext(tmpRn:2) * sext(rmHi); + prod2:4 = sext(rnHi) * sext(tmpRm:2); + diff:4 = prod1 - prod2; + Q = scarry(diff, smRa) || Q; #Q is sticky + smRd = smRa + diff; +} + +:smlsld^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdHi & RdLo & smRm & c0607=1 & x=0 & c0404=1 & smRn +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + prod1:8 = sext(tmpRn:2) * sext(tmpRm:2); + rnHi:2 = tmpRn(2); + rmHi:2 = tmpRm(2); + prod2:8 = sext(rnHi) * sext(rmHi); + result:8 = zext(RdLo) + (zext(RdHi) << 32) + (prod1 - prod2); + RdLo = result:4; + RdHi = result(4); +} + +:smlsldx^COND RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2027=0x74 & RdHi & RdLo & smRm & c0607=1 & x=1 & c0404=1 & smRn +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + rnHi:2 = tmpRn(2); + rmHi:2 = tmpRm(2); + prod1:8 = sext(tmpRn:2) * sext(rmHi); + prod2:8 = sext(rnHi) * sext(tmpRm:2); + result:8 = zext(RdLo) + (zext(RdHi) << 32) + (prod1 - prod2); + RdLo = result:4; + RdHi = result(4); +} + +:smmla^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=0 & r=0 & c0404=1 & smRa +{ + build COND; + val:8 = sext(smRn) * sext(smRm); + val = (zext(smRa) << 32) + val; + smRd = val(4); +} + +:smmlar^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=0 & r=1 & c0404=1 & smRa +{ + build COND; + val:8 = sext(smRn) * sext(smRm); + val = (zext(smRa) << 32) + val + 0x80000000; + smRd = val(4); +} + +:smmls^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=3 & r=0 & c0404=1 & smRa +{ + build COND; + val:8 = sext(smRn) * sext(smRm); + val = (zext(smRa) << 32) - val; + smRd = val(4); +} + +:smmlsr^COND smRd,smRn,smRm,smRa is $(AMODE) & COND & c2027=0x75 & smRd & smRn & smRm & c0607=3 & r=1 & c0404=1 & smRa +{ + build COND; + val:8 = sext(smRn) * sext(smRm); + val = (zext(smRa) << 32) - val + 0x80000000; + smRd = val(4); +} + +:smmul^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x75 & smRd & c1215=15 & smRn & c0607=0 & r=0 & c0404=1 & smRm +{ + build COND; + val:8 = sext(smRn) * sext(smRm); + smRd = val(4); +} + +:smmulr^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x75 & smRd & c1215=15 & smRn & c0607=0 & r=1 & c0404=1 & smRm +{ + build COND; + val:8 = (sext(smRn) * sext(smRm)) + 0x080000000; + smRd = val(4); +} + +:smuad^COND smRd, smRn, smRm is $(AMODE) & COND & c2027=0x70 & c0407=1 & smRd & c1619=15 & smRn & smRm +{ + build COND; + local tmpRm = smRm; + local tmpRn = smRn; + local tmpLRm = tmpRm:2; + local tmpURm = tmpRm >> 16; + local tmpLRn = tmpRn:2; + local tmpURn = tmpRn >> 16; + local product1 = sext(tmpLRm) * sext(tmpLRn); + local product2 = sext(tmpURm:2) * sext(tmpURn:2); + local tmpprod = product1 + product2; + Q = scarry(product1, product2); + smRd = tmpprod; +} + +:smuadx^COND smRd, smRn, smRm is $(AMODE) & COND & c2027=0x70 & c0407=3 & smRd & c1619=15 & smRn & smRm +{ + build COND; + local tmpRm = smRm; + local tmpRn = smRn; + local tmpLRm = tmpRm:2; + local tmpURm = tmpRm >> 16; + local tmpLRn = tmpRn:2; + local tmpURn = tmpRn >> 16; + local product1 = sext(tmpLRm) * sext(tmpURn:2); + local product2 = sext(tmpURm:2) * sext(tmpLRn); + local tmpprod = product1 + product2; + Q = scarry(product1, product2); + smRd = tmpprod; +} + +@endif # VERSION_6 + +@if defined(VERSION_5E) + +:smul^XBIT^YBIT^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x16 & smRd & c1215=0 & smRm & c0707=1 & XBIT & YBIT & c0404=0 & smRn +{ + build COND; + tmp:8 = sext(XBIT) * sext(YBIT); + smRd = tmp:4; +} + +@endif # VERSION_5E + +:smull^COND^SBIT_ZN RdLo,RdHi,smRn,smRm is $(AMODE) & COND & c2527=0 & c2124=6 & SBIT_ZN & RdHi & RdLo & smRn & c0407=9 & smRm +{ + build COND; + rn64:8 = sext(smRn); + rm64:8 = sext(smRm); + local tmp = rn64 * rm64; + resultflags(tmp); + RdLo = tmp(0); + RdHi = tmp(4); + build SBIT_ZN; +} + +@if defined(VERSION_5E) + +:smulw^YBIT^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x12 & smRd & c1215=0 & smRn & c0707=1 & YBIT & x=1 & c0404=0 & smRm +{ + build COND; + tmp:6 = sext(smRn) * sext(YBIT); + tmp = tmp >> 16; + smRd = tmp:4; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:smusd^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x70 & smRd & c1215=15 & smRm & c0607=1 & x=0 & c0404=1 & smRn +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + rmHi:2 = tmpRm(2); + prod1:4 = sext(tmpRn:2) * sext(tmpRm:2); + rnHi:2 = tmpRn(2); + prod2:4 = sext(rnHi) * sext(rmHi); + smRd = prod1 - prod2; +} + +:smusdx^COND smRd,smRn,smRm is $(AMODE) & COND & c2027=0x70 & smRd & c1215=15 & smRm & c0607=1 & x=1 & c0404=1 & smRn +{ + build COND; + local tmpRn = smRn; + local tmpRm = smRm; + rmHi:2 = tmpRm(2); + rnHi:2 = tmpRn(2); + prod1:4 = sext(tmpRn:2) * sext(rmHi); + prod2:4 = sext(rnHi) * sext(tmpRm:2); + smRd = prod1 - prod2; +} + + +:ssat^COND Rd, sSatImm5, shift4 is $(AMODE) & COND & c2127=0x35 & c0405=1 & sSatImm5 & Rd & shift4 +{ + build COND; + build shift4; + tmp:4 = SignedSaturate(shift4, sSatImm5); + Q = SignedDoesSaturate(shift4, sSatImm5); + Rd = tmp; +} + +:ssat16^COND Rd, sSatImm4, Rm is $(AMODE) & COND & c2027=0x6a & c0811=15 & c0407=0x3 & sSatImm4 & Rd & Rm +{ + build COND; + build sSatImm4; + local tmpl = Rm & 0xffff; + tmpl = SignedSaturate(tmpl, sSatImm4); + local tmpu = Rm >> 16; + tmpu = SignedSaturate(tmpu, sSatImm4); + Q = SignedDoesSaturate(tmpl,sSatImm4) | SignedDoesSaturate(tmpu,sSatImm4); + Rd = ((tmpu & 0xffff) << 16) | (tmpl & 0xffff); +} + +# ssubaddx +:ssax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=5 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + local diff = sext(uRn:2) - sext(lRm:2); + GE3 = diff s>= 0; + GE4 = diff s>= 0; + local sum = sext(lRn:2) + sext(uRm:2); + GE1 = sum s>= 0; + GE2 = sum s>= 0; + Rd = ((diff & 0xffff) << 16) | (sum & 0xffff); +} + +:ssub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=7 & Rn & Rd & Rm +{ + build COND; + local lRn = Rn & 0xffff; + local lRm = Rm & 0xffff; + local uRn = (Rn >> 16) & 0xffff; + local uRm = (Rm >> 16) & 0xffff; + local diffl = sext(lRn:2) - sext(lRm:2); + GE1 = diffl s>= 0; + GE2 = diffl s>= 0; + local diffu = sext(uRn:2) - sext(uRm:2); + GE3 = diffu s>= 0; + GE4 = diffu s>= 0; + Rd = ((diffu & 0xffff) << 16) | (diffl & 0xffff); +} + +:ssub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x61 & c0811=15 & c0407=15 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn & 0xff; + local tmpRm = Rm & 0xff; + local diff1 = sext(tmpRn:1) - sext(tmpRm:1); + GE1 = diff1 s>= 0; + tmpRn = (Rn >> 8) & 0xff; + tmpRm = (Rm >> 8) & 0xff; + local diff2 = sext(tmpRn:1) - sext(tmpRm:1); + GE2 = diff2 s>= 0; + tmpRn = (Rn >> 16) & 0xff; + tmpRm = (Rm >> 16) & 0xff; + local diff3 = sext(tmpRn:1) - sext(tmpRm:1); + GE3 = diff3 s>= 0; + tmpRn = (Rn >> 24) & 0xff; + tmpRm = (Rm >> 24) & 0xff; + local diff4 = sext(tmpRn:1) - sext(tmpRm:1); + GE4 = diff4 s>= 0; + Rd = ((diff4 & 0xff) << 24) | ((diff3 & 0xff) << 16) | ((diff2 & 0xff) << 8) | (diff1 & 0xff); +} + +@endif # VERSION_6 + +:stc^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=0 & L20=0 +{ + build COND; + build addrmode5; + t_cpn:4 = cpn; + coprocessor_store(t_cpn,CRd,addrmode5); +} + +:stcl^COND cpn,CRd,addrmode5 is $(AMODE) & COND & c2527=6 & addrmode5 & cpn & CRd & N22=1 & L20=0 +{ + build COND; + build addrmode5; + t_cpn:4 = cpn; + coprocessor_storelong(t_cpn,CRd,addrmode5); +} + +:stm^mdir^COND reglist is $(AMODE) & COND & c2527=4 & mdir & L20=0 & reglist +{ + build COND; + build reglist; +} + +#:str^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +#{ +# build COND; +# build addrmode2; +# tmp=addrmode2&0xfffffffc; +# *tmp = Rd; +#} + +# The following form of str assumes alignment checking is on +:str^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + *addrmode2 = Rd; +} + +:strb^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=1 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + local tmpRd = Rd; + *addrmode2 = tmpRd:1; +} + +:strbt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 &P24=0 & B22=1 & W21=1 & L20=0 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + local tmpRd = Rd; + *addrmode2 = tmpRd:1; +} + +:strh^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & L20=0 & c0407=11 & Rd & addrmode3 +{ + build COND; + build addrmode3; + local tmpRd = Rd; + *addrmode3 = tmpRd:2; +} + +@if defined(VERSION_5E) + +:strd^COND Rd,Rd2,addrmode3 is $(AMODE) & COND & c2527=0 & c0407=0xf & L20=0 & Rd & Rd2 & addrmode3 +{ + build COND; + build addrmode3; + local addr = addrmode3; + *(addr) = Rd; + addr = addr + 4; + *(addr) = Rd2; +} + +@endif # VERSION_5E + +@if defined(VERSION_6) + +:strex^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x18 & c0411=0xf9 & Rn & Rd & Rm +{ + build COND; + local tmp = Rn; + access:1 = hasExclusiveAccess(tmp); + Rd = 1; + if (!access) goto inst_next; + Rd = 0; + *tmp = Rm; +} + +@endif # VERSION_6 + +@if defined(VERSION_6K) + +:strexb^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x1c & c0411=0xf9 & Rn & Rd & Rm +{ + build COND; + local tmp = Rn; + access:1 = hasExclusiveAccess(tmp); + Rd = 1; + if (!access) goto inst_next; + Rd = 0; + local tmpRm = Rm; + *tmp = tmpRm:1; +} + +:strexd^COND Rd,Rm,Rm2,[Rn] is $(AMODE) & COND & c2027=0x1a & Rn & Rd & c0411=0xf9 & c0003 & Rm & Rm2 +{ + build COND; + local addr = Rn; + access:1 = hasExclusiveAccess(addr); + Rd = 1; + if (!access) goto inst_next; + Rd = 0; + *(addr) = Rm; + addr = addr + 4; + *(addr) = Rm2; +} + +:strexh^COND Rd,Rm,[Rn] is $(AMODE) & COND & c2027=0x1e & c0411=0xf9 & Rn & Rd & Rm +{ + build COND; + local tmp = Rn; + access:1 = hasExclusiveAccess(tmp); + Rd = 1; + if (!access) goto inst_next; + Rd = 0; + local tmpRm = Rm; + *tmp = tmpRm:2; +} + +:strht^COND Rd,addrmode3 is $(AMODE) & COND & c2527=0 & P24=0 & W21=1 & L20=0 & c0407=11 & Rd & addrmode3 { + build COND; + *:2 addrmode3 = Rd; +} + +@endif # VERSION_6K + +#:strt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & P24=0 & W21=1 & Rd & addrmode2 +#{ +# build COND; +# build addrmode2; +# tmp=addrmode2&0xfffffffc; +# *tmp = Rd; +#} + +# The following form of str assumes alignment checking is on +:strt^COND Rd,addrmode2 is $(AMODE) & COND & c2627=1 & B22=0 & L20=0 & P24=0 & W21=1 & Rd & (I25=0 | (I25=1 & c0404=0)) & addrmode2 +{ + build COND; + build addrmode2; + *addrmode2 = Rd; +} + +:sub^COND^SBIT_CZNO Rd,rn,shift1 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(rn,shift1); + Rd = rn-shift1; + resultflags(Rd); + build SBIT_CZNO; +} + +:sub^COND^SBIT_CZNO Rd,rn,shift2 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + subflags(rn,shift2); + Rd = rn-shift2; + resultflags(Rd); + build SBIT_CZNO; +} + +:sub^COND^SBIT_CZNO Rd,rn,shift3 is $(AMODE) & COND & c2124=2 & SBIT_CZNO & rn & Rd & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + subflags(rn,shift3); + Rd = rn-shift3; + resultflags(Rd); + build SBIT_CZNO; +} + +:sub^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(rn,shift1); + dest:4 = rn-shift1; + resultflags(dest); + build SBIT_CZNO; + cpsr = spsr; + SetThumbMode( ((cpsr >> 5) & 1) != 0 ); + pc = dest; + goto [pc]; +} + +:sub^COND^SBIT_CZNO pc,rn,shift1 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & Rn=14 & I25=1 & immed=0 & rotate=0 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + subflags(rn,shift1); + dest:4 = rn-shift1; + resultflags(dest); + build SBIT_CZNO; + cpsr = spsr; + ALUWritePC(dest); + return [pc]; +} + +:sub^COND^SBIT_CZNO pc,rn,shift2 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + subflags(rn,shift2); + dest:4 = rn-shift2; + resultflags(dest); + build SBIT_CZNO; + cpsr = spsr; + SetThumbMode( ((cpsr >> 5) & 1) != 0 ); + pc = dest; + goto [pc]; +} + +:sub^COND^SBIT_CZNO pc,rn,shift3 is $(AMODE) & pc & COND & c2124=2 & SBIT_CZNO & rn & Rd=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + subflags(rn,shift3); + dest:4 = rn-shift3; + resultflags(dest); + build SBIT_CZNO; + cpsr = spsr; + SetThumbMode( ((cpsr >> 5) & 1) != 0 ); + pc = dest; + goto [pc]; +} + +:swi^COND immed24 is $(AMODE) & COND & c2427=15 & immed24 +{ + build COND; + tmp:4 = immed24; + software_interrupt(tmp); +} + +#:swp^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=16 & Rn & Rd & c0811=0 & c0407=9 & Rm +#{ +# build COND; +# tmp = Rn & 0xfffffffc; +# tmp2 = (Rn&3)<<3; +# val:4 = *tmp; +# val=(val>>tmp2) | (val << (32-tmp2)); +# *tmp = Rm; +# Rd = val; +#} + +# Assuming alignment checking is enabled +:swp^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=16 & Rn & Rd & c0811=0 & c0407=9 & Rm +{ + build COND; + val:4 = *Rn; + *Rn = Rm; + Rd = val; +} + +:swpb^COND Rd,Rm,Rn is $(AMODE) & COND & c2027=20 & Rn & Rd & c0811=0 & c0407=9 & Rm +{ + build COND; + local tmp = *:1 Rn; + local tmpRm = Rm; + *Rn = tmpRm:1; + Rd = zext(tmp); +} + +@if defined(VERSION_6) + +:sxtab^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=2 & c0407=7 & Rd & Rn & ror1 +{ + build COND; + build ror1; + Rd = Rn + sext(ror1:1); +} + +:sxtab16^COND Rd,Rn,ror1 is $(AMODE) & COND & c2027=0x68 & c0407=7 & Rn & Rd & ror1 +{ + build COND; + build ror1; + b:1 = ror1:1; + lo:2 = Rn:2 + sext(b); + b = ror1(2); + hi:2 = Rn(2) + sext(b); + Rd = (zext(hi) << 16) + zext(lo); +} + +:sxtah^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=7 & Rd & Rn & ror1 +{ + build COND; + build ror1; + Rd = Rn + sext(ror1:2); +} + +:sxtb^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=2 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + Rd = sext(ror1:1); +} + +:sxtb16^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=0 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + local tmp1:1 = ror1:1; + local low:2 = sext(tmp1); + local tmp2:1 = ror1(2); + local high:2 = sext(tmp2); + Rd = (zext(high) << 16) | zext(low); +} + +:sxth^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=3 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + Rd = sext(ror1:2); +} + +@endif # VERSION_6 + +:teq^COND rn,shift1 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + local tmp = rn^shift1; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:teq^COND rn,shift2 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + local tmp = rn^shift2; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:teq^COND rn,shift3 is $(AMODE) & COND & c2024=19 & rn & c1215=0 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + local tmp = rn^shift3; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:teq^COND^"p" rn,shift1 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + local tmp = rn^shift1; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:teq^COND^"p" rn,shift2 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + local tmp = rn^shift2; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:teq^COND^"p" rn,shift3 is $(AMODE) & COND & c2024=19 & rn & c1215=15 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + local tmp = rn^shift3; + logicflags(); + resultflags(tmp); + affectflags(); +} + + +:tst^COND rn,shift1 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift1 +{ + build COND; + build rn; + build shift1; + local tmp = rn & shift1; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:tst^COND rn,shift2 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift2 +{ + build COND; + build rn; + build shift2; + local tmp = rn & shift2; + logicflags(); + resultflags(tmp); + affectflags(); +} + +:tst^COND rn,shift3 is $(AMODE) & COND & c2024=17 & rn & c1215=0 & c2627=0 & shift3 +{ + build COND; + build rn; + build shift3; + local tmp = rn & shift3; + logicflags(); + resultflags(tmp); + affectflags(); +} + +@if defined(VERSION_6) + +:uadd16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=1 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm:2; + local tcarry = carry(tmp1,tmp2); + GE1 = tcarry; + GE2 = tcarry; + local tmpLow = tmp1 + tmp2; + tmp1 = rn(2); + tmp2 = rm(2); + tcarry = carry(tmp1,tmp2); + GE3 = tcarry; + GE4 = tcarry; + local tmpHigh = tmp1 + tmp2; + Rd = zext(tmpHigh) << 16 | zext(tmpLow); +} + +:uadd8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=9 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:1 = tmpRn:1; + tmp2:1 = tmpRm:1; + GE1 = carry(tmp1,tmp2); + b1:1 = tmp1 + tmp2; + tmp1 = rn(1); + tmp2 = rm(1); + GE2 = carry(tmp1,tmp2); + b2:1 = tmp1 + tmp2; + tmp1 = rn(2); + tmp2 = rm(2); + GE3 = carry(tmp1,tmp2); + b3:1 = tmp1 + tmp2; + tmp1 = rn(3); + tmp2 = rm(3); + GE4 = carry(tmp1,tmp2); + b4:1 = tmp1 + tmp2; + Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1); +} + +# uaddsubx +:uasx^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=3 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm(2); + local tmpLow:4 = zext(tmp1) - zext(tmp2); + GE1 = tmpLow s>= 0; + GE2 = tmpLow s>= 0; + tmp1 = tmpRn(2); + tmp2 = tmpRm:2; + tcarry:1 = carry(tmp1,tmp2); + GE3 = tcarry; + GE4 = tcarry; + local tmpHigh = tmp1 + tmp2; + Rd[0,16] = tmpLow[0,16]; + Rd[16,16] = tmpHigh; + } + +@endif # VERSION_6 + +@if defined(VERSION_6T2) + +:ubfx^COND Rd,Rm,lsbImm,widthMinus1 is $(AMODE) & COND & c2127=0x3f & widthMinus1 & Rd & lsbImm & c0406=5 & Rm +{ + build COND; + build lsbImm; + build widthMinus1; + shift:4 = 31 - (lsbImm + widthMinus1); + Rd = Rm << shift; + shift = 31 - widthMinus1; + Rd = Rd >> shift; +} + +@endif # VERSION_6T2 + +@if defined(VERSION_7) + +:udiv^COND RdHi,RnLo,RmHi is $(AMODE) & COND & c2027=0x73 & RdHi & c1215=0xf & RmHi & c0407=0x1 & RnLo +{ + build COND; + result:8 = zext(RnLo) / zext(RmHi); + RdHi = result(0); +} + +@endif # VERSION_7 + +@if defined(VERSION_6) + +:uhadd16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=1 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:4 = tmpRn & 0xffff; + tmp2:4 = tmpRm & 0xffff; + local tmpLow = tmp1 + tmp2; + local tmpHigh = (tmpRn >> 16) + (tmpRm >> 16); + Rd[0,16] = tmpLow[1,16]; + Rd[16,16] = tmpHigh[1,16]; +} + +:uhadd8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=9 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:1 = tmpRn:1; + tmp2:1 = tmpRm:1; + b1:2 = (zext(tmp1) + zext(tmp2)) >> 1; + tmp1 = tmpRn(1); + tmp2 = tmpRm(1); + b2:2 = (zext(tmp1) + zext(tmp2)) >> 1; + tmp1 = tmpRn(2); + tmp2 = tmpRm(2); + b3:2 = (zext(tmp1) + zext(tmp2)) >> 1; + tmp1 = tmpRn(3); + tmp2 = tmpRm(3); + b4:2 = (zext(tmp1) + zext(tmp2)) >> 1; + Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1); +} + +# uhaddsubx +:uhasx^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=3 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm(2); + tmpLow:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff; + tmp1 = tmpRn(2); + tmp2 = tmpRm:2; + tmpHigh:4 = (zext(tmp1) + zext(tmp2)) >> 1; + Rd = (tmpHigh << 16) | tmpLow; +} + +# uhsubaddx +:uhsax^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=5 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm(2); + tmpLow:4 = (zext(tmp1) + zext(tmp2)) >> 1; + tmp1 = tmpRn(2); + tmp2 = tmpRm:2; + tmpHigh:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff; + Rd = (tmpHigh << 16) | tmpLow; +} + +:uhsub16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=7 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm:2; + tmpLow:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff; + tmp1 = rn(2); + tmp2 = rm(2); + tmpHigh:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ffff; + Rd = (tmpHigh << 16) | tmpLow; +} + +:uhsub8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=7 & c0811=15 & c0407=15 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:1 = tmpRn:1; + tmp2:1 = tmpRm:1; + b1:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff; + tmp1 = tmpRn(1); + tmp2 = tmpRm(1); + b2:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff; + tmp1 = tmpRn(2); + tmp2 = tmpRm(2); + b3:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff; + tmp1 = tmpRn(3); + tmp2 = tmpRm(3); + b4:4 = ((zext(tmp1) - zext(tmp2)) >> 1) & 0x0ff; + Rd = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1; +} + +:umaal^COND RdLo,RdHi,Rm,Rs is $(AMODE) & COND & c2027=0x04 & RdHi & RdLo & Rs & c0407=9 & Rm +{ + build COND; + result:8 = (zext(Rm) * zext(Rs)) + zext(RdLo) + zext(RdHi); + RdLo = result:4; + RdHi = result(4); +} + +@endif # VERSION_6 + +:umlal^COND^SBIT_ZN Rd,Rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=5 & SBIT_ZN & Rn & Rd & rs & c0407=9 & rm +{ + build COND; + build rm; + build rs; + tmp:8 = (zext(Rn) << 32) | zext(Rd); + rs64:8 = zext(rs); + rm64:8 = zext(rm); + tmp = rs64 * rm64 + tmp; + resultflags(tmp); + Rd = tmp(0); + Rn = tmp(4); + build SBIT_ZN; +} + +:umull^COND^SBIT_ZN Rd,Rn,rm,rs is $(AMODE) & COND & c2527=0 & c2124=4 & SBIT_ZN & Rn & Rd & rs & c0407=9 & rm +{ + build COND; + build rm; + build rs; + rs64:8 = zext(rs); + rm64:8 = zext(rm); + local tmp = rs64 * rm64; + resultflags(tmp); + Rd = tmp(0); + Rn = tmp(4); + build SBIT_ZN; +} + +@if defined(VERSION_6) + +:uqadd16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=1 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp2Rn:2 = tmpRn:2; + tmp2Rm:2 = tmpRm:2; + sum1:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2); + tmp2Rn = tmpRn(2); + tmp2Rm = tmpRm(2); + sum2:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +:uqadd8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=9 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp1Rn:1 = tmpRn:1; + tmp1Rm:1 = tmpRm:1; + sum1:1 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2); + tmp1Rn = tmpRn(1); + tmp1Rm = tmpRm(1); + sum2:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2); + tmp1Rn = tmpRn(2); + tmp1Rm = tmpRm(2); + sum3:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2); + tmp1Rn = tmpRn(3); + tmp1Rm = tmpRm(3); + sum4:2 = UnsignedSaturate(tmp1Rn + tmp1Rm, 16:2); + Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +# uqaddsubx +:uqasx^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=3 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp2Rn:2 = tmpRn:2; + tmp2Rm:2 = tmpRm(2); + sum1:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2); + tmp2Rn = tmpRn(2); + tmp2Rm = tmpRm:2; + sum2:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +# uqsubaddx +:uqsax^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=5 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp2Rn:2 = tmpRn:2; + tmp2Rm:2 = tmpRm(2); + sum1:2 = UnsignedSaturate(tmp2Rn + tmp2Rm, 16:2); + tmp2Rn = tmpRn(2); + tmp2Rm = tmpRm:2; + sum2:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +:uqsub16^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=7 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp2Rn:2 = tmpRn:2; + tmp2Rm:2 = tmpRm:2; + sum1:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2); + tmp2Rn = tmpRn(2); + tmp2Rm = tmpRm(2); + sum2:2 = UnsignedSaturate(tmp2Rn - tmp2Rm, 16:2); + Rd = (zext(sum2) << 16) | zext(sum1); +} + +:uqsub8^COND Rd, Rn, Rm is $(AMODE) & COND & c2027=0x66 & c0811=15 & c0407=15 & Rn & Rd & Rm +{ + build COND; + local tmpRn = Rn; + local tmpRm = Rm; + tmp1Rn:1 = tmpRn:1; + tmp1Rm:1 = tmpRm:1; + sum1:1 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2); + tmp1Rn = tmpRn(1); + tmp1Rm = tmpRm(1); + sum2:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2); + tmp1Rn = tmpRn(2); + tmp1Rm = tmpRm(2); + sum3:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2); + tmp1Rn = tmpRn(3); + tmp1Rm = tmpRm(3); + sum4:2 = UnsignedSaturate(tmp1Rn - tmp1Rm, 16:2); + Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +:usad8^COND Rd, Rm, Rs is $(AMODE) & COND & c2027=0x78 & c1215=15 & c0407=1 & Rd & Rm & Rs +{ + build COND; + local tmpRs = Rs; + local tmpRm = Rm; + tmp1Rs:1 = tmpRs:1; + tmp1Rm:1 = tmpRm:1; + sum1:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(1); + tmp1Rm = tmpRm(1); + sum2:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(2); + tmp1Rm = tmpRm(2); + sum3:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(3); + tmp1Rm = tmpRm(3); + sum4:1 = Absolute(tmp1Rs - tmp1Rm); + Rd = (zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1); +} + +:usada8^COND Rd, Rm, Rs, Rn is $(AMODE) & COND & c2027=0x78 & c0407=1 & Rd & Rn& Rm & Rs +{ + build COND; + local tmpRs = Rs; + local tmpRm = Rm; + tmp1Rs:1 = tmpRs:1; + tmp1Rm:1 = tmpRm:1; + sum1:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(1); + tmp1Rm = tmpRm(1); + sum2:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(2); + tmp1Rm = tmpRm(2); + sum3:1 = Absolute(tmp1Rs - tmp1Rm); + tmp1Rs = tmpRs(3); + tmp1Rm = tmpRm(3); + sum4:1 = Absolute(tmp1Rs - tmp1Rm); + Rd = Rn + ((zext(sum4) << 24) | (zext(sum3) << 16) | (zext(sum2) << 8) | zext(sum1)); +} + +:usat^COND Rd, uSatImm5, shift4 is $(AMODE) & COND & c2127=0x37 & c0405=0x1 & uSatImm5 & Rd & shift4 +{ + build COND; + build uSatImm5; + build shift4; + tmp:4 = UnsignedSaturate(shift4, uSatImm5); + Q = UnsignedDoesSaturate(shift4, uSatImm5); + Rd = tmp; +} + +:usat16^COND Rd, uSatImm4, Rm is $(AMODE) & COND & c2027=0x6e & c0811=15 & c0407=0x3 & uSatImm4 & Rd & Rm +{ + build COND; + build uSatImm4; + local tmpl = Rm & 0xffff; + tmpl = UnsignedSaturate(tmpl, uSatImm4); + local tmpu = Rm >> 16; + tmpu = UnsignedSaturate(tmpu, uSatImm4); + Q = UnsignedDoesSaturate(tmpl,uSatImm4) | UnsignedDoesSaturate(tmpu,uSatImm4); + Rd = ((tmpu & 0xffff) << 16) | (tmpl & 0xffff); +} + +# usubaddx +:usax^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=5 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm(2); + local tcarry = carry(tmp2,tmp1); + GE1 = tcarry; + GE2 = tcarry; + local tmpLow = tmp1 + tmp2; + tmp1 = tmpRn(2); + tmp2 = tmpRm:2; + tcarry = tmp2 <= tmp1; + GE3 = tcarry; + GE4 = tcarry; + local tmpHigh = tmp1 - tmp2; + Rd = zext(tmpHigh) << 16 | zext(tmpLow); +} + +:usub16^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=7 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:2 = tmpRn:2; + tmp2:2 = tmpRm:2; + local tcarry = tmp2 <= tmp1; + GE1 = tcarry; + GE2 = tcarry; + local tmpLow = tmp1 - tmp2; + tmp1 = tmpRn(2); + tmp2 = tmpRm(2); + tcarry = tmp2 <= tmp1; + GE3 = tcarry; + GE4 = tcarry; + local tmpHigh = tmp1 - tmp2; + Rd = zext(tmpHigh) << 16 | zext(tmpLow); +} + +:usub8^COND Rd,rn,rm is $(AMODE) & COND & c2327=12 & c2022=5 & c0811=15 & c0407=15 & Rd & rn & rm +{ + build COND; + build rn; + build rm; + local tmpRn = rn; + local tmpRm = rm; + tmp1:1 = tmpRn:1; + tmp2:1 = tmpRm:1; + GE1 = tmp2 <= tmp1; + b1:1 = tmp1 - tmp2; + tmp1 = tmpRn(1); + tmp2 = tmpRm(1); + GE2 = tmp2 <= tmp1; + b2:1 = tmp1 - tmp2; + tmp1 = tmpRn(2); + tmp2 = tmpRm(2); + GE3 = tmp2 <= tmp1; + b3:1 = tmp1 - tmp2; + tmp1 = tmpRn(3); + tmp2 = tmpRm(3); + GE4 = tmp2 <= tmp1; + b4:1 = tmp1 - tmp2; + Rd = (zext(b4) << 24) | (zext(b3) << 16) | (zext(b2) << 8) | zext(b1); +} + +:uxtab^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=6 & c0407=7 & Rd & Rn & ror1 +{ + build COND; + build ror1; + Rd = Rn + zext(ror1:1); +} + +:uxtab16^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=4 & c0407=7 & Rd & Rn & ror1 +{ + build COND; + build ror1; + local tmp1 = ror1 & 0xff; + local tmp2 = (ror1 >> 16) & 0xff; + local tmp1n = (Rn + tmp1) & 0xffff; + local tmp2n = (Rn >> 16) + tmp2; + Rd = (tmp2n << 16) | tmp1n; +} + +:uxtah^COND Rd,Rn,ror1 is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=7 & Rd & Rn & ror1 +{ + build COND; + build ror1; + Rd = Rn + zext(ror1:2); +} + +:uxtb^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=6 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + Rd = ror1 & 0x0ff; +} + +:uxtb16^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=4 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + Rd = ror1 & 0x0ff00ff; +} + +:uxth^COND Rd,ror1 is $(AMODE) & COND & c2327=13 & c2022=7 & c0407=7 & Rd & c1619=15 & ror1 +{ + build COND; + build ror1; + Rd = ror1 & 0x0ffff; +} + +@endif # VERSION_6 + +# :v* Advanced SIMD and VFP instructions - see ARMneon.sinc + +@if defined(VERSION_6K) + +:wfe^COND is $(AMODE) & COND & c0027=0x320f002 +{ + build COND; + WaitForEvent(); +} + +:wfi^COND is $(AMODE) & COND & c0027=0x320f003 +{ + build COND; + WaitForInterrupt(); +} + +:yield^COND is $(AMODE) & COND & c0027=0x320f001 +{ + build COND; + HintYield(); +} + +@endif # VERSION_6K + +## Some special pseudo ops for better distinguishing +## indirect calls, and returns + +#:callx rm is $(AMODE) & pref=0xe1a0e00f; cond=14 & c2027=18 & c1619=15 & c1215=15 & c0811=15 & c0407=1 & rm +#{ +# lr = inst_next + 8; +# TB=(rm&0x00000001)!=0; +# tmp=rm&0xfffffffe; +# call [tmp]; +# TB=0; +#} # Optional change to THUMB + +#:call^COND^SBIT_CZNO shift1 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift1 +#{ +# lr = inst_next + 8; +# build COND; +# build shift1; +# pc = shift1; +# resultflags(pc); +# logicflags(); +# build SBIT_CZNO; +# call [pc]; +#} + +#:call^COND^SBIT_CZNO shift2 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift2 +#{ +# lr = inst_next + 8; +# build COND; +# build shift2; +# pc = shift2; +# resultflags(pc); +# logicflags(); +# build SBIT_CZNO; +# call [pc]; +#} + +#:call^COND^SBIT_CZNO shift3 is $(AMODE) & pref=0xe1a0e00f; COND & c2124=13 & SBIT_CZNO & c1619=0 & Rd=15 & c2627=0 & shift3 +#{ +# lr = inst_next + 8; +# build COND; +# build shift3; +# pc = shift3; +# resultflags(pc); +# logicflags(); +# build SBIT_CZNO; +# call [pc]; +#} + + +@if defined(VERSION_6T2) || defined(VERSION_7) +} # End with : ARMcondCk=1 +@endif diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.dwarf b/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.dwarf new file mode 100644 index 00000000..fa2ff762 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.dwarf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.sinc b/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.sinc new file mode 100644 index 00000000..7f834993 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMneon.sinc @@ -0,0 +1,4717 @@ +# Advanced SIMD support / NEON + +# WARNING NOTE: Be very careful taking a subpiece or truncating a register with :# or (#) +# The LEBE hybrid language causes endian issues if you do not assign the register to a temp +# variable and then take a subpiece or truncate. +# + +@define FPSCR_RMODE "fpscr[22,2]" + +@define TMODE_E "TMode=1 & thv_c2831=14" # check for neon instructions in thumb mode +@define TMODE_F "TMode=1 & thv_c2831=15" +@define TMODE_EorF "TMode=1 & thv_c2931=7" + +# The RM field is bits 22 and 23 of FPSCR +@define FPSCR_RMODE "fpscr[21,2]" + +zero: "#0" is c0000 { export 0:8; } + +@if defined(SIMD) + +attach variables [ thv_Rm ] [ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc ]; + +attach variables [ Qn0 Qd0 Qm0 thv_Qn0 thv_Qd0 thv_Qm0 ] [ q0 _ q1 _ q2 _ q3 _ q4 _ q5 _ q6 _ q7 _ ]; +attach variables [ Qn1 Qd1 Qm1 thv_Qn1 thv_Qd1 thv_Qm1 ] [ q8 _ q9 _ q10 _ q11 _ q12 _ q13 _ q14 _ q15 _ ]; + +Qd: Qd0 is TMode=0 & Qd0 & D22=0 { export Qd0; } +Qd: Qd1 is TMode=0 & Qd1 & D22=1 { export Qd1; } +Qd: thv_Qd0 is TMode=1 & thv_Qd0 & thv_D22=0 { export thv_Qd0; } +Qd: thv_Qd1 is TMode=1 & thv_Qd1 & thv_D22=1 { export thv_Qd1; } + +Qn: Qn0 is TMode=0 & Qn0 & N7=0 { export Qn0; } +Qn: Qn1 is TMode=0 & Qn1 & N7=1 { export Qn1; } +Qn: thv_Qn0 is TMode=1 & thv_Qn0 & thv_N7=0 { export thv_Qn0; } +Qn: thv_Qn1 is TMode=1 & thv_Qn1 & thv_N7=1 { export thv_Qn1; } + +Qm: Qm0 is TMode=0 & Qm0 & M5=0 { export Qm0; } +Qm: Qm1 is TMode=0 & Qm1 & M5=1 { export Qm1; } +Qm: thv_Qm0 is TMode=1 & thv_Qm0 & thv_M5=0 { export thv_Qm0; } +Qm: thv_Qm1 is TMode=1 & thv_Qm1 & thv_M5=1 { export thv_Qm1; } + +@endif # SIMD + +@if defined(SIMD) || defined(VFPv3) || defined(VFPv2) + +attach variables [ Dm_3 thv_Dm_3 ] [ d0 d1 d2 d3 d4 d5 d6 d7 ]; + +attach variables [ Dn0 Dd0 Dm0 Dm_4 thv_Dn0 thv_Dd0 thv_Dm0 thv_Dm_4 ] [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ]; +attach variables [ thv_Dd_1 ] [ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 ]; +attach variables [ thv_Dd_2 ] [ d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ ]; +attach variables [ thv_Dd_3 ] [ d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ ]; +attach variables [ thv_Dd_4 ] [ d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ ]; +attach variables [ thv_Dd_5 ] [ d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ ]; +attach variables [ thv_Dd_6 ] [ d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ ]; +attach variables [ thv_Dd_7 ] [ d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ ]; +attach variables [ thv_Dd_8 ] [ d7 d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_9 ] [ d8 d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_10 ] [ d9 d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_11 ] [ d10 d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_12 ] [ d11 d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_13 ] [ d12 d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_14 ] [ d13 d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_15 ] [ d14 d15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ ]; +attach variables [ thv_Dd_16 ] [ d15 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ]; + +Dd: Dd0 is TMode=0 & Dd0 & D22=0 { export Dd0; } +Dn: Dn0 is TMode=0 & Dn0 & N7=0 { export Dn0; } +Dm: Dm0 is TMode=0 & Dm0 & M5=0 { export Dm0; } +Dd: thv_Dd0 is TMode=1 & thv_Dd0 & thv_D22=0 { export thv_Dd0; } +Dn: thv_Dn0 is TMode=1 & thv_Dn0 & thv_N7=0 { export thv_Dn0; } +Dm: thv_Dm0 is TMode=1 & thv_Dm0 & thv_M5=0 { export thv_Dm0; } + +Dd2: Dd is Dd { export Dd; } + +@endif # SIMD || VFPv3 || VFPv2 + +@if defined(SIMD) || defined(VFPv3) + +attach variables [ Dn1 Dd1 Dm1 thv_Dn1 thv_Dd1 thv_Dm1 ] [ d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 ]; + +Dd: Dd1 is TMode=0 & Dd1 & D22=1 { export Dd1; } +Dn: Dn1 is TMode=0 & Dn1 & N7=1 { export Dn1; } +Dm: Dm1 is TMode=0 & Dm1 & M5=1 { export Dm1; } +Dd: thv_Dd1 is TMode=1 & thv_Dd1 & thv_D22=1 { export thv_Dd1; } +Dn: thv_Dn1 is TMode=1 & thv_Dn1 & thv_N7=1 { export thv_Dn1; } +Dm: thv_Dm1 is TMode=1 & thv_Dm1 & thv_M5=1 { export thv_Dm1; } + +@endif # SIMD || VFPv3 + +@if defined(VFPv2) || defined(VFPv3) + +attach variables [ Sn0 Sd0 Sm0 thv_Sn0 thv_Sd0 thv_Sm0 ] [ s0 s2 s4 s6 s8 s10 s12 s14 s16 s18 s20 s22 s24 s26 s28 s30 ]; +attach variables [ Sn1 Sd1 Sm1 thv_Sn1 thv_Sd1 thv_Sm1 ] [ s1 s3 s5 s7 s9 s11 s13 s15 s17 s19 s21 s23 s25 s27 s29 s31 ]; + +attach variables [ Sm0next thv_Sm0next ] [ s1 s3 s5 s7 s9 s11 s13 s15 s17 s19 s21 s23 s25 s27 s29 s31 ]; +attach variables [ Sm1next thv_Sm1next ] [ s2 s4 s6 s8 s10 s12 s14 s16 s18 s20 s22 s24 s26 s28 s30 _ ]; + +# We need to create separate constructors for each register rather than attaching +# directly to a context variable +@if defined (VFPv2) || defined(SIMD) +Sreg: s0 is s0 & regNum=0 { export s0; } +Sreg: s1 is s1 & regNum=1 { export s1; } +Sreg: s2 is s2 & regNum=2 { export s2; } +Sreg: s3 is s3 & regNum=3 { export s3; } +Sreg: s4 is s4 & regNum=4 { export s4; } +Sreg: s5 is s5 & regNum=5 { export s5; } +Sreg: s6 is s6 & regNum=6 { export s6; } +Sreg: s7 is s7 & regNum=7 { export s7; } +Sreg: s8 is s8 & regNum=8 { export s8; } +Sreg: s9 is s9 & regNum=9 { export s9; } +Sreg: s10 is s10 & regNum=10 { export s10; } +Sreg: s11 is s11 & regNum=11 { export s11; } +Sreg: s12 is s12 & regNum=12 { export s12; } +Sreg: s13 is s13 & regNum=13 { export s13; } +Sreg: s14 is s14 & regNum=14 { export s14; } +Sreg: s15 is s15 & regNum=15 { export s15; } +Sreg: s16 is s16 & regNum=16 { export s16; } +Sreg: s17 is s17 & regNum=17 { export s17; } +Sreg: s18 is s18 & regNum=18 { export s18; } +Sreg: s19 is s19 & regNum=19 { export s19; } +Sreg: s20 is s20 & regNum=20 { export s20; } +Sreg: s21 is s21 & regNum=21 { export s21; } +Sreg: s22 is s22 & regNum=22 { export s22; } +Sreg: s23 is s23 & regNum=23 { export s23; } +Sreg: s24 is s24 & regNum=24 { export s24; } +Sreg: s25 is s25 & regNum=25 { export s25; } +Sreg: s26 is s26 & regNum=26 { export s26; } +Sreg: s27 is s27 & regNum=27 { export s27; } +Sreg: s28 is s28 & regNum=28 { export s28; } +Sreg: s29 is s29 & regNum=29 { export s29; } +Sreg: s30 is s30 & regNum=30 { export s30; } +Sreg: s31 is s31 & regNum=31 { export s31; } + +Sreg2: s0 is s0 & reg2Num=0 { export s0; } +Sreg2: s1 is s1 & reg2Num=1 { export s1; } +Sreg2: s2 is s2 & reg2Num=2 { export s2; } +Sreg2: s3 is s3 & reg2Num=3 { export s3; } +Sreg2: s4 is s4 & reg2Num=4 { export s4; } +Sreg2: s5 is s5 & reg2Num=5 { export s5; } +Sreg2: s6 is s6 & reg2Num=6 { export s6; } +Sreg2: s7 is s7 & reg2Num=7 { export s7; } +Sreg2: s8 is s8 & reg2Num=8 { export s8; } +Sreg2: s9 is s9 & reg2Num=9 { export s9; } +Sreg2: s10 is s10 & reg2Num=10 { export s10; } +Sreg2: s11 is s11 & reg2Num=11 { export s11; } +Sreg2: s12 is s12 & reg2Num=12 { export s12; } +Sreg2: s13 is s13 & reg2Num=13 { export s13; } +Sreg2: s14 is s14 & reg2Num=14 { export s14; } +Sreg2: s15 is s15 & reg2Num=15 { export s15; } +Sreg2: s16 is s16 & reg2Num=16 { export s16; } +Sreg2: s17 is s17 & reg2Num=17 { export s17; } +Sreg2: s18 is s18 & reg2Num=18 { export s18; } +Sreg2: s19 is s19 & reg2Num=19 { export s19; } +Sreg2: s20 is s20 & reg2Num=20 { export s20; } +Sreg2: s21 is s21 & reg2Num=21 { export s21; } +Sreg2: s22 is s22 & reg2Num=22 { export s22; } +Sreg2: s23 is s23 & reg2Num=23 { export s23; } +Sreg2: s24 is s24 & reg2Num=24 { export s24; } +Sreg2: s25 is s25 & reg2Num=25 { export s25; } +Sreg2: s26 is s26 & reg2Num=26 { export s26; } +Sreg2: s27 is s27 & reg2Num=27 { export s27; } +Sreg2: s28 is s28 & reg2Num=28 { export s28; } +Sreg2: s29 is s29 & reg2Num=29 { export s29; } +Sreg2: s30 is s30 & reg2Num=30 { export s30; } +Sreg2: s31 is s31 & reg2Num=31 { export s31; } + +Dreg: d0 is d0 & regNum=0 { export d0; } +Dreg: d1 is d1 & regNum=1 { export d1; } +Dreg: d2 is d2 & regNum=2 { export d2; } +Dreg: d3 is d3 & regNum=3 { export d3; } +Dreg: d4 is d4 & regNum=4 { export d4; } +Dreg: d5 is d5 & regNum=5 { export d5; } +Dreg: d6 is d6 & regNum=6 { export d6; } +Dreg: d7 is d7 & regNum=7 { export d7; } +Dreg: d8 is d8 & regNum=8 { export d8; } +Dreg: d9 is d9 & regNum=9 { export d9; } +Dreg: d10 is d10 & regNum=10 { export d10; } +Dreg: d11 is d11 & regNum=11 { export d11; } +Dreg: d12 is d12 & regNum=12 { export d12; } +Dreg: d13 is d13 & regNum=13 { export d13; } +Dreg: d14 is d14 & regNum=14 { export d14; } +Dreg: d15 is d15 & regNum=15 { export d15; } +Dreg2: d0 is d0 & reg2Num=0 { export d0; } +Dreg2: d1 is d1 & reg2Num=1 { export d1; } +Dreg2: d2 is d2 & reg2Num=2 { export d2; } +Dreg2: d3 is d3 & reg2Num=3 { export d3; } +Dreg2: d4 is d4 & reg2Num=4 { export d4; } +Dreg2: d5 is d5 & reg2Num=5 { export d5; } +Dreg2: d6 is d6 & reg2Num=6 { export d6; } +Dreg2: d7 is d7 & reg2Num=7 { export d7; } +Dreg2: d8 is d8 & reg2Num=8 { export d8; } +Dreg2: d9 is d9 & reg2Num=9 { export d9; } +Dreg2: d10 is d10 & reg2Num=10 { export d10; } +Dreg2: d11 is d11 & reg2Num=11 { export d11; } +Dreg2: d12 is d12 & reg2Num=12 { export d12; } +Dreg2: d13 is d13 & reg2Num=13 { export d13; } +Dreg2: d14 is d14 & reg2Num=14 { export d14; } +Dreg2: d15 is d15 & reg2Num=15 { export d15; } +@if defined(SIMD) || defined(VFPv3) +Dreg: d16 is d16 & regNum=16 { export d16; } +Dreg: d17 is d17 & regNum=17 { export d17; } +Dreg: d18 is d18 & regNum=18 { export d18; } +Dreg: d19 is d19 & regNum=19 { export d19; } +Dreg: d20 is d20 & regNum=20 { export d20; } +Dreg: d21 is d21 & regNum=21 { export d21; } +Dreg: d22 is d22 & regNum=22 { export d22; } +Dreg: d23 is d23 & regNum=23 { export d23; } +Dreg: d24 is d24 & regNum=24 { export d24; } +Dreg: d25 is d25 & regNum=25 { export d25; } +Dreg: d26 is d26 & regNum=26 { export d26; } +Dreg: d27 is d27 & regNum=27 { export d27; } +Dreg: d28 is d28 & regNum=28 { export d28; } +Dreg: d29 is d29 & regNum=29 { export d29; } +Dreg: d30 is d30 & regNum=30 { export d30; } +Dreg: d31 is d31 & regNum=31 { export d31; } +Dreg2: d16 is d16 & reg2Num=16 { export d16; } +Dreg2: d17 is d17 & reg2Num=17 { export d17; } +Dreg2: d18 is d18 & reg2Num=18 { export d18; } +Dreg2: d19 is d19 & reg2Num=19 { export d19; } +Dreg2: d20 is d20 & reg2Num=20 { export d20; } +Dreg2: d21 is d21 & reg2Num=21 { export d21; } +Dreg2: d22 is d22 & reg2Num=22 { export d22; } +Dreg2: d23 is d23 & reg2Num=23 { export d23; } +Dreg2: d24 is d24 & reg2Num=24 { export d24; } +Dreg2: d25 is d25 & reg2Num=25 { export d25; } +Dreg2: d26 is d26 & reg2Num=26 { export d26; } +Dreg2: d27 is d27 & reg2Num=27 { export d27; } +Dreg2: d28 is d28 & reg2Num=28 { export d28; } +Dreg2: d29 is d29 & reg2Num=29 { export d29; } +Dreg2: d30 is d30 & reg2Num=30 { export d30; } +Dreg2: d31 is d31 & reg2Num=31 { export d31; } +@else +# this is just a placeholder so the parse patterns will match correctly. +# regNum is 31 when the base pattern matches, and incremented when +# this constructor actually matches +Dreg: d0 is d0 & regNum=31 { export d0; } +Dreg2: d0 is d0 & reg2Num=31 { export d0; } +@endif +@endif + +VRm: Rm is TMode=0 & Rm { export Rm; } +VRm: thv_Rm is TMode=1 & thv_Rm { export thv_Rm; } + +VRn: Rn is TMode=0 & Rn { export Rn; } +VRn: thv_Rn is TMode=1 & thv_Rn { export thv_Rn; } + +VRd: Rd is TMode=0 & Rd { export Rd; } +VRd: thv_Rd is TMode=1 & thv_Rd { export thv_Rd; } + +Sd: Sd0 is TMode=0 & Sd0 & D22=0 { export Sd0; } +Sd: Sd1 is TMode=0 & Sd1 & D22=1 { export Sd1; } +Sd: thv_Sd0 is TMode=1 & thv_Sd0 & thv_D22=0 { export thv_Sd0; } +Sd: thv_Sd1 is TMode=1 & thv_Sd1 & thv_D22=1 { export thv_Sd1; } + +Sn: Sn0 is TMode=0 & Sn0 & N7=0 { export Sn0; } +Sn: Sn1 is TMode=0 & Sn1 & N7=1 { export Sn1; } +Sn: thv_Sn0 is TMode=1 & thv_Sn0 & thv_N7=0 { export thv_Sn0; } +Sn: thv_Sn1 is TMode=1 & thv_Sn1 & thv_N7=1 { export thv_Sn1; } + +Sm: Sm0 is TMode=0 & Sm0 & M5=0 { export Sm0; } +Sm: Sm1 is TMode=0 & Sm1 & M5=1 { export Sm1; } +Sm: thv_Sm0 is TMode=1 & thv_Sm0 & thv_M5=0 { export thv_Sm0; } +Sm: thv_Sm1 is TMode=1 & thv_Sm1 & thv_M5=1 { export thv_Sm1; } + +SmNext: Sm0next is TMode=0 & Sm0next & M5=0 { export Sm0next; } +SmNext: Sm1next is TMode=0 & Sm1next & M5=1 { export Sm1next; } +SmNext: thv_Sm0next is TMode=1 & thv_Sm0next & thv_M5=0 { export thv_Sm0next; } +SmNext: thv_Sm1next is TMode=1 & thv_Sm1next & thv_M5=1 { export thv_Sm1next; } + +Sd2: Sd is Sd { export Sd; } + +@endif # VFPv2 || VFPv3 + +udt: "s" is TMode=0 & c2424=0 { export 0:1; } +udt: "u" is TMode=0 & c2424=1 { export 1:1; } +udt: "s" is TMode=1 & thv_c2828=0 { export 0:1; } +udt: "u" is TMode=1 & thv_c2828=1 { export 1:1; } + +udt7: "s" is TMode=0 & c0707=0 { export 0:1; } +udt7: "u" is TMode=0 & c0707=1 { export 1:1; } +udt7: "s" is TMode=1 & thv_c0707=0 { export 0:1; } +udt7: "u" is TMode=1 & thv_c0707=1 { export 1:1; } + +fdt: "u" is TMode=0 & c0808=0 { export 0:1; } +fdt: "f" is TMode=0 & c0808=1 { export 1:1; } +fdt: "u" is TMode=1 & thv_c0808=0 { export 0:1; } +fdt: "f" is TMode=1 & thv_c0808=1 { export 1:1; } + +esize2021: "8" is TMode=0 & c2021=0 { export 1:4; } +esize2021: "16" is TMode=0 & c2021=1 { export 2:4; } +esize2021: "32" is TMode=0 & c2021=2 { export 4:4; } +esize2021: "64" is TMode=0 & c2021=3 { export 8:4; } +esize2021: "8" is TMode=1 & thv_c2021=0 { export 1:4; } +esize2021: "16" is TMode=1 & thv_c2021=1 { export 2:4; } +esize2021: "32" is TMode=1 & thv_c2021=2 { export 4:4; } +esize2021: "64" is TMode=1 & thv_c2021=3 { export 8:4; } + +esize2021x2: "16" is TMode=0 & c2021=0 { export 2:4; } +esize2021x2: "32" is TMode=0 & c2021=1 { export 4:4; } +esize2021x2: "64" is TMode=0 & c2021=2 { export 8:4; } +esize2021x2: "16" is TMode=1 & thv_c2021=0 { export 2:4; } +esize2021x2: "32" is TMode=1 & thv_c2021=1 { export 4:4; } +esize2021x2: "64" is TMode=1 & thv_c2021=2 { export 8:4; } + +esize1819: "8" is TMode=0 & c1819=0 { export 1:4; } +esize1819: "16" is TMode=0 & c1819=1 { export 2:4; } +esize1819: "32" is TMode=0 & c1819=2 { export 4:4; } +esize1819: "64" is TMode=0 & c1819=3 { export 8:4; } +esize1819: "8" is TMode=1 & thv_c1819=0 { export 1:4; } +esize1819: "16" is TMode=1 & thv_c1819=1 { export 2:4; } +esize1819: "32" is TMode=1 & thv_c1819=2 { export 4:4; } +esize1819: "64" is TMode=1 & thv_c1819=3 { export 8:4; } + +esize1819x2: "16" is TMode=0 & c1819=0 { export 2:4; } +esize1819x2: "32" is TMode=0 & c1819=1 { export 4:4; } +esize1819x2: "64" is TMode=0 & c1819=2 { export 8:4; } +esize1819x2: "16" is TMode=1 & thv_c1819=0 { export 2:4; } +esize1819x2: "32" is TMode=1 & thv_c1819=1 { export 4:4; } +esize1819x2: "64" is TMode=1 & thv_c1819=2 { export 8:4; } + +esize1819x3: "8" is TMode=0 & c1819=0 { export 1:4; } +esize1819x3: "16" is TMode=0 & c1819=1 { export 2:4; } +esize1819x3: "32" is TMode=0 & c1819=2 { export 4:4; } +esize1819x3: "8" is TMode=1 & thv_c1819=0 { export 1:4; } +esize1819x3: "16" is TMode=1 & thv_c1819=1 { export 2:4; } +esize1819x3: "32" is TMode=1 & thv_c1819=2 { export 4:4; } + +esize1011: "8" is TMode=0 & c1011=0 { export 1:4; } +esize1011: "16" is TMode=0 & c1011=1 { export 2:4; } +esize1011: "32" is TMode=0 & c1011=2 { export 4:4; } +esize1011: "64" is TMode=0 & c1011=3 { export 8:4; } +esize1011: "8" is TMode=1 & thv_c1011=0 { export 1:4; } +esize1011: "16" is TMode=1 & thv_c1011=1 { export 2:4; } +esize1011: "32" is TMode=1 & thv_c1011=2 { export 4:4; } +esize1011: "64" is TMode=1 & thv_c1011=3 { export 8:4; } + +esize0607: "8" is TMode=0 & c0607=0 { export 1:4; } +esize0607: "16" is TMode=0 & c0607=1 { export 2:4; } +esize0607: "32" is TMode=0 & c0607=2 { export 4:4; } +esize0607: "64" is TMode=0 & c0607=3 { export 8:4; } # see VLD4 (single 4-element structure to all lanes) +esize0607: "8" is TMode=1 & thv_c0607=0 { export 1:4; } +esize0607: "16" is TMode=1 & thv_c0607=1 { export 2:4; } +esize0607: "32" is TMode=1 & thv_c0607=2 { export 4:4; } +esize0607: "64" is TMode=1 & thv_c0607=3 { export 8:4; } # see VLD4 (single 4-element structure to all lanes) + +fesize2021: "16" is TMode=0 & c2020=1 { export 4:4; } +fesize2021: "32" is TMode=0 & c2020=0 { export 2:4; } +fesize2021: "16" is TMode=1 & thv_c2020=1 { export 4:4; } +fesize2021: "32" is TMode=1 & thv_c2020=0 { export 2:4; } + +define pcodeop VFPExpandImmediate; + + + +# float +vfpExpImm_4: imm is TMode=0 & c1919 & c1818 & c1617 & c0003 [ imm = (c1919 << 31) | ((c1818 $xor 1) << 30) | ((c1818 * 0x1f) << 25) | (c1617 << 23) | (c0003 << 19); ] { + export *[const]:4 imm; +} + +# float +vfpExpImm_4: imm is TMode=1 & thv_c1919 & thv_c1818 & thv_c1617 & thv_c0003 [ imm = (thv_c1919 << 31) | ((thv_c1818 $xor 1) << 30) | ((thv_c1818 * 0x1f) << 25) | (thv_c1617 << 23) | (thv_c0003 << 19); ] { + export *[const]:4 imm; +} + + +# double +vfpExpImm_8: imm is TMode=0 & c1919 & c1818 & c1617 & c0003 [ imm = (c1919 << 63) | ((c1818 $xor 1) << 62) | ((c1818 * 0xff) << 54) | (c1617 << 52) | (c0003 << 48); ] { + export *[const]:8 imm; +} + +# double +vfpExpImm_8: imm is TMode=1 & thv_c1919 & thv_c1818 & thv_c1617 & thv_c0003 [ imm = (thv_c1919 << 63) | ((thv_c1818 $xor 1) << 62) | ((thv_c1818 * 0xff) << 54) | (thv_c1617 << 52) | (thv_c0003 << 48); ] { + export *[const]:8 imm; +} + +define pcodeop SIMDExpandImmediate; + +simdExpImm_8: "#0" is TMode=0 & c2424=0 & c1618=0 & c0003=0 { + export 0:8; +} +simdExpImm_8: "simdExpand("^c0505^","^cmode^","^val^")" is TMode=0 & c2424 & c1618 & c0505 & c0003 & cmode [ val = (c2424 << 7) | (c1618 << 4) | c0003; ] { + imm64:8 = SIMDExpandImmediate(c0505:1, cmode:1, val:1); + export imm64; +} +simdExpImm_8: "#0" is TMode=1 & thv_c2828=0 & thv_c1618=0 & thv_c0003=0 { + export 0:8; +} +simdExpImm_8: "simdExpand("^thv_c0505^","^thv_cmode^","^val^")" is TMode=1 & thv_c2828 & thv_c1618 & thv_c0505 & thv_c0003 & thv_cmode [ val = (thv_c2828 << 7) | (thv_c1618 << 4) | thv_c0003; ] { + imm64:8 = SIMDExpandImmediate(thv_c0505:1, thv_cmode:1, val:1); + export imm64; +} + +simdExpImm_16: "#0" is TMode=0 & c2424=0 & c1618=0 & c0003=0 { + tmp:8 = 0; + tmp1:16 = zext(tmp); + export tmp1; +} +simdExpImm_16: "simdExpand("^c0505^","^cmode^","^val^")" is TMode=0 & c2424 & c1618 & c0505 & c0003 & cmode [ val = (c2424 << 7) | (c1618 << 4) | c0003; ] { + imm128:16 = SIMDExpandImmediate(c0505:1, cmode:1, val:1); + export imm128; +} +simdExpImm_16: "#0" is TMode=1 & thv_c2828=0 & thv_c1618=0 & thv_c0003=0 { + tmp:8 = 0; + tmp1:16 = zext(tmp); + export tmp1; +} +simdExpImm_16: "simdExpand("^thv_c0505^","^thv_cmode^","^val^")" is TMode=1 & thv_c2828 & thv_c1618 & thv_c0505 & thv_c0003 & thv_cmode [ val = (thv_c2828 << 7) | (thv_c1618 << 4) | thv_c0003; ] { + imm128:16 = SIMDExpandImmediate(thv_c0505:1, thv_cmode:1, val:1); + export imm128; +} + +simdExpImmDT: "i32" is TMode=0 & c0911=0 { } +simdExpImmDT: "i32" is TMode=0 & c0911=1 { } +simdExpImmDT: "i32" is TMode=0 & c0911=2 { } +simdExpImmDT: "i32" is TMode=0 & c0911=3 { } +simdExpImmDT: "i16" is TMode=0 & c0911=4 { } +simdExpImmDT: "i16" is TMode=0 & c0911=5 { } +simdExpImmDT: "i32" is TMode=0 & c0811=12 { } +simdExpImmDT: "i32" is TMode=0 & c0811=13 { } +simdExpImmDT: "i8" is TMode=0 & c0811=14 & c0505=0 { } +simdExpImmDT: "i64" is TMode=0 & c0811=14 & c0505=1 { } +simdExpImmDT: "f32" is TMode=0 & c0811=15 & c0505=0 { } + +simdExpImmDT: "i32" is TMode=1 & thv_c0911=0 { } +simdExpImmDT: "i32" is TMode=1 & thv_c0911=1 { } +simdExpImmDT: "i32" is TMode=1 & thv_c0911=2 { } +simdExpImmDT: "i32" is TMode=1 & thv_c0911=3 { } +simdExpImmDT: "i16" is TMode=1 & thv_c0911=4 { } +simdExpImmDT: "i16" is TMode=1 & thv_c0911=5 { } +simdExpImmDT: "i32" is TMode=1 & thv_c0811=12 { } +simdExpImmDT: "i32" is TMode=1 & thv_c0811=13 { } +simdExpImmDT: "i8" is TMode=1 & thv_c0811=14 & thv_c0505=0 { } +simdExpImmDT: "i64" is TMode=1 & thv_c0811=14 & thv_c0505=1 { } +simdExpImmDT: "f32" is TMode=1 & thv_c0811=15 & thv_c0505=0 { } + +macro replicate1to8(bytes, dest) { + local val:8 = zext(bytes); + val = val | (val << 8); + val = val | (val << 16); + dest = val | (val << 32); +} + +macro replicate2to8(bytes, dest) { + local val:8 = zext(bytes); + val = val | (val << 16); + dest = val | (val << 32); +} + +macro replicate4to8(bytes, dest) { + local val:8 = zext(bytes); + dest = val | (val << 32); +} + +define pcodeop VectorAbsoluteDifferenceAndAccumulate; +define pcodeop VectorAbsoluteDifference; +define pcodeop FloatVectorAbsoluteDifference; +define pcodeop VectorAbsolute; +define pcodeop FloatVectorAbsolute; + +@if defined(SIMD) + +# TODO: watch out for c2021=3 + +:vaba.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=1 ) ) & Dm & Dn & Dd & udt & esize2021 +{ + Dd = VectorAbsoluteDifferenceAndAccumulate(Dn,Dm,esize2021,udt); +} + +:vaba.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=7 & thv_c0606=1 & thv_c0404=1 ) ) & Qd & Qn & Qm & udt & esize2021 +{ + Qd = VectorAbsoluteDifferenceAndAccumulate(Qn,Qm,esize2021,udt); +} + +:vabal.^udt^esize2021 Qd,Dn,Dm is (($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=5 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=5 & thv_c0606=0 & thv_c0404=0 ) ) & Qd & Dm & Dn & udt & esize2021 +{ + Qd = VectorAbsoluteDifferenceAndAccumulate(Dn,Dm,esize2021,udt); +} + +:vabd.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dn & Dd & udt & esize2021 +{ + Dd = VectorAbsoluteDifference(Dn,Dm,esize2021,udt); +} + +:vabd.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=7 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=7 & thv_Q6=1 & thv_c0404=0 ) ) & Qd & Qn & Qm & udt & esize2021 +{ + Qd = VectorAbsoluteDifference(Qn,Qm,esize2021,udt); +} + +:vabdl.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=7 & Q6=0 & c0404=0 ) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021 +{ + Qd = VectorAbsoluteDifference(Dn,Dm,esize2021,udt); +} + +:vabd.f32 Dd,Dn,Dm is ( ( $(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=13 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=13 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & Dn +{ + Dd = FloatVectorAbsoluteDifference(Dn,Dm,2:1,32:1); +} + +:vabd.f32 Qd,Qn,Qm is ( ( $(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=13 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=13 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & Qn +{ + Qd = FloatVectorAbsoluteDifference(Qn,Qm,2:1,32:1); +} + +:vabs.s^esize1819 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=6 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=6 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819 +{ + Dd = VectorAbsolute(Dm,esize1819); +} + +:vabs.s^esize1819 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=6 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=6 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819 +{ + Qd = VectorAbsolute(Qm,esize1819); +} + + +:vabs.f32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=0xe & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=0xe & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dd +{ + Dd = FloatVectorAbsolute(Dm,2:1,32:1); +} + +:vabs.f32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=0xe & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=0xe & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm +{ + Qd = FloatVectorAbsolute(Qm,2:1,32:1); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +:vabs^COND^".f32" Sd,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x30 & c0611=0x2b & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2b & thv_c0404=0 ) ) & Sm & Sd +{ + build COND; + build Sd; + build Sm; + Sd = abs(Sm); +} + +:vabs^COND^".f64" Dd,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x30 & c0611=0x2f & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2f & thv_c0404=0 ) ) & Dd & Dm +{ + build COND; + build Dd; + build Dm; + Dd = abs(Dm); +} + +@endif # VFPv2 || VFPv3 + +define pcodeop FloatCompareGE; +define pcodeop FloatCompareGT; +define pcodeop VectorAdd; +define pcodeop VectorSub; +define pcodeop FloatVectorAdd; +define pcodeop VectorPairwiseAdd; +define pcodeop VectorPairwiseMin; +define pcodeop VectorPairwiseMax; +define pcodeop FloatVectorPairwiseAdd; +define pcodeop FloatVectorPairwiseMin; +define pcodeop FloatVectorPairwiseMax; +define pcodeop VectorPairwiseAddLong; +define pcodeop VectorPairwiseAddAccumulateLong; + +@if defined(SIMD) + +:vacge.f32 Dd,Dn,Dm is $(AMODE) & cond=15 & c2327=6 & c2021=0 & Dn & Dd & c0811=14 & Q6=0 & c0404=1 & Dm +{ + Dd = FloatCompareGE(Dn,Dm,2:1,32:1); +} + +:vacge.f32 Qd,Qn,Qm is $(AMODE) & cond=15 & c2327=6 & c2021=0 & Qn & Qd & c0811=14 & Q6=1 & c0404=1 & Qm +{ + Qd = FloatCompareGE(Qn,Qm,2:1,32:1); +} + +:vacgt.f32 Dd,Dn,Dm is $(AMODE) & cond=15 & c2327=6 & c2021=2 & Dn & Dd & c0811=14 & Q6=0 & c0404=1 & Dm +{ + Dd = FloatCompareGT(Dn,Dm,2:1,32:1); +} + +:vacgt.f32 Qd,Qn,Qm is $(AMODE) & cond=15 & c2327=6 & c2021=2 & Qn & Qd & c0811=14 & Q6=1 & c0404=1 & Qm +{ + Qd = FloatCompareGT(Qn,Qm,2:1,32:1); +} + +:vadd.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=8 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dn & Dd & Dm +{ + Dd = VectorAdd(Dn,Dm,esize2021); +} + +:vadd.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=8 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=8 & thv_Q6=1 & thv_c0404=0) ) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorAdd(Qn,Qm,esize2021); +} + +:vadd.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=13 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & Dm& Dn & Dd +{ + Dd = FloatVectorAdd(Dn,Dm,2:1,32:1); +} + +:vadd.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=13 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=13 & thv_Q6=1 & thv_c0404=0) ) & Qn & Qd & Qm +{ + Qd = FloatVectorAdd(Qn,Qm,2:1,32:1); +} + + +:vpadd.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=11 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=11 & thv_Q6=0 & thv_c0404=1)) & esize2021 & Dn & Dd & Dm +{ + Dd = VectorPairwiseAdd(Dn,Dm,esize2021); +} + +:vpadd.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021<3 & c0811=11 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=11 & thv_Q6=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorPairwiseAdd(Qn,Qm,esize2021); +} + +:vpadd.f^fesize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2121=0 & c0811=13 & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & fesize2021 & Dm& Dn & Dd +{ + Dd = FloatVectorPairwiseAdd(Dn,Dm,fesize2021:1); +} + + +:vpmax.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=10 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=10 & thv_Q6=0 & thv_c0404=0)) & udt & esize2021 & Dn & Dd & Dm +{ + Dd = VectorPairwiseMax(Dn,Dm,esize2021,udt); +} + + +:vpmax.f^fesize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2121=0 & c0811=15 & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0) ) & fesize2021 & Dm & Dn & Dd +{ + Dd = FloatVectorPairwiseMax(Dn,Dm,fesize2021:1); +} + +:vpmin.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=10 & Q6=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=10 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm +{ + Dd = VectorPairwiseMin(Dn,Dm,esize2021,udt); +} + +:vpmin.f^fesize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2121=1 & c0811=15 & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=1 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0) ) & fesize2021 & Dm & Dn & Dd +{ + Dd = FloatVectorPairwiseMin(Dn,Dm,fesize2021:1); +} + +:vpadal.^udt7^esize1819 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0811=6 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=6 & thv_Q6=0 & thv_c0404=0)) & udt7 & esize1819 & Dd & Dm +{ + Dd = VectorPairwiseAddAccumulateLong(Dm,esize1819); +} + +:vpadal.^udt7^esize1819 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0811=6 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=6 & thv_Q6=1 & thv_c0404=0)) & udt7 & esize1819 & Qd & Qm +{ + Qd = VectorPairwiseAddAccumulateLong(Qm,esize1819); +} + +:vpaddl.^udt7^esize1819 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0811=2 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=2 & thv_Q6=0 & thv_c0404=0)) & udt7 & esize1819 & Dd & Dm +{ + Dd = VectorPairwiseAddLong(Dm,esize1819); +} + +:vpaddl.^udt7^esize1819 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0811=2 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0811=2 & thv_Q6=1 & thv_c0404=0)) & udt7 & esize1819 & Qd & Qm +{ + Qd = VectorPairwiseAddLong(Qm,esize1819); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +:vadd^COND^".f32" Sd,Sn,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=10 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & Sm & Sd & Sn +{ + build COND; + build Sd; + build Sm; + build Sn; + Sd = Sn f+ Sm; +} + +:vadd^COND^".f64" Dd,Dn,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=11 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) ) & Dm & Dd & Dn +{ + build COND; + build Dd; + build Dm; + build Dn; + Dd = Dn f+ Dm; +} + +@endif # VFPv2 || VFPv3 + +define pcodeop VectorAddReturnHigh; +define pcodeop VectorBitwiseInsertIfFalse; +define pcodeop VectorBitwiseInsertIfTrue; +define pcodeop VectorBitwiseSelect; +define pcodeop VectorCompareEqual; +define pcodeop FloatVectorCompareEqual; +define pcodeop VectorCompareGreaterThanOrEqual; +define pcodeop FloatVectorCompareGreaterThanOrEqual; +define pcodeop VectorCompareGreaterThan; +define pcodeop FloatVectorCompareGreaterThan; +define pcodeop VectorCountLeadingSignBits; +define pcodeop VectorCountLeadingZeros; + +@if defined(SIMD) + +:vaddhn.i^esize2021x2 Dd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=5 & c2021<3 & c0811=4 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=4 & thv_c0606=0 & thv_c0404=0) ) & esize2021x2 & Qn & Dd & Qm +{ + Dd = VectorAddReturnHigh(Qn,Qm,esize2021x2); +} + +:vaddl.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=0 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0 & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Dn & Qd & Dm +{ + Qd = VectorAdd(Dn,Dm,esize2021,udt); +} + +:vaddw.^udt^esize2021 Qd,Qn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=1 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=1 & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Qn & Qd & Dm +{ + Qd = VectorAdd(Qn,Dm,esize2021,udt); +} + + +:vand Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=1 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm +{ + Dd = Dn & Dm; +} + +:vand Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=1 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qn & Qd & Qm +{ + Qd = Qn & Qm; +} + +:vbic.i16 Dd,simdExpImm_8 is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c1011<3 & c0808=1 & c0407=3 ) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=3) ) & Dd & simdExpImm_8 +{ + Dd = Dd & ~simdExpImm_8; +} + +:vbic.i32 Qd,simdExpImm_16 is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c1011<3 & c0808=1 & c0407=7 ) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=7) ) & Qd & simdExpImm_16 +{ + Qd = Qd & ~simdExpImm_16; +} + +:vbic Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=1 & c0811=1 & Q6=0 & c0404=1 ) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1) ) & Dm & Dn & Dd +{ + Dd = Dn & ~Dm; +} + +:vbic Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=1 & c0811=1 & Q6=1 & c0404=1 ) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd +{ + Qd = Qn & ~Qm; +} + +:vbif Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=3 & c0811=1 & Q6=0 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1) ) & Dm & Dn & Dd +{ + Dd = VectorBitwiseInsertIfFalse(Dd,Dn,Dm); +} + +:vbif Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=3 & c0811=1 & Q6=1 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd +{ + Qd = VectorBitwiseInsertIfFalse(Qd,Qn,Qm); +} + +:vbit Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=1 & Q6=0 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dm & Dn & Dd +{ + Dd = VectorBitwiseInsertIfTrue(Dd,Dn,Dm); +} + +:vbit Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=1 & Q6=1 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd +{ + Qd = VectorBitwiseInsertIfTrue(Qd,Qn,Qm); +} + +:vbsl Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=1 & c0811=1 & Q6=0 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dm & Dn & Dd +{ + Dd = VectorBitwiseSelect(Dd,Dn,Dm); +} + +:vbsl Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=1 & c0811=1 & Q6=1 & c0404=1 ) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=1 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qm & Qn & Qd +{ + Qd = VectorBitwiseSelect(Qd,Qn,Qm); +} + +:vceq.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021<3 & c0811=8 & Q6=0 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=8 & thv_Q6=0 & thv_c0404=1) ) & esize2021 & Dm & Dn & Dd +{ + Dd = VectorCompareEqual(Dn,Dm,esize2021); +} + +:vceq.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021<3 & c0811=8 & Q6=1 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=8 & thv_Q6=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorCompareEqual(Qn,Qm,esize2021); +} + +:vceq.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=14 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + Dd = FloatVectorCompareEqual(Dn,Dm,2:1,32:1); +} + +:vceq.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=14 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & Qm & Qn & Qd +{ + Qd = FloatVectorCompareEqual(Qn,Qm,2:1,32:1); +} + +:vceq.i^esize1819 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=2 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=2 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = VectorCompareEqual(Dm,zero,esize1819); +} + +:vceq.i^esize1819 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=2 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=2 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = VectorCompareEqual(Qm,zero,esize1819); +} + +:vceq.f32 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=10 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=10 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = FloatVectorCompareEqual(Dm,zero,2:1,32:1); +} + +:vceq.f32 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=10 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=10 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = FloatVectorCompareEqual(Qm,zero,2:1,32:1); +} + +:vcge.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=3 & Q6=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=0 & thv_c0404=1) ) & udt & esize2021 & Dm & Dn & Dd +{ + Dd = VectorCompareGreaterThanOrEqual(Dn,Dm,esize2021,udt); +} + +:vcge.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=3 & Q6=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd +{ + Qd = VectorCompareGreaterThanOrEqual(Qn,Qm,esize2021,udt); +} + +:vcge.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=0 & c0811=14 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + Dd = FloatVectorCompareGreaterThanOrEqual(Dn,Dm,2:1,32:1); +} + +:vcge.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=0 & c0811=14 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & Qm & Qn & Qd +{ + Qd = FloatVectorCompareGreaterThanOrEqual(Qn,Qm,2:1,32:1); +} + +:vcge.s^esize1819 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=1 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=1 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = VectorCompareGreaterThanOrEqual(Dm,zero,esize1819); +} + +:vcge.s^esize1819 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=1 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=1 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = VectorCompareGreaterThanOrEqual(Qm,zero,esize1819); +} + +:vcge.f32 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=9 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=9 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = FloatVectorCompareGreaterThanOrEqual(Dm,zero,2:1,32:1); +} + +:vcge.f32 Qd,Qm,zero is( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=9 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=9 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = FloatVectorCompareGreaterThanOrEqual(Qm,zero,2:1,32:1); +} + +:vcgt.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=3 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=0 & thv_c0404=0) ) & udt & esize2021 & Dm & Dn & Dd +{ + Dd = VectorCompareGreaterThan(Dn,Dm,esize2021); +} + +:vcgt.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=3 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=3 & thv_Q6=1 & thv_c0404=0) ) & udt & esize2021 & Qm & Qn & Qd +{ + Qd = VectorCompareGreaterThan(Qn,Qm,esize2021); +} + +:vcgt.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=14 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=14 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + Dd = FloatVectorCompareGreaterThan(Dn,Dm,2:1,32:1); +} + +:vcgt.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=2 & c0811=14 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=14 & thv_Q6=1 & thv_c0404=0) ) & Qm & Qn & Qd +{ + Qd = FloatVectorCompareGreaterThan(Qn,Qm,2:1,32:1); +} + +:vcgt.i^esize1819 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=0 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0 & thv_Q6=0 & thv_c0404=0 ) ) & esize1819 & Dd & Dm & zero +{ + Dd = VectorCompareGreaterThan(Dm,zero,esize1819); +} + +:vcgt.i^esize1819 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=0 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0 & thv_Q6=1 & thv_c0404=0 ) ) & esize1819 & Qd & Qm & zero +{ + Qd = VectorCompareGreaterThan(Qm,zero,esize1819); +} + +:vcgt.f32 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=8 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=8 & thv_Q6=0 & thv_c0404=0 ) ) & esize1819 & Dd & Dm & zero +{ + Dd = FloatVectorCompareGreaterThan(Dm,zero,2:1,32:1); +} + +:vcgt.f32 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=8 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=8 & thv_Q6=1 & thv_c0404=0 ) ) & esize1819 & Qd & Qm & zero +{ + Qd = FloatVectorCompareGreaterThan(Qm,zero,2:1,32:1); +} + +:vcle.s^esize1819 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=3 & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=3 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm & zero +{ + Dd = VectorCompareGreaterThanOrEqual(zero,Dm,esize1819); +} + +:vcle.s^esize1819 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=3 & Q6=1 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=3 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm & zero +{ + Qd = VectorCompareGreaterThanOrEqual(zero,Qm,esize1819); +} + +:vcle.f32 Dd,Dm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=0xb & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0xb & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm & zero +{ + Dd = FloatVectorCompareGreaterThanOrEqual(zero,Dm,2:1,32:1); +} + +:vcle.f32 Qd,Qm,zero is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=0xb & Q6=1 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=0xb & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm & zero +{ + Qd = FloatVectorCompareGreaterThanOrEqual(zero,Qm,2:1,32:1); +} + +:vcls.s^esize1819 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=0 & c0711=8 & Q6=0 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=8 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dd & Dm +{ + Dd = VectorCountLeadingSignBits(Dm,esize1819); +} + +:vcls.s^esize1819 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=0 & c0711=8 & Q6=1 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=0 & thv_c0711=8 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qd & Qm +{ + Qd = VectorCountLeadingSignBits(Qm,esize1819); +} + +:vclt.s^esize1819 Dd,Dm,zero is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=4 & Q6=0 & c0404=0) | + ( $(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=4 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = VectorCompareGreaterThan(zero,Dm,esize1819); +} + +:vclt.s^esize1819 Qd,Qm,zero is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=4 & Q6=1 & c0404=0) | + ( $(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=4 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = VectorCompareGreaterThan(zero,Qm,esize1819); +} + +:vclt.f32 Dd,Dm,zero is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=12 & Q6=0 & c0404=0) | + ( $(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=12 & thv_Q6=0 & thv_c0404=0) ) & esize1819 & Dm & Dd & zero +{ + Dd = FloatVectorCompareGreaterThan(zero,Dm,2:1,32:1); +} + +:vclt.f32 Qd,Qm,zero is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=12 & Q6=1 & c0404=0) | + ( $(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=12 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd & zero +{ + Qd = FloatVectorCompareGreaterThan(zero,Qm,2:1,32:1); +} + +:vclz.i^esize1819 Dd,Dm is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Dd & c0711=9 & Q6=0 & c0404=0 & Dm +{ + Dd = VectorCountLeadingZeros(Dm,esize1819); +} + +:vclz.i^esize1819 Qd,Qm is $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & esize1819 & c1617=0 & Qd & c0711=9 & Q6=1 & c0404=0 & Qm +{ + Qd = VectorCountLeadingZeros(Qm,esize1819); +} + +@endif # SIMD + +# set float register flags correctly for comparison +macro FloatVectorCompare(op1,op2,nanx) { + local tNG = op1 f< op2; + local tZR = op1 f== op2; + local tCY = op2 f<= op1; + tOV:1 = nan(op1) | nan(op2); # this is really a comparison with NAN and may also raise an exception when NAN + + fpscr = (fpscr & 0x0fffffff) | (zext(tNG) << 31) | (zext(tZR) << 30) | (zext(tCY) << 29) | (zext(tOV) << 28); +} + +@if defined(VFPv2) || defined(VFPv3) + +nanx: "e" is c0707=1 { export 1:1; } +nanx: is c0707=0 { export 0:1; } + +:vcmp^nanx^COND^".f32" Sd,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=4 & c0811=0b1010 & c0606=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=4 & thv_c0811=0b1010 & thv_c0606=1 & thv_c0404=0) ) & Sd & nanx & Sm +{ + build COND; + build Sd; + build Sm; + + FloatVectorCompare(Sd,Sm,nanx); +} + +:vcmp^nanx^COND^".f64" Dd,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=4 & c0811=0b1011 & c0606=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=4 & thv_c0811=0b1011 & thv_c0606=1 & thv_c0404=0) ) & Dd & nanx & Dm +{ + build COND; + build Dd; + build Dm; + FloatVectorCompare(Dd,Dm,nanx); +} + +:vcmp^nanx^COND^".f32" Sd,zero is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=5 & c0811=0b1010 & c0006=0b1000000 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=5 & thv_c0811=0b1010 & thv_c0006=0b1000000 ) ) & Sd & nanx & zero +{ + build COND; + build Sd; + local Zero:4 = 0; + FloatVectorCompare(Sd,Zero,nanx); +} + +:vcmp^nanx^COND^".f64" Dd,zero is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=5 & c0811=0b1011 & c0006=0b1000000 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=5 & thv_c0811=0b1011 & thv_c0006=0b1000000 ) ) & Dd & nanx & zero +{ + build COND; + build Dd; + local Zero:8 = 0; + FloatVectorCompare(Dd,Zero,nanx); +} + +@endif # VFPv2 || VFPv3 + +define pcodeop VectorCountOneBits; + + +@ifndef VERSION_8 +#second arg to conversion function indicates rounding mode (see RMODE bits of FPSCR) +define pcodeop VectorFloatToSigned; +define pcodeop VectorFloatToUnsigned; +define pcodeop VectorSignedToFloat; +define pcodeop VectorUnsignedToFloat; +@endif # VERSION_8 + +@if defined(SIMD) +####### +# VCVT (between floating-point and integer, Advanced SIMD) +# + +:vcnt.8 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1619=0 & c0711=10 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0711=10 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm +{ + Dd = VectorCountOneBits(Dm,8:1,8:1); +} + +:vcnt.8 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=0 & c1617=0 & c0711=10 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0711=10 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm +{ + Qd = VectorCountOneBits(Qm,8:1,8:1); +} + +@ifndef VERSION_8 +:vcvt.s32.f32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=2 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=2 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm + +{ + Dd = VectorFloatToSigned(Dm,3:1); +} + +:vcvt.u32.f32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=3 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=3 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm + +{ + Dd = VectorFloatToUnsigned(Dm,3:1); +} + +:vcvt.f32.s32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=0 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=0 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm +{ + Dd = VectorSignedToFloat(Dm,0:1); +} + +:vcvt.f32.u32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=1 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=1 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm + +{ + Dd = VectorUnsignedToFloat(Dm,0:1); +} + +:vcvt.s32.f32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=2 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=2 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm + +{ + Qd = VectorFloatToSigned(Qm,3:1); +} + +:vcvt.u32.f32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=3 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=3 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm + +{ + Qd = VectorFloatToUnsigned(Qm,3:1); +} + +:vcvt.f32.s32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=0 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=0 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm + +{ + Qd = VectorSignedToFloat(Qm,0:1); +} + +:vcvt.f32.u32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x3b & c0911=3 & c0708=1 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x3b & thv_c0911=3 & thv_c0708=1 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm + +{ + Qd = VectorUnsignedToFloat(Qm,0:1); +} + +@endif # ! VERSION_8 +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +@ifndef VERSION_8 +####### +# VCVT (between floating-point and integer, VFP) +# + +roundMode: "r" is TMode=0 & c0707=0 { tmp:1 = $(FPSCR_RMODE); export tmp; } +roundMode: is TMode=0 & c0707=1 { export 3:1; } # Round towards zero +roundMode: "r" is TMode=1 & thv_c0707=0 { tmp:1 = $(FPSCR_RMODE); export tmp; } +roundMode: is TMode=1 & thv_c0707=1 { export 3:1; } # Round towards zero + +:vcvt^roundMode^COND^".s32.f32" Sd,Sm is COND & ( ($(AMODE) &ARMcond=1 & c2327=0x1d & c1921=7 & c1618=5 & c0911=5 & c0808=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1b & thv_c1921=7 & thv_c1618=5 & thv_c0911=5 & thv_c0808=0 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sm & roundMode +{ + build COND; + build Sd; + build Sm; + build roundMode; + Sd = VectorFloatToSigned(Sm,roundMode); +} + +:vcvt^roundMode^COND^".s32.f64" Sd,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=5 & c0911=5 & c0808=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=5 & thv_c0911=5 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0) ) & Sd & roundMode & Dm +{ + build COND; + build Sd; + build Dm; + build roundMode; + Sd = VectorFloatToSigned(Dm,roundMode); +} + +:vcvt^roundMode^COND^".u32.f32" Sd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=4 & c0911=5 & c0808=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=4 & thv_c0911=5 & thv_c0808=0 & thv_c0606=1 & thv_c0404=0) ) & roundMode & Sd & Sm +{ + build COND; + build Sd; + build Sm; + build roundMode; + Sd = VectorFloatToUnsigned(Sm,roundMode); +} + +:vcvt^roundMode^COND^".u32.f64" Sd,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=4 & c0911=5 & c0808=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=4 & thv_c0911=5 & thv_c0808=1 & thv_c0606=1 & thv_c0404=0)) & roundMode& Sd & Dm +{ + build COND; + build Sd; + build Dm; + build roundMode; + Sd = VectorFloatToUnsigned(Dm,roundMode); +} + +:vcvt^COND^".f32.s32" Sd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=0 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sm +{ + build COND; + build Sd; + build Sm; + mode:1 = $(FPSCR_RMODE); + Sd = VectorSignedToFloat(Sm,mode); +} + +:vcvt^COND^".f64.s32" Dd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=0 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Dd & Sm +{ + build COND; + build Dd; + build Sm; + mode:1 = $(FPSCR_RMODE); + Dd = VectorSignedToFloat(Sm,mode); +} + +:vcvt^COND^".f32.u32" Sd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=0 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sm +{ + build COND; + build Sd; + build Sm; + mode:1 = $(FPSCR_RMODE); + Sd = VectorUnsignedToFloat(Sm,mode); +} + +:vcvt^COND^".f64.u32" Dd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1618=0 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1618=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) )& Dd & Sm +{ + build COND; + build Dd; + build Sm; + mode:1 = $(FPSCR_RMODE); + Dd = VectorUnsignedToFloat(Sm,mode); +} +@endif # ! VERSION_8 +@endif # VFPv2 || VFPv3 + +@if defined(SIMD) +@ifndef VERSION_8 +define pcodeop VectorFloatToSignedFixed; +define pcodeop VectorFloatToUnsignedFixed; +define pcodeop VectorSignedFixedToFloat; +define pcodeop VectorUnsignedFixedToFloat; + +####### +# VCVT (between floating-point and fixed-point, Advanced SIMD) +# + +fbits: "#"val is c1620 [ val = 32 - c1620; ] { tmp:1 = val; export tmp; } + +:vcvt.s32.f32 Dd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=1 & c0707=0 & Q6=0 & c0404=1 & Dm +{ + Dd = VectorFloatToSignedFixed(Dm,fbits); +} + +:vcvt.u32.f32 Dd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=1 & c0707=0 & Q6=0 & c0404=1 & Dm +{ + Dd = VectorFloatToUnsignedFixed(Dm,fbits); +} + +:vcvt.f32.s32 Dd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=0 & c0707=0 & Q6=0 & c0404=1 & Dm +{ + Dd = VectorSignedFixedToFloat(Dm,fbits); +} + +:vcvt.f32.u32 Dd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Dd & c0911=7 & c0808=0 & c0707=0 & Q6=0 & c0404=1 & Dm +{ + Dd = VectorUnsignedFixedToFloat(Dm,fbits); +} + +:vcvt.s32.f32 Qd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=1 & c0707=0 & Q6=1 & c0404=1 & Dm +{ + Qd = VectorFloatToSignedFixed(Dm,fbits); +} + +:vcvt.u32.f32 Qd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=1 & c0707=0 & Q6=1 & c0404=1 & Dm +{ + Qd = VectorFloatToUnsignedFixed(Dm,fbits); +} + +:vcvt.f32.s32 Qd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=0 & c0707=0 & Q6=1 & c0404=1 & Dm +{ + Qd = VectorSignedFixedToFloat(Dm,fbits); +} + +:vcvt.f32.u32 Qd,Dm,fbits is $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2121=1 & fbits & Qd & c0911=7 & c0808=0 & c0707=0 & Q6=1 & c0404=1 & Dm +{ + Qd = VectorUnsignedFixedToFloat(Dm,fbits); +} + +@endif # ! VERSION_8 + +@endif # SIMD + +@if defined(VFPv3) + +@ifndef VERSION_8 + +####### +# VCVT (between floating-point and fixed-point, VFP) +# + +fbits16: "#"^val is TMode=0 & c0505 & c0003 [ val = 16 - ((c0505 << 4) + c0003); ] { tmp:1 = val; export tmp; } +fbits32: "#"^val is TMode=0 & c0505 & c0003 [ val = 32 - ((c0505 << 4) + c0003); ] { tmp:1 = val; export tmp; } +fbits16: "#"^val is TMode=1 & thv_c0505 & thv_c0003 [ val = 16 - ((thv_c0505 << 4) + thv_c0003); ] { tmp:1 = val; export tmp; } +fbits32: "#"^val is TMode=1 & thv_c0505 & thv_c0003 [ val = 32 - ((thv_c0505 << 4) + thv_c0003); ] { tmp:1 = val; export tmp; } + +:vcvt^COND^".s16.f32" Sd,Sd2,fbits16 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0)) & Sd & Sd2 & fbits16 +{ + build COND; + build Sd; + build Sd2; + build fbits16; + Sd = VectorFloatToSignedFixed(Sd2,16:1,fbits16); +} + +:vcvt^COND^".u16.f32" Sd,Sd2,fbits16 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=0 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sd2 & fbits16 +{ + build COND; + build Sd; + build Sd2; + build fbits16; + Sd = VectorFloatToUnsignedFixed(Sd2,16:1,fbits16); +} + +:vcvt^COND^".s32.f32" Sd,Sd2,fbits32 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sd2 & fbits32 +{ + build COND; + build Sd; + build Sd2; + build fbits32; + Sd = VectorFloatToSignedFixed(Sd2,32:1,fbits32); +} + +:vcvt^COND^".u32.f32" Sd,Sd2,fbits32 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=0 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Sd & Sd2 & fbits32 +{ + build COND; + build Sd; + build Sd2; + build fbits32; + Sd = VectorFloatToUnsignedFixed(Sd2,32:1,fbits32); +} + +:vcvt^COND^".s16.f64" Dd,Dd2,fbits16 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & Dd & Dd2 & fbits16 +{ + build COND; + build Dd; + build Dd2; + build fbits16; + Dd = VectorFloatToSignedFixed(Dd2,16:1,fbits16); +} + +:vcvt^COND^".u16.f64" Dd,Dd2,fbits16 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=1 & thv_c0707=0 & thv_c0606=1 & thv_c0404=0) ) & Dd & Dd2 & fbits16 +{ + build COND; + build Dd; + build Dd2; + build fbits16; + Dd = VectorFloatToUnsignedFixed(Dd2,16:1,fbits16); +} + +:vcvt^COND^".s32.f64" Dd,Dd2,fbits32 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=0 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=0 & thv_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Dd & Dd2 & fbits32 +{ + build COND; + build Dd; + build Dd2; + build fbits32; + Dd = VectorFloatToSignedFixed(Dd2,32:1,fbits32); +} + +:vcvt^COND^".u32.f64" Dd,Dd2,fbits32 is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=0 & c1717=1 & c1616=1 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1921=7 & thv_c1818=0 & thv_c1717=1 & thv_c1616=1 & thv_c0911=5 & thv_c0808=1 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0) ) & Dd & Dd2 & fbits32 +{ + build COND; + build Dd; + build Dd2; + build fbits32; + Dd = VectorFloatToUnsignedFixed(Dd2,32:1,fbits32); +} + +:vcvt^COND^".f32.s16" Sd,Sd2,fbits16 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0 & fbits16 +{ + build COND; + build Sd; + build Sd2; + build fbits16; + Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits16); +} + +:vcvt^COND^".f32.u16" Sd,Sd2,fbits16 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=0 & c0606=1 & c0404=0 & fbits16 +{ + build COND; + build Sd; + build Sd2; + build fbits16; + Sd = VectorUnsignedFixedToFloat(Sd2,32:1,fbits16); +} + +:vcvt^COND^".f32.s32" Sd,Sd2,fbits32 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0 & fbits32 +{ + build COND; + build Sd; + build Sd2; + build fbits32; + Sd = VectorSignedFixedToFloat(Sd2,32:1,fbits32); +} + +:vcvt^COND^".f32.u32" Sd,Sd2,fbits32 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Sd & Sd2 & c0911=5 & c0808=0 & c0707=1 & c0606=1 & c0404=0 & fbits32 +{ + build COND; + build Sd; + build Sd2; + build fbits32; + Sd = VectorUnsignedFixedToFloat(Sd2,32:1,fbits32); +} + +:vcvt^COND^".f64.s16" Dd,Dd2,fbits16 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0 & fbits16 +{ + build COND; + build Dd; + build Dd2; + build fbits16; + Dd = VectorSignedFixedToFloat(Dd2,64:1,fbits16); +} + +:vcvt^COND^".f64.u16" Dd,Dd2,fbits16 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=0 & c0606=1 & c0404=0 & fbits16 +{ + build COND; + build Dd; + build Dd2; + build fbits16; + Dd = VectorUnsignedFixedToFloat(Dd2,64:1,fbits16); +} + +:vcvt^COND^".f64.s32" Dd,Dd2,fbits32 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=0 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0 & fbits32 +{ + build COND; + build Dd; + build Dd2; + build fbits32; + Dd = VectorSignedFixedToFloat(Dd2,64:1,fbits32); +} + +:vcvt^COND^".f64.u32" Dd,Dd2,fbits32 is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1921=7 & c1818=1 & c1717=1 & c1616=1 & Dd & Dd2 & c0911=5 & c0808=1 & c0707=1 & c0606=1 & c0404=0 & fbits32 +{ + build COND; + build Dd; + build Dd2; + build fbits32; + Dd = VectorUnsignedFixedToFloat(Dd2,64:1,fbits32); +} + +@endif # ! VERSION_8 + +@endif # VFPv3 + +define pcodeop VectorFloatDoubleToSingle; +define pcodeop VectorFloatSingleToDouble; + +@if defined(VFPv2) || defined(VFPv3) + +@ifndef VERSION_8 +####### +# VCVT (between double-precision and single-precision) +# + +:vcvt^COND^".f32.f64" Sd,Dm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x37 & Sd & c0911=5 & c0808=1 & c0607=3 & c0404=0 & Dm +{ + build COND; + build Sd; + build Dm; + Sd = float2float(Dm); +} + +:vcvt^COND^".f64.f32" Dd,Sm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x37 & Dd & c0911=5 & c0808=0 & c0607=3 & c0404=0 & Sm +{ + build COND; + build Dd; + build Sm; + Dd = float2float(Sm); +} + +@endif # ! VERSION_8 +@endif # VFPv2 || VFPv3 + +@if defined(SIMD) + +@ifndef VERSION_8 +define pcodeop VectorFloatSingleToHalf; +define pcodeop VectorFloatHalfToSingle; + +####### +# VCVT (between half-precision and single-precision) +# +:vcvt.f16.f32 Dd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x36 & c0911=3 & c0808=0 & c0607=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x36 & thv_c0911=3 & thv_c0808=0 & thv_c0607=0 & thv_c0404=0 ) ) & Dd & Qm + +{ + Dd = VectorFloatSingleToHalf(Qm, 4:1, 16:1); +} + +:vcvt.f16.f32 Qd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c1621=0x36 & c0911=3 & c0808=1 & c0607=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c1621=0x36 & thv_c0911=3 & thv_c0808=1 & thv_c0607=0 & thv_c0404=0 ) ) & Qd & Dm + +{ + Qd = VectorFloatHalfToSingle(Dm, 4:1, 16:1); +} + +@endif # ! VERSION_8 +@endif # SIMD + +@if defined(VFPv3) + +@ifndef VERSION_8 +:vcvtb^COND^".f32.f16" Sd,Sm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x32 & Sd & c0611=0x29 & c0404=0 & Sm +{ + build COND; + build Sd; + build Sm; + Sd = float2float(Sm:2); +} + +:vcvtb^COND^".f16.f32" Sd,Sm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x33 & Sd & c0611=0x29 & c0404=0 & Sm +{ + build COND; + build Sd; + build Sm; + w:2 = float2float(Sm); + Sd[0,16] = w; +} + +:vcvtt^COND^".f32.f16" Sd,Sm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x32 & Sd & c0611=0x2b & c0404=0 & Sm +{ + build COND; + build Sd; + build Sm; + w:2 = Sm(2); + Sd = float2float(w); +} + +:vcvtt^COND^".f16.f32" Sd,Sm is $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x33 & Sd & c0611=0x2b & c0404=0 & Sm +{ + build COND; + build Sd; + build Sm; + w:2 = float2float(Sm); + Sd[16,16] = w; +} +@endif # ! VERSION_8 + +@endif # VFPv3 + +@if defined(VFPv2) || defined(VFPv3) + +:vdiv^COND^".f32" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c2021=0 & c0811=10 & c0606=0 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=0 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0 ) ) & Sn & Sd & Sm +{ + build COND; + build Sd; + build Sm; + build Sn; + Sd = Sn f/ Sm; +} + +:vdiv^COND^".f64" Dd,Dn,Dm is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x1d & c2021=0 & c0811=11 & c0606=0 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0 ) ) & Dn & Dd & Dm +{ + build COND; + build Dd; + build Dm; + build Dn; + Dd = Dn f/ Dm; +} + +@endif # VFPv2 || VFPv3 + +define pcodeop VectorHalvingAdd; +define pcodeop VectorHalvingSubtract; +define pcodeop VectorRoundHalvingAdd; +define pcodeop VectorRoundAddAndNarrow; + +@if defined(SIMD) + +####### +# VDUP (scalar) +# + +vdupIndex: c1719 is TMode=0 & c1616=1 & c1719 { tmp:4 = c1719; export tmp; } +vdupIndex: c1819 is TMode=0 & c1617=2 & c1819 { tmp:4 = c1819; export tmp; } +vdupIndex: c1919 is TMode=0 & c1618=4 & c1919 { tmp:4 = c1919; export tmp; } + +vdupIndex: thv_c1719 is TMode=1 & thv_c1616=1 & thv_c1719 { tmp:4 = thv_c1719; export tmp; } +vdupIndex: thv_c1819 is TMode=1 & thv_c1617=2 & thv_c1819 { tmp:4 = thv_c1819; export tmp; } +vdupIndex: thv_c1919 is TMode=1 & thv_c1618=4 & thv_c1919 { tmp:4 = thv_c1919; export tmp; } + +vdupSize: 8 is TMode=0 & c1616=1 { } +vdupSize: 16 is TMode=0 & c1617=2 { } +vdupSize: 32 is TMode=0 & c1618=4 { } +vdupSize: 8 is TMode=1 & thv_c1616=1 { } +vdupSize: 16 is TMode=1 & thv_c1617=2 { } +vdupSize: 32 is TMode=1 & thv_c1618=4 { } + +vdupDm: Dm^"["^vdupIndex^"]" is Dm & vdupIndex & ((TMode=0 & c1616=1) | (TMode=1 & thv_c1616=1)) +{ + ptr:4 = &Dm + vdupIndex; + val:8 = 0; + replicate1to8(*[register]:1 ptr, val); + export val; +} +vdupDm: Dm^"["^vdupIndex^"]" is Dm & vdupIndex & ((TMode=0 & c1617=2) | (TMode=1 & thv_c1617=2)) +{ + ptr:4 = &Dm + (2 * vdupIndex); + val:8 = 0; + replicate2to8(*[register]:2 ptr, val); + export val; +} +vdupDm: Dm^"["^vdupIndex^"]" is Dm & vdupIndex & ((TMode=0 & c1618=4) | (TMode=1 & thv_c1618=4)) +{ + ptr:4 = &Dm + (4 * vdupIndex); + val:8 = 0; + replicate4to8(*[register]:4 ptr, val); + export val; +} + +vdupDm16: vdupDm is vdupDm +{ + val:16 = zext(vdupDm); + val = val & (val << 64); + export val; +} + +:vdup.^vdupSize Dd,vdupDm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & vdupSize & c0711=0x18 & Q6=0 & c0404=0 ) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c0711=0x18 & thv_Q6=0 & thv_c0404=0 ) ) & Dd & vdupDm +{ + Dd = vdupDm; +} + +:vdup.^vdupSize Qd,vdupDm16 is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & vdupSize & c0711=0x18 & Q6=1 & c0404=0 ) | + ($(TMODE_F) &thv_c2327=0x1f & thv_c2021=3 & thv_c0711=0x18 & thv_Q6=1 & thv_c0404=0) ) & Qd & vdupDm16 +{ + Qd = vdupDm16; +} + +####### +# VDUP (ARM core register) +# + +vdupSize2: 8 is c2222=1 & c0505=0 { } +vdupSize2: 16 is c2222=0 & c0505=1 { } +vdupSize2: 32 is c2222=0 & c0505=0 { } + +vdupRd8: Rd is Rd & c2222=1 & c0505=0 +{ + val:8 = 0; + local tmpRd = Rd; + replicate1to8(tmpRd:1, val); + export val; +} +vdupRd8: Rd is Rd & c2222=0 & c0505=1 +{ + val:8 = 0; + local tmpRd = Rd; + replicate2to8(tmpRd:2, val); + export val; +} +vdupRd8: Rd is Rd & c2222=0 & c0505=0 +{ + val:8 = 0; + local tmpRd = Rd; + replicate4to8(tmpRd:4, val); + export val; +} + +vdupRd16: vdupRd8 is vdupRd8 +{ + val:16 = zext(vdupRd8); + val = val & (val << 64); + export val; +} + +:vdup^COND^"."^vdupSize2 Dn,vdupRd8 is COND & (( $(AMODE) & ARMcond=1 & c2327=0x1d & c2121=0 & c2020=0 & c0811=11 & c0606=0 & c0004=0x10) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0004=0x10 ) ) & Dn & vdupSize2 & vdupRd8 +{ + build COND; + build vdupRd8; + build Dn; + Dn = vdupRd8; +} + +:vdup^COND^"."^vdupSize2 Qn,vdupRd16 is COND & (( $(AMODE) & ARMcond=1 & c2327=0x1d & c2121=1 & c2020=0 & c0811=11 & c0606=0 & c0004=0x10) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=2 & thv_c0811=11 & thv_c0606=0 & thv_c0004=0x10 ) ) & Qn & vdupSize2 & vdupRd16 +{ + build COND; + build vdupRd16; + build Qn; + Qn = vdupRd16; +} + +:veor Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=0x6 & c2021=0 & c0811=1 & Q6=0 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm + +{ + Dd = Dn ^ Dm; +} + +:veor Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=0x6 & c2021=0 & c0811=1 & Q6=1 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2021=0 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm +{ + Qd = Qn ^ Qm; +} + +extImm: "#"^c0811 is TMode=0 & c0811 { tmp:1 = c0811; export tmp; } +extImm: "#"^thv_c0811 is TMode=1 & thv_c0811 { tmp:1 = thv_c0811; export tmp; } + +:vext.8 Dd,Dn,Dm,extImm is ( ( $(AMODE) & cond=15 & c2327=5 & c2021=3 & c0606=0 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=3 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dn & Dm & extImm +{ + val:16 = (zext(Dm) << 64) | zext(Dn); + local shift = extImm * 8; + val = val >> shift; + Dd = val:8; +} + +:vext.8 Qd,Qn,Qm,extImm is ( ( $(AMODE) & cond=15 & c2327=5 & c2021=3 & c0606=1 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=3 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qn & Qm & extImm +{ + val:32 = (zext(Qm) << 128) | zext(Qn); + local shift = extImm * 8; + val = val >> shift; + Qd = val:16; +} + +:vhadd.^udt^esize2021 Dd,Dn,Dm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=0 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=0 & thv_Q6=0 & thv_c0404=0) ) & udt & Dm & esize2021 & Dn & Dd +{ + Dd = VectorHalvingAdd(Dn,Dm,esize2021,udt); +} + +:vhadd.^udt^esize2021 Qd,Qn,Qm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=0 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=0 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd +{ + Qd = VectorHalvingAdd(Qn,Qm,esize2021,udt); +} + + +:vraddhn.i^esize2021x2 Dd,Qn,Qm is (($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=4 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=4 & thv_Q6=0 & thv_c0404=0) ) & Qm & esize2021x2 & Qn & Dd +{ + Dd = VectorRoundAddAndNarrow(Qn,Qm,esize2021x2); +} + +:vrhadd.^udt^esize2021 Dd,Dn,Dm is (($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=1 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=1 & thv_Q6=0 & thv_c0404=0) ) & udt & Dm & esize2021 & Dn & Dd +{ + Dd = VectorRoundHalvingAdd(Dn,Dm,esize2021,udt); +} + +:vrhadd.^udt^esize2021 Qd,Qn,Qm is (($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=1 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=1 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd +{ + Qd = VectorRoundHalvingAdd(Qn,Qm,esize2021,udt); +} + +:vhsub.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=2 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=2 & thv_Q6=0 & thv_c0404=0) ) & udt & esize2021 & Dn & Dd & Dm +{ + Dd = VectorHalvingSubtract(Dn,Dm,esize2021,udt); +} + +:vhsub.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=2 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=2 & thv_Q6=1 & thv_c0404=0) ) & udt & Qm & esize2021 & Qn & Qd +{ + Qd = VectorHalvingSubtract(Qn,Qm,esize2021,udt); +} + +####### +# VLD1 (multiple single elements) +# + +buildVld1DdList: Dreg is Dreg & counter=1 [ counter=0; regNum=regNum+1; ] +{ + Dreg = * mult_addr; +} +buildVld1DdList: Dreg,buildVld1DdList is Dreg & buildVld1DdList [ counter=counter-1; regNum=regNum+1; ] +{ + Dreg = * mult_addr; + mult_addr = mult_addr + 8; + build buildVld1DdList; +} + +vld1DdList: "{"^buildVld1DdList^"}" is TMode=0 & c0811=7 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=0 & c0811=10 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=0 & c0811=6 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=3; ] { export 3:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=0 & c0811=2 & D22 & c1215 & buildVld1DdList [ regNum=(D22<<4)+c1215-1; counter=4; ] { export 4:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=1 & thv_c0811=7 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=1 & thv_c0811=10 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=1 & thv_c0811=6 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=3; ] { export 3:4; } +vld1DdList: "{"^buildVld1DdList^"}" is TMode=1 & thv_c0811=2 & thv_D22 & thv_c1215 & buildVld1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=4; ] { export 4:4; } + +@define Vld1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10)" +@define thv_Vld1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10)" + +vldAlign45: is TMode=0 & c0405=0 { } +vldAlign45: "@64" is TMode=0 & c0405=1 { } +vldAlign45: "@128" is TMode=0 & c0405=2 { } +vldAlign45: "@256" is TMode=0 & c0405=3 { } +vldAlign45: is TMode=1 & thv_c0405=0 { } +vldAlign45: "@64" is TMode=1 & thv_c0405=1 { } +vldAlign45: "@128" is TMode=1 & thv_c0405=2 { } +vldAlign45: "@256" is TMode=1 & thv_c0405=3 { } + +RnAligned45: "["^VRn^vldAlign45^"]" is TMode=0 & VRn & vldAlign45 { export VRn; } +RnAligned45: "["^VRn^vldAlign45^"]" is TMode=1 & VRn & vldAlign45 { export VRn; } + + +:vld1.^esize0607 vld1DdList,RnAligned45 is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & c0003=15 & $(Vld1DdList)) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0003=15 & $(thv_Vld1DdList)) ) & esize0607 & RnAligned45 & vld1DdList +{ + mult_addr = RnAligned45; + build vld1DdList; +} + +:vld1.^esize0607 vld1DdList,RnAligned45^"!" is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & c0003=13 & $(Vld1DdList)) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0003=13 & $(thv_Vld1DdList)) ) & esize0607 & RnAligned45 & vld1DdList +{ + mult_addr = RnAligned45; + build vld1DdList; + RnAligned45 = RnAligned45 + (8 * vld1DdList); +} + +:vld1.^esize0607 vld1DdList,RnAligned45,VRm is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & $(Vld1DdList)) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & $(thv_Vld1DdList)) ) & VRm & esize0607 & RnAligned45 & vld1DdList +{ + mult_addr = RnAligned45; + build vld1DdList; + RnAligned45 = RnAligned45 + VRm; +} + + +####### +# VLD1 (single element to one lane) +# + +vld1Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } +vld1Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + +vld1DdElement2: Dd^"["^vld1Index^"]" is Dd & vld1Index & ((TMode=0 & c1011=0) | (TMode=1 & thv_c1011=0)) +{ + ptr:4 = &Dd + vld1Index; + *[register]:1 ptr = *:1 mult_addr; +} +vld1DdElement2: Dd^"["^vld1Index^"]" is Dd & vld1Index & ((TMode=0 & c1011=1) | (TMode=1 & thv_c1011=1)) +{ + ptr:4 = &Dd + (2 * vld1Index); + *[register]:2 ptr = *:2 mult_addr; +} +vld1DdElement2: Dd^"["^vld1Index^"]" is Dd & vld1Index & ((TMode=0 & c1011=2) | (TMode=1 & thv_c1011=2)) +{ + ptr:4 = &Dd + (4 * vld1Index); + *[register]:4 ptr = *:4 mult_addr; +} + +@define Vld1DdElement2 "((c1011=0 & c0404=0) | (c1011=1 & c0505=0) | (c1011=2 & (c0406=0 | c0406=3)))" +@define T_Vld1DdElement2 "((thv_c1011=0 & thv_c0404=0) | (thv_c1011=1 & thv_c0505=0) | (thv_c1011=2 & (thv_c0406=0 | thv_c0406=3)))" + + +vld1Align2: is TMode=0 & c0404=0 { } +vld1Align2: "@16" is TMode=0 & c1011=1 & c0404=1 { } +vld1Align2: "@32" is TMode=0 & c1011=2 & c0404=1 { } +vld1Align2: is TMode=1 & thv_c0404=0 { } +vld1Align2: "@16" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vld1Align2: "@32" is TMode=1 & thv_c1011=2 & thv_c0404=1 { } + +RnAligned2: "["^VRn^vld1Align2^"]" is VRn & vld1Align2 { export VRn; } + +:vld1.^esize1011 vld1DdElement2,RnAligned2 is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0809=0 & c0003=15 & $(Vld1DdElement2) ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & thv_c0003=15 & $(T_Vld1DdElement2) ) ) & RnAligned2 & esize1011 & vld1DdElement2 +{ + mult_addr = RnAligned2; + build vld1DdElement2; +} + +:vld1.^esize1011 vld1DdElement2,RnAligned2^"!" is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0809=0 & c0003=13 & $(Vld1DdElement2) ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & thv_c0003=13 & $(T_Vld1DdElement2) ) ) & RnAligned2 & esize1011 & vld1DdElement2 +{ + mult_addr = RnAligned2; + build vld1DdElement2; + RnAligned2 = RnAligned2 + esize1011; +} + +:vld1.^esize1011 vld1DdElement2,RnAligned2,VRm is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0809=0 & $(Vld1DdElement2) ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0809=0 & $(T_Vld1DdElement2) ) ) & VRm & RnAligned2 & esize1011 & vld1DdElement2 +{ + mult_addr = RnAligned2; + build vld1DdElement2; + RnAligned2 = RnAligned2 + VRm; +} + + +####### +# VLD1 (single element to all lanes) +# + +vld1RnReplicate: is Rn & c0607=0 +{ + val:8 = 0; + replicate1to8(*:1 Rn, val); + export val; +} +vld1RnReplicate: is Rn & c0607=1 +{ + val:8 = 0; + replicate2to8(*:2 Rn, val); + export val; +} +vld1RnReplicate: is Rn & c0607=2 +{ + val:8 = 0; + replicate4to8(*:4 Rn, val); + export val; +} + +vld1Dd3: Dreg^"[]" is Dreg { export Dreg; } + +buildVld1DdList3: is counter=0 { } +buildVld1DdList3: vld1Dd3 is counter=1 & vld1Dd3 [ counter=0; regNum=regNum+1; ] +{ + vld1Dd3 = mult_dat8; +} +buildVld1DdList3: vld1Dd3,buildVld1DdList3 is vld1Dd3 & buildVld1DdList3 [ counter=counter-1; regNum=regNum+1; ] +{ + vld1Dd3 = mult_dat8; + build buildVld1DdList3; +} + +vld1DdList3: "{"^buildVld1DdList3^"}" is c0505=0 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; } +vld1DdList3: "{"^buildVld1DdList3^"}" is c0505=1 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; } + +vld1Align3: is c0404=0 { } +vld1Align3: "@16" is c0404=1 & c0607=1 { } +vld1Align3: "@32" is c0404=1 & c0607=2 { } + +RnAligned3: "["^Rn^vld1Align3^"]" is Rn & vld1Align3 { export Rn; } + +@define vld1Constrain "((c0607=0 & c0404=0) | c0607=1 | c0607=2)" + +:vld1.^esize0607 vld1DdList3,RnAligned3 is $(AMODE) & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & c0003=15 & $(vld1Constrain) +{ + mult_dat8 = vld1RnReplicate; + build vld1DdList3; +} + +:vld1.^esize0607 vld1DdList3,RnAligned3^"!" is $(AMODE) & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & c0003=13 & $(vld1Constrain) +{ + mult_dat8 = vld1RnReplicate; + build vld1DdList3; + RnAligned3 = RnAligned3 + vld1DdList3; +} + +:vld1.^esize0607 vld1DdList3,RnAligned3,VRm is $(AMODE) & cond=15 & c2327=9 & c2021=2 & RnAligned3 & vld1RnReplicate & vld1DdList3 & c0811=12 & esize0607 & VRm & $(vld1Constrain) +{ + mult_dat8 = vld1RnReplicate; + build vld1DdList3; + RnAligned3 = RnAligned3 + VRm; +} + +thv_vld1RnReplicate: is VRn & thv_c0607=0 +{ + val:8 = 0; + replicate1to8(*:1 VRn, val); + export val; +} +thv_vld1RnReplicate: is VRn & thv_c0607=1 +{ + val:8 = 0; + replicate2to8(*:2 VRn, val); + export val; +} +thv_vld1RnReplicate: is VRn & thv_c0607=2 +{ + val:8 = 0; + replicate4to8(*:4 VRn, val); + export val; +} + +thv_vld1DdList3: "{"^buildVld1DdList3^"}" is thv_c0505=0 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; } +thv_vld1DdList3: "{"^buildVld1DdList3^"}" is thv_c0505=1 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; } + +thv_vld1Align3: is thv_c0404=0 { } +thv_vld1Align3: "@16" is thv_c0404=1 & thv_c0607=1 { } +thv_vld1Align3: "@32" is thv_c0404=1 & thv_c0607=2 { } + +VRnAligned3: "["^VRn^thv_vld1Align3^"]" is VRn & thv_vld1Align3 { export VRn; } + +@define T_vld1Constrain "((thv_c0607=0 & thv_c0404=0) | thv_c0607=1 | thv_c0607=2)" + +:vld1.^esize0607 thv_vld1DdList3,VRnAligned3 is $(TMODE_F) &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & thv_c0003=15 & $(T_vld1Constrain) +{ + mult_dat8 = thv_vld1RnReplicate; + build thv_vld1DdList3; +} + +:vld1.^esize0607 thv_vld1DdList3,VRnAligned3^"!" is $(TMODE_F) &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & thv_c0003=13 & $(T_vld1Constrain) +{ + mult_dat8 = thv_vld1RnReplicate; + build thv_vld1DdList3; + VRnAligned3 = VRnAligned3 + thv_vld1DdList3; +} + +:vld1.^esize0607 thv_vld1DdList3,VRnAligned3,VRm is $(TMODE_F) &thv_c2327=19 & thv_c2021=2 & VRnAligned3 & thv_vld1RnReplicate & thv_vld1DdList3 & thv_c0811=12 & esize0607 & VRm & $(T_vld1Constrain) +{ + mult_dat8 = thv_vld1RnReplicate; + build thv_vld1DdList3; + VRnAligned3 = VRnAligned3 + VRm; +} + +####### +# VLD2 (multiple 2-element structures) +# + +vld2Dd: Dreg is (($(AMODE) & c0607=0) | ($(TMODE_F) & thv_c0607=0)) & Dreg & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 8; + + *[register]:1 ptr1 = *:1 mult_addr; + mult_addr = mult_addr + 1; + *[register]:1 ptr2 = *:1 mult_addr; + mult_addr = mult_addr + 1; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 1; + ptr2 = ptr2 + 1; + goto ; + +} +vld2Dd: Dreg is (($(AMODE) & c0607=1) | ($(TMODE_F) & thv_c0607=1)) & Dreg & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 4; + + *[register]:2 ptr1 = *:2 mult_addr; + mult_addr = mult_addr + 2; + *[register]:2 ptr2 = *:2 mult_addr; + mult_addr = mult_addr + 2; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 2; + ptr2 = ptr2 + 2; + goto ; + +} +vld2Dd: Dreg is (($(AMODE) & c0607=2) | ($(TMODE_F) & thv_c0607=2)) & Dreg & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 2; + + *[register]:4 ptr1 = *:4 mult_addr; + mult_addr = mult_addr + 4; + *[register]:4 ptr2 = *:4 mult_addr; + mult_addr = mult_addr + 4; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 4; + ptr2 = ptr2 + 4; + goto ; + +} + +buildVld2DdListA: is counter=0 { } +buildVld2DdListA: vld2Dd,buildVld2DdListA is vld2Dd & buildVld2DdListA & esize0607 [ counter=counter-1; regNum=regNum+1; ] +{ + build vld2Dd; + build buildVld2DdListA; +} + +buildVld2DdListB: is counter2=0 { } +buildVld2DdListB: Dreg2 is Dreg2 & counter2=1 & esize0607 [ counter2=0; reg2Num=reg2Num+1; ] { } +buildVld2DdListB: Dreg2,buildVld2DdListB is Dreg2 & buildVld2DdListB & esize0607 [ counter2=counter2-1; reg2Num=reg2Num+1; ] { } + +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=0 & c0811=8 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; } +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=0 & c0811=9 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; } +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=0 & c0811=3 & D22 & c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVld2DdListA; build buildVld2DdListB; export 4:4; } +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=1 & thv_c0811=8 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; } +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=1 & thv_c0811=9 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVld2DdListA; build buildVld2DdListB; export 2:4; } +vld2DdList: "{"^buildVld2DdListA^buildVld2DdListB^"}" is TMode=1 & thv_c0811=3 & thv_D22 & thv_c1215 & buildVld2DdListA & buildVld2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVld2DdListA; build buildVld2DdListB; export 4:4; } + +@define Vld2DdList "(c0811=3 | c0811=8 | c0811=9)" +@define thv_Vld2DdList "(thv_c0811=3 | thv_c0811=8 | thv_c0811=9)" + +:vld2.^esize0607 vld2DdList,RnAligned45 is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & c0607<3 & c0003=15 & $(Vld2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0607<3 & thv_c0003=15 & $(thv_Vld2DdList) ) ) & RnAligned45 & esize0607 & vld2DdList +{ + mult_addr = RnAligned45; + build vld2DdList; +} + +:vld2.^esize0607 vld2DdList,RnAligned45^"!" is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & c0607<3 & c0003=13 & $(Vld2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0607<3 & thv_c0003=13 & $(thv_Vld2DdList) ) ) & RnAligned45 & esize0607 & vld2DdList +{ + mult_addr = RnAligned45; + build vld2DdList; + RnAligned45 = RnAligned45 + (8 * vld2DdList); +} + +:vld2.^esize0607 vld2DdList,RnAligned45,VRm is ( ($(AMODE) & cond=15 & c2327=8 & c2021=2 & c0607<3 & c0003 & $(Vld2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0607<3 & thv_c0003 & $(thv_Vld2DdList) ) ) & VRm & RnAligned45 & esize0607 & vld2DdList +{ + mult_addr = RnAligned45; + build vld2DdList; + RnAligned45 = RnAligned45 + VRm; +} + +####### +# VLD2 (single 2-element structure to one lane) +# + +vld2Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } +vld2Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + +vld2DdElement2: Dreg^"["^vld2Index^"]" is Dreg & vld2Index +{ +} + +vld2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vld2Align2: "@16" is TMode=0 & c1011=0 & c0404=1 { } +vld2Align2: "@32" is TMode=0 & c1011=1 & c0404=1 { } +vld2Align2: "@64" is TMode=0 & c1011=2 & c0405=1 { } +vld2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vld2Align2: "@16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vld2Align2: "@32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vld2Align2: "@64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } + +vld2RnAligned2: "["^VRn^vld2Align2^"]" is VRn & vld2Align2 { export VRn; } + +buildVld2DdList2: is counter=0 { } +buildVld2DdList2: vld2DdElement2 is counter=1 & vld2DdElement2 [ counter=0; regNum=regNum+regInc; ] { } +buildVld2DdList2: vld2DdElement2,buildVld2DdList2 is vld2DdElement2 & buildVld2DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld2DdList2: "{"^buildVld2DdList2^"}" is TMode=0 & D22 & c1215 & buildVld2DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single +vld2DdList2: "{"^buildVld2DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVld2DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double +vld2DdList2: "{"^buildVld2DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVld2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single +vld2DdList2: "{"^buildVld2DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVld2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double + + +:vld2.^esize1011 vld2DdList2,vld2RnAligned2 is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003=15 ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003=15 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2 + unimpl + +:vld2.^esize1011 vld2DdList2,vld2RnAligned2^"!" is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003=13 ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003=13 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2 + unimpl + +:vld2.^esize1011 vld2DdList2,vld2RnAligned2,VRm is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=1 & c0003 ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=1 & thv_c0003 ) ) & esize1011 & VRm & vld2RnAligned2 & vld2DdList2 + unimpl + +####### +# VLD2 (single 2-element structure to all lanes) +# + +vld2Align3: is TMode=0 & c0404=0 { } +vld2Align3: "@16" is TMode=0 & c0404=1 & c0607=0 { } +vld2Align3: "@32" is TMode=0 & c0404=1 & c0607=1 { } +vld2Align3: "@64" is TMode=0 & c0404=1 & c0607=2 { } +vld2Align3: is TMode=1 & thv_c0404=0 { } +vld2Align3: "@16" is TMode=1 & thv_c0404=1 & thv_c0607=0 { } +vld2Align3: "@32" is TMode=1 & thv_c0404=1 & thv_c0607=1 { } +vld2Align3: "@64" is TMode=1 & thv_c0404=1 & thv_c0607=2 { } + +vld2RnAligned3: "["^VRn^vld2Align3^"]" is VRn & vld2Align3 { export VRn; } + +buildVld2DdList3: is counter=0 { } +buildVld2DdList3: Dreg^"[]" is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVld2DdList3: Dreg^"[]",buildVld2DdList3 is Dreg & buildVld2DdList3 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld2DdList3: "{"^buildVld2DdList3^"}" is TMode=0 & c0505=0 & D22 & c1215 & buildVld2DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single +vld2DdList3: "{"^buildVld2DdList3^"}" is TMode=0 & c0505=1 & D22 & c1215 & buildVld2DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double +vld2DdList3: "{"^buildVld2DdList3^"}" is TMode=1 & thv_c0505=0 & thv_D22 & thv_c1215 & buildVld2DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single +vld2DdList3: "{"^buildVld2DdList3^"}" is TMode=1 & thv_c0505=1 & thv_D22 & thv_c1215 & buildVld2DdList3 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double + +:vld2.^esize0607 vld2DdList3,vld2RnAligned3 is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003=15 ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003=15 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3 + unimpl + +:vld2.^esize0607 vld2DdList3,vld2RnAligned3^"!" is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003=13 ) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003=13 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3 + unimpl + +:vld2.^esize0607 vld2DdList3,vld2RnAligned3,VRm is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=13 & c0607<3 & c0003) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=13 & thv_c0607<3 & thv_c0003 ) ) & esize0607 & VRm & vld2RnAligned3 & vld2DdList3 + unimpl + +####### +# VLD3 (multiple 3-element structures) +# + +vld3Align: is TMode=0 & c0404=0 { } +vld3Align: "@64" is TMode=0 & c0404=1 { } +vld3Align: is TMode=1 & thv_c0404=0 { } +vld3Align: "@64" is TMode=1 & thv_c0404=1 { } + + +vld3RnAligned: "["^VRn^vld3Align^"]" is VRn & vld3Align { export VRn; } + +buildVld3DdList: is counter=0 { } +buildVld3DdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVld3DdList: Dreg,buildVld3DdList is buildVld3DdList & Dreg [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld3DdList: "{"^buildVld3DdList^"}" is TMode=0 & c0811=4 & D22 & c1215 & buildVld3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList: "{"^buildVld3DdList^"}" is TMode=0 & c0811=5 & D22 & c1215 & buildVld3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double +vld3DdList: "{"^buildVld3DdList^"}" is TMode=1 & thv_c0811=4 & thv_D22 & thv_c1215 & buildVld3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList: "{"^buildVld3DdList^"}" is TMode=1 & thv_c0811=5 & thv_D22 & thv_c1215 & buildVld3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double + +:vld3.^esize0607 vld3DdList,vld3RnAligned is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 & c0003=15 ) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 & thv_c0003=15) ) & vld3RnAligned & esize0607 & vld3DdList unimpl + +:vld3.^esize0607 vld3DdList,vld3RnAligned^"!" is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 & c0003=13 ) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 & thv_c0003=13) ) & vld3RnAligned & esize0607 & vld3DdList unimpl + +:vld3.^esize0607 vld3DdList,vld3RnAligned,VRm is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & (c0811=4 | c0811=5) & c0607<3 & c0505=0 ) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & (thv_c0811=4 | thv_c0811=5) & thv_c0607<3 & thv_c0505=0 ) ) & VRm & vld3RnAligned & esize0607 & vld3DdList unimpl + +####### +# VLD3 (single 3-element structure to one lane) +# + +vld3Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } +vld3Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + +vld3DdElement2: Dreg^"["^vld3Index^"]" is Dreg & vld3Index +{ +} + +vld3Rn: "["^VRn^"]" is VRn { export VRn; } + +buildVld3DdList2: is counter=0 { } +buildVld3DdList2: vld3DdElement2 is counter=1 & vld3DdElement2 [ counter=0; regNum=regNum+regInc; ] { } +buildVld3DdList2: vld3DdElement2,buildVld3DdList2 is vld3DdElement2 & buildVld3DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld3DdList2: "{"^buildVld3DdList2^"}" is TMode=0 & D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList2: "{"^buildVld3DdList2^"}" is TMode=0 & ((c1011=1 & c0405=2) | (c1011=2 & c0406=4)) & D22 & c1215 & buildVld3DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double +vld3DdList2: "{"^buildVld3DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVld3DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList2: "{"^buildVld3DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0405=2) | (thv_c1011=2 & thv_c0406=4)) & thv_D22 & thv_c1215 & buildVld3DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double + + +:vld3.^esize1011 vld3DdList2,vld3Rn is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2 & c0003=15) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2 & thv_c0003=15) ) & vld3Rn & esize1011 & vld3DdList2 unimpl + +:vld3.^esize1011 vld3DdList2,vld3Rn^"!" is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2 & c0003=13) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2 & thv_c0003=13) ) & vld3Rn & esize1011 & vld3DdList2 unimpl + +:vld3.^esize1011 vld3DdList2,vld3Rn,VRm is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=2) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=2) ) & VRm & vld3Rn & esize1011 & vld3DdList2 unimpl + +####### +# VLD3 (single 3-element structure to all lanes) +# + +buildVld3DdList3: is counter=0 { } +buildVld3DdList3: Dreg^"[]" is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVld3DdList3: Dreg^"[]",buildVld3DdList3 is Dreg & buildVld3DdList3 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld3DdList3: "{"^buildVld3DdList3^"}" is TMode=0 & c0505=0 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList3: "{"^buildVld3DdList3^"}" is TMode=0 & c0505=1 & D22 & c1215 & buildVld3DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double +vld3DdList3: "{"^buildVld3DdList3^"}" is TMode=1 & thv_c0505=0 & thv_D22 & thv_c1215 & buildVld3DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single +vld3DdList3: "{"^buildVld3DdList3^"}" is TMode=1 & thv_c0505=1 & thv_D22 & thv_c1215 & buildVld3DdList3 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double + +:vld3.^esize0607 vld3DdList3,vld3Rn is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0 & c0003=15) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0 & thv_c0003=15) ) & vld3Rn & esize0607 & vld3DdList3 unimpl + +:vld3.^esize0607 vld3DdList3,vld3Rn^"!" is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0 & c0003=13) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0 & thv_c0003=13) ) & vld3Rn & esize0607 & vld3DdList3 unimpl + +:vld3.^esize0607 vld3DdList3,vld3Rn,VRm is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c0811=14 & c0607<3 & c0404=0) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=14 & thv_c0404=0) ) & VRm & vld3Rn & esize0607 & vld3DdList3 unimpl + + +####### +# VLD4 (single 4-element structure to one lane) +# + +vld4Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } +vld4Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + +vld4DdElement2: Dreg^"["^vld4Index^"]" is Dreg & vld4Index +{ +} + +vld4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vld4Align2: "@32" is TMode=0 & c1011=0 & c0404=1 { } +vld4Align2: "@64" is TMode=0 & (c1011=1 & c0404=1) | (c1011=2 & c0405=1) { } +vld4Align2: "@128" is TMode=0 & c1011=2 & c0405=2 { } +vld4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vld4Align2: "@32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vld4Align2: "@64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } +vld4Align2: "@128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } + +vld4RnAligned2: "["^Rn^vld4Align2^"]" is Rn & vld4Align2 { export Rn; } + +buildVld4DdList2: is counter=0 { } +buildVld4DdList2: vld4DdElement2 is counter=1 & vld4DdElement2 [ counter=0; regNum=regNum+regInc; ] { } +buildVld4DdList2: vld4DdElement2,buildVld4DdList2 is vld4DdElement2 & buildVld4DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=0 & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVld4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVld4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double + + +:vld4.^esize1011 vld4DdList2,vld4RnAligned2 is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003=15) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2 +unimpl + +:vld4.^esize1011 vld4DdList2,vld4RnAligned2^"!" is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003=13) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2 +unimpl + +:vld4.^esize1011 vld4DdList2,vld4RnAligned2,VRm is ( ($(AMODE) & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003 ) ) & esize1011 & VRm & vld4RnAligned2 & vld4DdList2 + unimpl + +####### +# VLD4 (single 4-element structure to all lanes) +# + +vld4Align3: is c0404=0 { } +vld4Align3: "@32" is c0404=1 & c0607=0 { } +vld4Align3: "@64" is c0404=1 & (c0607=1 | c0607=2) { } +vld4Align3: "@128" is c0404=1 & c0607=3 { } + +vld4RnAligned3: "["^Rn^vld4Align3^"]" is Rn & vld4Align3 { export Rn; } + +buildVld4DdList3: is counter=0 { } +buildVld4DdList3: Dreg^"[]" is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVld4DdList3: Dreg^"[]",buildVld4DdList3 is Dreg & buildVld4DdList3 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld4DdList3: "{"^buildVld4DdList3^"}" is c0505=0 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList3: "{"^buildVld4DdList3^"}" is c0505=1 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double + +:vld4.^esize0607 vld4DdList3,vld4RnAligned3 is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=15 & vld4DdList3 unimpl +#thv_2327=0x12 + +:vld4.^esize0607 vld4DdList3,vld4RnAligned3^"!" is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=13 & vld4DdList3 unimpl + +:vld4.^esize0607 vld4DdList3,vld4RnAligned3,VRm is $(AMODE) & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & VRm & vld4DdList3 unimpl + +####### +# VLD4 (multiple 4-element structures) +# + +vld4Align: is TMode=0 & c0405=0 { } +vld4Align: "@64" is TMode=0 & c0405=1 { } +vld4Align: "@128" is TMode=0 & c0405=2 { } +vld4Align: "@256" is TMode=0 & c0405=3 { } +vld4Align: is TMode=1 & thv_c0405=0 { } +vld4Align: "@64" is TMode=1 & thv_c0405=1 { } +vld4Align: "@128" is TMode=1 & thv_c0405=2 { } +vld4Align: "@256" is TMode=1 & thv_c0405=3 { } + +vld4RnAligned: "["^VRn^vld4Align^"]" is VRn & vld4Align { export VRn; } + +buildVld4DdList: is counter=0 { } +buildVld4DdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVld4DdList: Dreg,buildVld4DdList is buildVld4DdList & Dreg [ counter=counter-1; regNum=regNum+regInc; ] { } + +vld4DdList: "{"^buildVld4DdList^"}" is TMode=0 & c0808=0 & D22 & c1215 & buildVld4DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList: "{"^buildVld4DdList^"}" is TMode=0 & c0808=1 & D22 & c1215 & buildVld4DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vld4DdList: "{"^buildVld4DdList^"}" is TMode=1 & thv_c0808=0 & thv_D22 & thv_c1215 & buildVld4DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList: "{"^buildVld4DdList^"}" is TMode=1 & thv_c0808=1 & thv_D22 & thv_c1215 & buildVld4DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double + +:vld4.^esize0607 vld4DdList,vld4RnAligned is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3 & c0003=15 ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 & thv_c0003=15 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList + unimpl + +:vld4.^esize0607 vld4DdList,vld4RnAligned^"!" is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3 & c0003=13 ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 & thv_c0003=13 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList + unimpl + +:vld4.^esize0607 vld4DdList,vld4RnAligned,VRm is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=2 & c0911=0 & c0607<3) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=2 & thv_c0911=0 & thv_c0607<3 ) ) & esize0607 & VRm & vld4RnAligned & vld4DdList + unimpl + + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +####### +# VLDM (A1) +# + +vldmRn: Rn is TMode=0 & Rn & c2121=0 { export Rn; } +vldmRn: Rn^"!" is TMode=0 & Rn & c2121=1 { export Rn; } +vldmRn: thv_Rn is TMode=1 & thv_Rn & thv_c2121=0 { export thv_Rn; } +vldmRn: thv_Rn^"!" is TMode=1 & thv_Rn & thv_c2121=1 { export thv_Rn; } +vldmOffset: value is $(AMODE) & immed [ value= immed << 2; ] { export *[const]:4 value; } +vldmOffset: value is TMode=1 & thv_immed [ value= thv_immed << 2; ] { export *[const]:4 value; } +vldmUpdate: immed is TMode=0 & vldmRn & c2121=0 & immed { } +vldmUpdate: immed is TMode=0 & vldmRn & c2121=1 & immed { vldmRn = vldmRn + (immed << 2); } +vldmUpdate: thv_immed is TMode=1 & vldmRn & thv_c2121=0 & thv_immed { } +vldmUpdate: thv_immed is TMode=1 & vldmRn & thv_c2121=1 & thv_immed { vldmRn = vldmRn + (thv_immed << 2); } + +buildVldmDdList: is counter=0 { } +buildVldmDdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+1; ] +{ + Dreg = *mult_addr; + mult_addr = mult_addr + 8; +} + +buildVldmDdList: Dreg,buildVldmDdList is Dreg & buildVldmDdList [ counter=counter-1; regNum=regNum+1; ] +{ + Dreg = *mult_addr; + mult_addr = mult_addr + 8; + build buildVldmDdList; +} + +vldmDdList: "{"^buildVldmDdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVldmDdList [ regNum=(D22<<4)+c1215 - 1; counter=c0007>>1; ] { } +vldmDdList: "{"^buildVldmDdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVldmDdList [ regNum=(thv_D22<<4)+thv_c1215 - 1; counter=thv_c0007>>1; ] { } + +:vldmia^COND vldmRn,vldmDdList is ( ($(AMODE) & COND & c2327=0x19 & c2121 & c2020=1 & c0811=11 & c0000=0) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0) ) & vldmRn & vldmDdList & vldmOffset & vldmUpdate +{ + mult_addr = vldmRn; + build vldmDdList; + build vldmUpdate; +} + +:vldmdb^COND vldmRn,vldmDdList is ( ($(AMODE) & COND & c2327=0x1a & c2121=1 & c2020=1 & c0811=11 & c0000=0) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0 ) ) & vldmRn & vldmDdList & vldmOffset +{ + local start_addr = vldmRn - vldmOffset; + mult_addr = start_addr; + build vldmDdList; + vldmRn = start_addr; +} + +@endif # VFPv2 | VFPv3 | SIMD + +@if defined(VERSION_8) + +fldmSet1: thv_Dd_1 is TMode=1 & thv_Rn & thv_Dd_1 { thv_Dd_1 = * thv_Rn; } +fldmSet2: thv_Dd_2 is TMode=1 & thv_Rn & thv_Dd_2 & fldmSet1 { build fldmSet1; thv_Dd_2 = *:8 (thv_Rn + 8:4); } +fldmSet3: thv_Dd_3 is TMode=1 & thv_Rn & thv_Dd_3 & fldmSet2 { build fldmSet2; thv_Dd_3 = *:8 (thv_Rn + 16:4); } +fldmSet4: thv_Dd_4 is TMode=1 & thv_Rn & thv_Dd_4 & fldmSet3 { build fldmSet3; thv_Dd_4 = *:8 (thv_Rn + 24:4); } +fldmSet5: thv_Dd_5 is TMode=1 & thv_Rn & thv_Dd_5 & fldmSet4 { build fldmSet4; thv_Dd_5 = *:8 (thv_Rn + 32:4); } +fldmSet6: thv_Dd_6 is TMode=1 & thv_Rn & thv_Dd_6 & fldmSet5 { build fldmSet5; thv_Dd_6 = *:8 (thv_Rn + 40:4); } +fldmSet7: thv_Dd_7 is TMode=1 & thv_Rn & thv_Dd_7 & fldmSet6 { build fldmSet6; thv_Dd_7 = *:8 (thv_Rn + 48:4); } +fldmSet8: thv_Dd_8 is TMode=1 & thv_Rn & thv_Dd_8 & fldmSet7 { build fldmSet7; thv_Dd_8 = *:8 (thv_Rn + 56:4); } +fldmSet9: thv_Dd_9 is TMode=1 & thv_Rn & thv_Dd_9 & fldmSet8 { build fldmSet8; thv_Dd_9 = *:8 (thv_Rn + 64:4); } +fldmSet10: thv_Dd_10 is TMode=1 & thv_Rn & thv_Dd_10 & fldmSet9 { build fldmSet9; thv_Dd_10 = *:8 (thv_Rn + 72:4); } +fldmSet11: thv_Dd_11 is TMode=1 & thv_Rn & thv_Dd_11 & fldmSet10 { build fldmSet10; thv_Dd_11 = *:8 (thv_Rn + 80:4); } +fldmSet12: thv_Dd_12 is TMode=1 & thv_Rn & thv_Dd_12 & fldmSet11 { build fldmSet11; thv_Dd_12 = *:8 (thv_Rn + 88:4); } +fldmSet13: thv_Dd_13 is TMode=1 & thv_Rn & thv_Dd_13 & fldmSet12 { build fldmSet12; thv_Dd_13 = *:8 (thv_Rn + 96:4); } +fldmSet14: thv_Dd_14 is TMode=1 & thv_Rn & thv_Dd_14 & fldmSet13 { build fldmSet13; thv_Dd_14 = *:8 (thv_Rn + 104:4); } +fldmSet15: thv_Dd_15 is TMode=1 & thv_Rn & thv_Dd_15 & fldmSet14 { build fldmSet14; thv_Dd_15 = *:8 (thv_Rn + 112:4); } +fldmSet16: thv_Dd_16 is TMode=1 & thv_Rn & thv_Dd_16 & fldmSet15 { build fldmSet15; thv_Dd_16 = *:8 (thv_Rn + 120:4); } + +fldmSet: "{"^thv_Dd_1^"}" is TMode=1 & thv_Dd_1 & thv_c0007=3 & fldmSet1 { build fldmSet1; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet2^"}" is TMode=1 & thv_Dd_1 & thv_c0007=5 & fldmSet2 { build fldmSet2; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet3^"}" is TMode=1 & thv_Dd_1 & thv_c0007=7 & fldmSet3 { build fldmSet3; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet4^"}" is TMode=1 & thv_Dd_1 & thv_c0007=9 & fldmSet4 { build fldmSet4; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet5^"}" is TMode=1 & thv_Dd_1 & thv_c0007=11 & fldmSet5 { build fldmSet5; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet6^"}" is TMode=1 & thv_Dd_1 & thv_c0007=13 & fldmSet6 { build fldmSet6; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet7^"}" is TMode=1 & thv_Dd_1 & thv_c0007=15 & fldmSet7 { build fldmSet7; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet8^"}" is TMode=1 & thv_Dd_1 & thv_c0007=17 & fldmSet8 { build fldmSet8; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet9^"}" is TMode=1 & thv_Dd_1 & thv_c0007=19 & fldmSet9 { build fldmSet9; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet10^"}" is TMode=1 & thv_Dd_1 & thv_c0007=21 & fldmSet10 { build fldmSet10; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet11^"}" is TMode=1 & thv_Dd_1 & thv_c0007=23 & fldmSet11 { build fldmSet11; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet12^"}" is TMode=1 & thv_Dd_1 & thv_c0007=25 & fldmSet12 { build fldmSet12; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet13^"}" is TMode=1 & thv_Dd_1 & thv_c0007=27 & fldmSet13 { build fldmSet13; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet14^"}" is TMode=1 & thv_Dd_1 & thv_c0007=29 & fldmSet14 { build fldmSet14; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet15^"}" is TMode=1 & thv_Dd_1 & thv_c0007=31 & fldmSet15 { build fldmSet15; } +fldmSet: "{"^thv_Dd_1^"-"^fldmSet16^"}" is TMode=1 & thv_Dd_1 & thv_c0007=33 & fldmSet16 { build fldmSet16; } + +fldmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=1 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn + (4 * thv_c0007:4); } +fldmWback: thv_Rn^"!" is thv_bit21=1 & thv_bit23=0 & thv_c0007 & thv_Rn { thv_Rn = thv_Rn - (4 * thv_c0007:4); } +fldmWback: thv_Rn is thv_bit21=0 & thv_Rn { } + +:fldmdbx^ItCond fldmWback, fldmSet is TMode=1 & ItCond & thv_c2331=0b111011010 & thv_bit21=1 & thv_bit20=1 & thv_c0811=0b1011 & fldmWback & fldmSet +{ + build fldmWback; + build fldmSet; +} + +:fldmiax^ItCond fldmWback, fldmSet is TMode=1 & ItCond & thv_c2331=0b111011001 & thv_bit20=1 & thv_c0811=0b1011 & fldmWback & fldmSet +{ + build fldmSet; + build fldmWback; +} + +@endif + +@if defined(VFPv2) || defined(VFPv3) + +####### +# VLDM (A2) +# + +buildVldmSdList: is counter=0 { } +buildVldmSdList: Sreg is counter=1 & Sreg [ counter=0; regNum=regNum+1; ] +{ + Sreg = *mult_addr; + mult_addr = mult_addr + 4; +} +buildVldmSdList: Sreg,buildVldmSdList is Sreg & buildVldmSdList [ counter=counter-1; regNum=regNum+1; ] +{ + Sreg = *mult_addr; + mult_addr = mult_addr + 4; + build buildVldmSdList; +} + +vldmSdList: "{"^buildVldmSdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVldmSdList [ regNum=(c1215<<1) + D22 - 1; counter=c0007; ] { } +vldmSdList: "{"^buildVldmSdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVldmSdList [ regNum=(thv_c1215<<1) + thv_D22 - 1; counter=thv_c0007; ] { } + +:vldmia^COND vldmRn,vldmSdList is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x19 & c2121 & c2020=1 & c0811=10 ) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=1 & thv_c0811=10 ) ) & vldmRn & vldmSdList & vldmOffset & vldmUpdate +{ + mult_addr = vldmRn; + build vldmSdList; + build vldmUpdate; +} + +:vldmdb^COND vldmRn,vldmSdList is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x1a & c2121=1 & c2020=1 & c0811=10 ) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=1 & thv_c0811=10 ) ) & vldmRn & vldmSdList & vldmOffset +{ + local start_addr = vldmRn - vldmOffset; + mult_addr = start_addr; + build vldmSdList; + vldmRn = start_addr; +} + +####### +# VLDR +# + +vldrRn: "["^Rn^"]" is TMode=0 & Rn & immed=0 & c2323=0 { ptr:4 = Rn; export ptr; } +vldrRn: "["^Rn^"]" is TMode=0 & Rn & immed=0 & c2323=1 { ptr:4 = Rn; export ptr; } +vldrRn: "["^Rn^",#-"^vldrImm^"]" is TMode=0 & Rn & immed & c2323=0 [ vldrImm = immed * 4; ] { ptr:4 = Rn - vldrImm; export ptr; } +vldrRn: "["^Rn^",#"^vldrImm^"]" is TMode=0 & Rn & immed & c2323=1 [ vldrImm = immed * 4; ] { ptr:4 = Rn + vldrImm; export ptr; } +vldrRn: "["^pc^",#-"^vldrImm^"]" is TMode=0 & Rn=15 & pc & immed & c2323=0 [ vldrImm = immed * 4; ] { ptr:4 = ((inst_start + 8) & 0xfffffffc) - vldrImm; export ptr; } +vldrRn: "["^pc^",#"^vldrImm^"]" is TMode=0 & Rn=15 & pc & immed & c2323=1 [ vldrImm = immed * 4; ] { ptr:4 = ((inst_start + 8) & 0xfffffffc) + vldrImm; export ptr; } +vldrRn: "["^VRn^"]" is TMode=1 & VRn & thv_immed=0 & thv_c2323=0 { ptr:4 = VRn; export ptr; } +vldrRn: "["^VRn^"]" is TMode=1 & VRn & thv_immed=0 & thv_c2323=1 { ptr:4 = VRn; export ptr; } +vldrRn: "["^VRn^",#-"^vldrImm^"]" is TMode=1 & VRn & thv_immed & thv_c2323=0 [ vldrImm = thv_immed * 4; ] { ptr:4 = VRn - vldrImm; export ptr; } +vldrRn: "["^VRn^",#"^vldrImm^"]" is TMode=1 & VRn & thv_immed & thv_c2323=1 [ vldrImm = thv_immed * 4; ] { ptr:4 = VRn + vldrImm; export ptr; } +vldrRn: "["^pc^",#-"^vldrImm^"]" is TMode=1 & thv_Rn=15 & pc & thv_immed & thv_c2323=0 [ vldrImm = thv_immed * 4; ] { ptr:4 = ((inst_start + 4) & 0xfffffffc) - vldrImm; export ptr; } +vldrRn: "["^pc^",#"^vldrImm^"]" is TMode=1 & thv_Rn=15 & pc & thv_immed & thv_c2323=1 [ vldrImm = thv_immed * 4; ] { ptr:4 = ((inst_start + 4) & 0xfffffffc) + vldrImm; export ptr; } + +:vldr^COND^".64" Dd,vldrRn is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=1 & c0811=11) | ($(TMODE_E) & thv_c2427=13 & thv_c2021=1 & thv_c0811=11)) & Dd & vldrRn +{ + Dd = *:8 vldrRn; +} + +:vldr^COND^".32" Sd,vldrRn is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=1 & c0811=10) | ($(TMODE_E) & thv_c2427=13 & thv_c2021=1 & thv_c0811=10)) & Sd & vldrRn +{ + Sd = *:4 vldrRn; +} + +@endif # VFPv2 | VFPv3 + +define pcodeop VectorMin; +define pcodeop VectorMax; +define pcodeop FloatVectorMin; +define pcodeop FloatVectorMax; +define pcodeop VectorMultiplyAccumulate; +define pcodeop VectorMultiplySubtract; +define pcodeop VectorMultiplySubtractLong; +define pcodeop VectorDoubleMultiplyHighHalf; +define pcodeop VectorRoundDoubleMultiplyHighHalf; +define pcodeop VectorDoubleMultiplyLong; +define pcodeop VectorDoubleMultiplyAccumulateLong; +define pcodeop VectorDoubleMultiplySubtractLong; +define pcodeop FloatVectorMultiplyAccumulate; +define pcodeop FloatVectorMultiplySubtract; +define pcodeop VectorGetElement; + +@if defined(SIMD) + +:vmax.^udt^esize2021 Dd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=0 & c0404=0 ) | + ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=0 & thv_c0404=0 ) ) & esize2021 & udt & Dm & Dn & Dd +{ + Dd = VectorMax(Dn,Dm,esize2021,udt); +} + +:vmax.^udt^esize2021 Qd, Qn, Qm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=1 & c0404=0 ) | + ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & udt & Qm & Qn & Qd +{ + Qd = VectorMax(Qn,Qm,esize2021,udt); +} + +:vmax.f32 Dd,Dn,Dm is (($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=15 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0)) & Dm & Dn & Dd +{ + Dd = FloatVectorMax(Dn,Dm,2:4,32:1); +} + +:vmax.f32 Qd,Qn,Qm is (($(AMODE) & cond=15 & c2327=4 & c2021=0 & c0811=15 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=15 & thv_Q6=1 & thv_c0404=0)) & Qm & Qn & Qd +{ + Qd = FloatVectorMax(Qn,Qm,2:4,32:1); +} + +:vmin.^udt^esize2021 Dd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=0 & c0404=1 ) | + ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=0 & thv_c0404=1 ) ) & esize2021 & udt & Dm & Dn & Dd + +{ + Dd = VectorMin(Dn,Dm,esize2021,udt); +} + +:vmin.^udt^esize2021 Qd, Qn, Qm is ( ( $(AMODE) & cond=15 & c2527=1 & c2323=0 & c2021<3 & c0811=6 & Q6=1 & c0404=1 ) | + ( $(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c2021<3 & thv_c0811=6 & thv_Q6=1 & thv_c0404=1 ) ) & esize2021 & udt & Qm & Qn & Qd + +{ + Qd = VectorMin(Qn,Qm,esize2021,udt); +} + +:vmin.f32 Dd,Dn,Dm is (($(AMODE) & cond=15 & c2327=4 & c2021=2 & c0811=15 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=15 & thv_Q6=0 & thv_c0404=0)) & Dm & Dn & Dd +{ + Dd = FloatVectorMin(Dn,Dm,2:4,32:1); +} + +:vmin.f32 Qd,Qn,Qm is (($(AMODE) & cond=15 & c2327=4 & c2021=2 & c0811=15 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=15 & thv_Q6=1 & thv_c0404=0)) & Qm & Qn & Qd +{ + Qd = FloatVectorMin(Qn,Qm,2:4,32:1); +} + +:vmla.i^esize2021 Dd,Dn,Dm is ( ( $(AMODE) & cond=15 & c2327=4 & c2021<3 & c0811=9 & Q6=0 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dm & Dn & Dd +{ + Dd = VectorMultiplyAccumulate(Dn,Dm,esize2021,0:1); +} + +:vmla.i^esize2021 Qd,Qn,Qm is ( ( $(AMODE) & cond=15 & c2327=4 & c2021<3 & c0811=9 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=1 & thv_c0404=0)) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorMultiplyAccumulate(Qn,Qm,esize2021,0:1); +} + +:vmls.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2424=1 & c2021<3 & c0811=9 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dm & Dn & Dd +{ + Dd = VectorMultiplySubtract(Dn,Dm,esize2021,0:1); +} + +:vmls.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2424=1 & c2021<3 & c0811=9 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021<3 & thv_c0811=9 & thv_Q6=1 & thv_c0404=0)) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorMultiplySubtract(Qn,Qm,esize2021,0:1); +} + +:vmlal.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=8 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=8 & thv_Q6=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021 +{ + Qd = VectorMultiplyAccumulate(Dn,Dm,esize2021,udt); +} + +:vmlsl.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=10 & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=10 & thv_Q6=0 & thv_c0404=0 ) ) & Dm & Dn & Qd & udt & esize2021 +{ + Qd = VectorMultiplySubtractLong(Dn,Dm,esize2021,udt); +} + +:vmla.f^fesize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=0 & c0811=13 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_c0606=0 & thv_c0404=1)) & fesize2021 & Dn & Dd & Dm +{ + Dd = FloatVectorMultiplyAccumulate(Dn,Dm,fesize2021,8:1); +} + +:vmla.f^fesize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=0 & c0811=13 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_c0606=1 & thv_c0404=1)) & fesize2021 & Qn & Qd & Qm +{ + Qd = FloatVectorMultiplyAccumulate(Qn,Qm,fesize2021,16:1); +} + +:vmls.f^fesize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_c0606=0 & thv_c0404=1)) & fesize2021 & Dn & Dd & Dm +{ + Dd = FloatVectorMultiplySubtract(Dn,Dm,fesize2021,8:1); +} + +:vmls.f^fesize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_c0606=1 & thv_c0404=1)) & fesize2021 & Qn & Qd & Qm +{ + Qd = FloatVectorMultiplySubtract(Qn,Qm,fesize2021,16:1); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +:vmla^COND^".f32" Sd,Sn,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=0 & c0811=10 & c0606=0 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=0 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0)) & Sm & Sn & Sd +{ + Sd = Sd f+ (Sn f* Sm); +} + +:vmla^COND^".f64" Dd,Dn,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=0 & c0811=11 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=0 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0)) & Dm & Dn & Dd +{ + Dd = Dd f+ (Dn f* Dm); +} + +:vmls^COND^".f32" Sd,Sn,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=0 & c0811=10 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=0 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0)) & Sm & Sn & Sd +{ + Sd = Sd f- (Sn f* Sm); +} + +:vmls^COND^".f64" Dd,Dn,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2021=0 & c0811=11 & c0606=1 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=0 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0)) & Dm & Dn & Dd +{ + Dd = Dd f- (Dn f* Dm); +} + +@endif # VFPv2 || VFPv3 + +@if defined(SIMD) + +##### +# VML* (by scalar) (A1) +# + +vmlDm: Dm_3^"["^index^"]" is TMode=0 & c2021=1 & Dm_3 & M5 & c0303 [ index = (M5 << 1) + c0303; ] { el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; } +vmlDm: Dm_4^"["^M5^"]" is TMode=0 & c2021=2 & Dm_4 & M5 { el:4 = VectorGetElement(Dm_4, M5:1, 4:1, 0:1); export el; } +vmlDm: thv_Dm_3^"["^index^"]" is TMode=1 & thv_c2021=1 & thv_Dm_3 & thv_M5 & thv_c0303 [ index = (thv_M5 << 1) + thv_c0303; ] { el:4 = VectorGetElement(thv_Dm_3, index:1, 2:1, 0:1); export el; } +vmlDm: thv_Dm_4^"["^thv_M5^"]" is TMode=1 & thv_c2021=2 & thv_Dm_4 & thv_M5 { el:4 = VectorGetElement(thv_Dm_4, thv_M5:1, 4:1, 0:1); export el; } + + +:vmla.i^esize2021 Dd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2) & c0811=0 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Dn & Dd & vmlDm +{ + Dd = VectorMultiplyAccumulate(Dn,vmlDm,esize2021); +} + +:vmla.i^esize2021 Qd,Qn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Qn & Qd & vmlDm +{ + Qd = VectorMultiplyAccumulate(Qn,vmlDm,esize2021); +} + +:vmla.f32 Dd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & c0811=1 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=1 & thv_c0606=1 & thv_c0404=0)) & Dn & Dd & vmlDm +{ + Dd = FloatVectorMultiplyAccumulate(Dn,vmlDm,2:4,32:1); +} + +:vmla.f32 Qd,Qn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2021=2 & c0811=1 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=1 & thv_c0606=1 & thv_c0404=0)) & Qn & Qd & vmlDm +{ + Qd = FloatVectorMultiplyAccumulate(Qn,vmlDm,2:4,32:1); +} + +:vmls.i^esize2021 Dd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2) & c0811=4 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=4 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Dn & Dd & vmlDm +{ + Dd = VectorMultiplySubtract(Dn,vmlDm,esize2021); +} + +:vmls.i^esize2021 Qd,Qn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2)& c0811=4 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=4 & thv_c0606=1 & thv_c0404=0)) & esize2021 & Qn & Qd & vmlDm +{ + Qd = VectorMultiplySubtract(Qn,vmlDm,esize2021); +} + +:vmls.f32 Dd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & c0811=5 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=5 & thv_c0606=1 & thv_c0404=0)) & Dn & Dd & vmlDm +{ + Dd = FloatVectorMultiplySubtract(Dn,vmlDm,2:4,32:1); +} + +:vmls.f32 Qd,Qn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c2021=2 & c0811=5 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=5 & thv_c0606=1 & thv_c0404=0)) & Qn & Qd & vmlDm +{ + Qd = FloatVectorMultiplySubtract(Qn,vmlDm,2:4,32:1); +} + +##### +# VML* (by scalar) (A2) +# + + + +:vmlal.^udt^esize2021 Qd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=2 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=2 & thv_Q6=1 & thv_c0404=0 ) ) & udt & esize2021 & Dn & Qd & vmlDm +{ + Qd = VectorMultiplyAccumulate(Dn,vmlDm,esize2021,udt); +} + +:vmlsl.^udt^esize2021 Qd,Dn,vmlDm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=6 & Q6=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=6 & thv_Q6=1 & thv_c0404=0 ) ) & udt & esize2021 & Dn & Qd & vmlDm +{ + Qd = VectorMultiplySubtract(Dn,vmlDm,esize2021,udt); +} + +:vmov.^simdExpImmDT Dd,simdExpImm_8 is (( $(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c0707=0 & Q6=0 & c0404=1 ) | + ( $(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c0707=0 & thv_Q6=0 & thv_c0404=1 )) & Dd & simdExpImmDT & simdExpImm_8 +{ + Dd = simdExpImm_8; +} + +:vmov.^simdExpImmDT Qd,simdExpImm_16 is (( $(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c0707=0 & Q6=1 & c0404=1 ) | + ( $(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c0707=0 & thv_Q6=1 & thv_c0404=1 )) & Qd & simdExpImmDT & simdExpImm_16 +{ + Qd = simdExpImm_16; +} + +@endif # SIMD + +@if defined(VFPv3) + +:vmov^COND^".f32" Sd,vfpExpImm_4 is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c0411=0xa0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0xa0 ) ) & Sd & vfpExpImm_4 +{ + Sd = vfpExpImm_4; +} + +:vmov^COND^".f64" Dd,vfpExpImm_8 is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2021=3 & c0411=0xb0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c0411=0xb0 ) ) & Dd & vfpExpImm_8 +{ + Dd = vfpExpImm_8; +} + +@endif # VFPv3 + +@if defined(SIMD) + +:vmov Dd,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=2 & c1619=c0003 & c0811=1 & c0707=c0505 & Q6=0 & c0404=1 ) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c1619=thv_c0003 & thv_c0811=1 & thv_c0707=thv_c0505 & thv_c0606=0 & thv_c0404=1) ) & Dd & Dm +{ + Dd = Dm; +} + +:vmov Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=4 & c2021=2 & c1619=c0003 & c0811=1 & c0707=c0505 & Q6=1 & c0404=1 ) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c1619=thv_c0003 & thv_c0811=1 & thv_c0707=thv_c0505 & thv_c0606=1 & thv_c0404=1) ) & Qd & Qm +{ + Qd = Qm; +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +:vmov^COND^".f32" Sd,Sm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x30 & c0611=0x29 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x29 & thv_c0404=0) ) & Sd & Sm +{ + Sd = Sm; +} + +:vmov^COND^".f64" Dd,Dm is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1d & c1621=0x30 & c0611=0x2d & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x30 & thv_c0611=0x2d & thv_c0404=0) ) & Dd & Dm +{ + Dd = Dm; +} + +@endif # VFPv2 || VFPv3 + +define pcodeop VectorSetElement; + +@if defined(SIMD) + +vmovSize: 8 is TMode=0 & c2222=1 { export 1:1; } +vmovSize: 16 is TMode=0 & c2222=0 & c0505=1 { export 2:1; } +vmovSize: 8 is TMode=1 & thv_c2222=1 { export 1:1; } +vmovSize: 16 is TMode=1 & thv_c2222=0 & thv_c0505=1 { export 2:1; } + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +vmovSize: 32 is TMode=0 & c2222=0 & c0506=0 { export 4:1; } +vmovSize: 32 is TMode=1 & thv_c2222=0 & thv_c0506=0 { export 4:1; } + +@endif # VFPv2 || VFPv3 || SIMD + +vmovIndex: val is TMode=0 & c2222=1 & c2121 & c0506 [ val = (c2121 << 2) + c0506; ] { tmp:1 = val; export tmp; } +vmovIndex: val is TMode=0 & c2222=0 & c2121 & c0606 & c0505=1 [ val = (c2121 << 1) + c0606; ] { tmp:1 = val; export tmp; } + +vmovIndex: val is TMode=1 & thv_c2222=1 & thv_c2121 & thv_c0506 [ val = (thv_c2121 << 2) + thv_c0506; ] { tmp:1 = val; export tmp; } +vmovIndex: val is TMode=1 & thv_c2222=0 & thv_c2121 & thv_c0606 & thv_c0505=1 [ val = (thv_c2121 << 1) + thv_c0606; ] { tmp:1 = val; export tmp; } + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +vmovIndex: c2121 is TMode=0 & c2222=0 & c2121 & c0606=0 & c0506=0 { tmp:1 = c2121; export tmp; } +vmovIndex: thv_c2121 is TMode=1 & thv_c2222=0 & thv_c2121 & thv_c0606=0 & thv_c0506=0 { tmp:1 = thv_c2121; export tmp; } + +@endif # VFPv2 || VFPv3 || SIMD + + +dNvmovIndex: Dn^"["^vmovIndex^"]" is Dn & vmovIndex { } + + +:vmov^COND^"."^vmovSize dNvmovIndex,VRd is ( ($(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2020=0 & c0811=11 & c0404=1 & c0003=0 ) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2020=0 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex +{ + VectorSetElement(VRd,Dn,vmovIndex,vmovSize); +} + +:vmov^COND^".u"^vmovSize VRd,dNvmovIndex is ( ($(AMODE) & COND & ARMcond=1 & c2327=0x1d & c2020=1 & c0811=11 & c0404=1 & c0003=0 ) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex +{ + VRd = VectorGetElement(Dn,vmovIndex,vmovSize,0:1); +} + +:vmov^COND^".s"^vmovSize VRd,dNvmovIndex is ( ( $(AMODE) & COND & ARMcond=1 & c2327=0x1c & c2020=1 & c0811=11 & c0404=1 & c0003=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2020=1 & thv_c0811=11 & thv_c0404=1 & thv_c0003=0 ) ) & Dn & VRd & vmovSize & vmovIndex & dNvmovIndex +{ + VRd = VectorGetElement(Dn,vmovIndex,vmovSize,1:1); +} + +@endif # SIMD + + +@if defined(VFPv2) || defined(VFPv3) + +:vmov^COND Sn,VRd is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2122=0 & c2020=0 & c0811=10 & c0006=0x10) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2122=0 & thv_c2020=0 & thv_c0811=10 & thv_c0006=0x10) ) & Sn & VRd +{ + Sn = VRd; +} + +:vmov^COND VRd,Sn is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2122=0 & c2020=1 & c0811=10 & c0006=0x10) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2122=0 & thv_c2020=1 & thv_c0811=10 & thv_c0006=0x10) ) & Sn & VRd +{ + VRd = Sn; +} + +:vmov^COND Sm,SmNext,VRd,VRn is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc4 & c0611=0x28 & c0404=1) | + ($(TMODE_E) & thv_c2027=0xc4 & thv_c0611=0x28 & thv_c0404=1) ) & VRn & VRd & Sm & SmNext +{ + Sm = VRd; + SmNext = VRn; +} + +:vmov^COND VRd,VRn,Sm,SmNext is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc5 & c0611=0x28 & c0404=1) | + ($(TMODE_E) & thv_c2027=0xc5 & thv_c0611=0x28 & thv_c0404=1) ) & VRn & VRd & Sm & SmNext +{ + VRd = Sm; + VRn = SmNext; +} + +@endif # VFPv2 || VFPv3 + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +:vmov^COND Dm,VRd,VRn is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc4 & c0611=0x2c & c0404=1) | ($(TMODE_E) & thv_c2027=0xc4 & thv_c0611=0x2c & thv_c0404=1) ) & Dm & VRn & VRd +{ + Dm = (zext(VRn) << 32) + zext(VRd); +} + +:vmov^COND VRd,VRn,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2027=0xc5 & c0611=0x2c & c0404=1) | ($(TMODE_E) & thv_c2027=0xc5 & thv_c0611=0x2c & thv_c0404=1) ) & Dm & VRn & VRd +{ + VRn = Dm(4); + VRd = Dm:4; +} + +@endif # VFPv2 || VFPv3 || SIMD + +define pcodeop VectorCopyLong; +define pcodeop VectorCopyNarrow; + +@if defined(SIMD) + +:vmovl.^udt^esize2021 Qd,Dm is $(AMODE) & cond=15 & c2527=1 & udt & c2323=1 & (c1921=1 | c1921=2 | c1921=4) & esize2021 & c1618=0 & Qd & c0611=0x28 & c0404=1 & Dm +{ + Qd = VectorCopyLong(Dm,esize2021,udt); +} + +:vmovn.i^esize1819x2 Dd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0611=8 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0611=8 & thv_c0404=0) ) & esize1819x2 & Dd & Qm +{ + Dd = VectorCopyNarrow(Qm,esize1819x2); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +:vmrs^COND VRd,fpscr is COND & ( ($(AMODE) & ARMcond=1 & c1627=0xef1 & c0011=0xa10) | ($(TMODE_E) & thv_c1627=0xef1 & thv_c0011=0xa10)) & fpscr & VRd +{ + VRd = fpscr; +} + +apsr: "apsr" is epsilon {} + +:vmrs^COND apsr,fpscr is COND & apsr & ( ($(AMODE) & ARMcond=1 & c1627=0xef1 & c1215=15 & c0011=0xa10) | ($(TMODE_E) & thv_c1627=0xef1 & thv_c1215=15 & thv_c0011=0xa10) ) & fpscr +{ + NG = $(FPSCR_N); + ZR = $(FPSCR_Z); + CY = $(FPSCR_C); + OV = $(FPSCR_V); +} + +:vmsr^COND fpscr,VRd is COND & ( ($(AMODE) & ARMcond=1 & c1627=0xee1 & c0011=0xa10) | ($(TMODE_E) & thv_c1627=0xee1 & thv_c0011=0xa10) ) & VRd & fpscr +{ + fpscr = VRd; +} + +@endif # VFPv2 || VFPv3 || SIMD + +@if defined(SIMD) + +### +# VMUL (floating Point) +# + +define pcodeop FloatVectorMult; +define pcodeop VectorMultiply; +define pcodeop PolynomialMultiply; + +:vmul.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=0x06 & c2121=0 & c2020=0 & c0811=13 & Q6=0 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm +{ + Dd = FloatVectorMult(Dn,Dm,2:1,32:1); +} + +:vmul.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=0x06 & c2121=0 & c2020=0 & c0811=13 & Q6=1 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c0811=13 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd +{ + Qd = FloatVectorMult(Qn,Qm,2:1,32:1); +} + +:vmul.f16 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=0x06 & c2121=0 & c2020=1 & c0811=13 & Q6=0 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c2020=1 & thv_c0811=13 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm +{ + Dd = FloatVectorMult(Dn,Dm,4:1,16:1); +} + +:vmul.f16 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=0x06 & c2121=0 & c2020=1 & c0811=13 & Q6=1 & c0404=1) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c2121=0 & thv_c2020=1 & thv_c0811=13 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd +{ + Qd = FloatVectorMult(Qn,Qm,4:1,16:1); +} + +:vmul^COND^".f64" Dd,Dn,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=2 & c0811=11 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + Dd = Dn f* Dm; +} + +:vmul^COND^".f32" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=2 & c0811=10 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & Sm & Sn & Sd +{ + Sd = Sn f* Sm; +} + +:vmul^COND^".f16" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=2 & c0811=9 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:2 = Sn:2 f* Sm:2; + Sd = zext(product); +} + +:vmul.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=9 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=9 & thv_Q6=0 & thv_c0404=1)) & esize2021 & Dn & Dd & Dm +{ + Dd = VectorMultiply(Dn,Dm,esize2021); +} + +:vmul.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=9 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=9 & thv_Q6=1 & thv_c0404=1)) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorMultiply(Qn,Qm,esize2021); +} + +:vmul.p8 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=0 & c0811=9 & Q6=0 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=9 & thv_Q6=0 & thv_c0404=1) ) & Dn & Dd & Dm +{ + Dd = PolynomialMultiply(Dn,Dm,1:1); +} + +:vmul.p8 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c2021=0 & c0811=9 & Q6=1 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=9 & thv_Q6=1 & thv_c0404=1) ) & Qm & Qn & Qd +{ + Qd = PolynomialMultiply(Qn,Qm,1:1); +} + +:vmull.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=0xc & Q6=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=0xc & thv_Q6=0 & thv_c0404=0) ) & esize2021 & Dm & Dn & Qd & udt +{ + Qd = VectorMultiply(Dn,Dm,esize2021,udt); +} + +:vmull.p8 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=0 & c0811=0xe & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=0 & thv_c0811=0xe & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Qd +{ + Qd = PolynomialMultiply(Dn,Dm,1:1); +} + +:vmull.p64 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & c2021=2 & c0811=0xe & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c2021=2 & thv_c0811=0xe & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Qd +{ + Qd = PolynomialMultiply(Dn,Dm,8:1); +} + +etype: "I" is TMode=0 & c0909=0 & c0808=0 {} +etype: "F" is TMode=0 & c0909=0 & c0808=1 {} +etype: "S" is TMode=0 & c0909=1 & c2424=0 {} +etype: "U" is TMode=0 & c0909=1 & c2424=1 {} +etype: "I" is TMode=1 & thv_c0909=0 & thv_c0808=0 {} +etype: "F" is TMode=1 & thv_c0909=0 & thv_c0808=1 {} +etype: "S" is TMode=1 & thv_c0909=1 & thv_c2828=0 {} +etype: "U" is TMode=1 & thv_c0909=1 & thv_c2828=1 {} + +vmlDmA: Dm_3^"["^index^"]" is TMode=0 & c2021=1 & Dm_3 & M5 & c0303 [ index = (M5 << 1) + c0303; ] { el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; } +vmlDmA: Dm_4^"["^M5^"]" is TMode=0 & c2021=2 & Dm_4 & M5 { el:4 = VectorGetElement(Dm_4, M5:1, 4:1, 0:1); export el; } +vmlDmA: Dm_3^"["^index^"]" is TMode=1 & thv_c2021=1 & Dm_3 & thv_M5 & c0303 [ index = (thv_M5 << 1) + c0303; ] { el:4 = VectorGetElement(Dm_3, index:1, 2:1, 0:1); export el; } +vmlDmA: Dm_4^"["^thv_M5^"]" is TMode=1 & thv_c2021=2 & Dm_4 & thv_M5 { el:4 = VectorGetElement(Dm_4, thv_M5:1, 4:1, 0:1); export el; } + +:vmul.^etype^esize2021 Qd,Qn,vmlDmA is ( ($(AMODE) & cond=15 & c2424=1 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0911=4 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2828=1 & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0911=4 & thv_c0606=1 & thv_c0404=0 ) ) & etype & esize2021 & Qn & Qd & vmlDmA +{ + Qd = VectorMultiply(Qn,vmlDmA,esize2021); +} + +:vmul.^etype^esize2021 Dd,Dn,vmlDmA is ( ($(AMODE) & cond=15 & c2424=0 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0911=4 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2828=0 & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0911=4 & thv_c0606=1 & thv_c0404=0 ) ) & etype & esize2021 & Dn & Dd & vmlDmA +{ + Dd = VectorMultiply(Dn,vmlDmA,esize2021); +} + +:vmull.^etype^esize2021 Qd,Dn,vmlDmA is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=10 & c0606=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=10 & thv_c0606=1 & thv_c0404=0 ) ) & Dd & Dm & esize1819 & etype & esize2021 & Dn & Qd & vmlDmA +{ + Qd = VectorMultiply(Dn,vmlDmA,esize2021); +} + +:vmvn Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1619=0 & c0811=5 & c0707=1 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0811=5 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0) ) & Dd & Dm +{ + Dd = ~Dm; +} + +:vmvn Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1619=0 & c0811=5 & c0707=1 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0 & thv_c0811=5 & thv_c0707=1 & thv_Q6=1 & thv_c0404=0) ) & Qd & Qm +{ + tmp1:8 = Qm:8; + tmp2:8 = Qm(8); + tmp1 = ~ tmp1; + tmp2 = ~ tmp2; + Qd = (zext(tmp1) << 8) | zext(tmp2); +} + +@endif # SIMD + + + +define pcodeop FloatVectorNeg; + +@if defined(SIMD) + +:vneg.s^esize1819 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=7 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=7 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819 +{ + Dd = FloatVectorNeg(Dm,esize1819); +} + +:vneg.s^esize1819 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=1 & c0711=7 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=1 & thv_c0711=7 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819 +{ + Qd = FloatVectorNeg(Qm,esize1819); +} + + +:vneg.f32 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=0xf & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=0xf & thv_c0606=0 & thv_c0404=0 ) ) & Dm & Dd +{ + Dd = FloatVectorNeg(Dm,2:1,32:1); +} + +:vneg.f32 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819=2 & c1617=1 & c0711=0xf & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819=2 & thv_c1617=1 & thv_c0711=0xf & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm +{ + Qd = FloatVectorNeg(Qm,2:1,32:1); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + + +:vnmla^COND^".f64" Dd,Dn,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=1 & c0811=11 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dn & Dd +{ + product:8 = Dn f* Dm; + Dd = (0 f- Dd) f+ (0 f- product); +} + +:vnmla^COND^".f32" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=1 & c0811=10 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:4 = Sn f* Sm; + Sd = (0 f- Sd) f+ (0 f- product); +} + +:vnmla.f16 Sd,Sn,Sm is ( ($(AMODE) & cond=0xe & c2327=0x1c & c2021=1 & c0811=9 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=9 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:2 = Sn:2 f* Sm:2; + product = (0:2 f- Sd:2) f+ (0:2 f- product); + Sd = zext(product); +} + +:vnmls^COND^".f64" Dd,Dn,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=1 & c0811=11 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=11 & thv_c0606=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + product:8 = Dn f* Dm; + Dd = product f- Dd; +} + +:vnmls^COND^".f32" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=1 & c0811=10 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=10 & thv_c0606=0 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:4 = Sn f* Sm; + Sd = product f- Sd; +} + +:vnmls.f16 Sd,Sn,Sm is ( ($(AMODE) & cond=0xe & c2327=0x1c & c2021=1 & c0811=9 & c0606=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=1 & thv_c0811=9 & thv_c0606=0 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:2 = Sn:2 f* Sm:2; + product = product f- Sd:2; + Sd = zext(product); +} + +:vnmul^COND^".f64" Dd,Dn,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=2 & c0811=11 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dn & Dd +{ + product:8 = Dn f* Dm; + Dd = 0 f- product; +} + +:vnmul^COND^".f32" Sd,Sn,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=2 & c0811=10 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:4 = Sn f* Sm; + Sd = 0 f- product; +} + +:vnmul.f16 Sd,Sn,Sm is ( ($(AMODE) & cond=0xe & c2327=0x1c & c2021=2 & c0811=9 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=2 & thv_c0811=9 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd +{ + product:2 = Sn:2 f* Sm:2; + product = 0 f- product; + Sd = zext(product); +} + +:vneg^COND^".f32" Sd,Sm is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x1d & c1621=0x31 & c0611=0x29 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x29 & thv_c0404=0 ) ) & Sm & Sd +{ + build COND; + build Sd; + build Sm; + Sd = 0 f- Sm; +} + +:vneg^COND^".f64" Dd,Dm is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x1d & c1621=0x31 & c0611=0x2d & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1d & thv_c1621=0x31 & thv_c0611=0x2d & thv_c0404=0 ) ) & Dd & Dm +{ + build COND; + build Dd; + build Dm; + Dd = 0 f- Dm; +} + +@endif # VFPv2 || VFPv3 + +@if defined(SIMD) + +#F6.1.141 VORR (register) 64-bit SIMD vector variant (A1 and T1) +:vorr Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=2 & c0811=1 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm + +{ + Dd = Dn | Dm; +} + +#F6.1.141 VORR (register) 128-bit SIMD vector variant (A1 and T1) +:vorr Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=2 & c0811=1 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm +{ + Qd = Qn | Qm; +} + +#F6.1.140 VORR and F6.1.138 VORN (immediate) 64-bit SIMD vector variant +:vorr Dd,simdExpImm_8 is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c1011<3 & c0808=1 & c0407=1 ) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=1) ) & Dd & simdExpImm_8 +{ + Dd = Dd | simdExpImm_8; +} + +#F6.1.140 VORR and F6.1.138 VORN (immediate) 128-bit SIMD vector variant +:vorr Qd,simdExpImm_16 is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1921=0 & c1011<3 & c0808=1 & c0407=5 ) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1921=0 & thv_c1011<3 & thv_c0808=1 & thv_c0407=5) ) & Qd & simdExpImm_16 +{ + Qd = Qd | simdExpImm_16; +} + +#F6.1.139 VORN (register) 64-bit SIMD vector variant (A1 and T1) +:vorn Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=3 & c0811=1 & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=0 & thv_c0404=1)) & Dn & Dd & Dm + +{ + Dd = Dn | ~Dm; +} + +#F6.1.139 VORN (register) 128-bit SIMD vector variant (A1 and T1) +:vorn Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2021=3 & c0811=1 & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=3 & thv_c0811=1 & thv_Q6=1 & thv_c0404=1)) & Qd & Qn & Qm +{ + Qd = Qn | ~Qm; +} + +@endif # SIMD + + +####### +# VPUSH (A2) +# + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +buildVpushSdList: Sreg is counter=0 & Sreg [ regNum=regNum+1; ] { * mult_addr = Sreg; mult_addr = mult_addr + 4; } +buildVpushSdList: Sreg,buildVpushSdList is Sreg & buildVpushSdList [ counter=counter-1; regNum=regNum+1; ] { * mult_addr = Sreg; mult_addr = mult_addr + 4; } + +vpushSdList: "{"^buildVpushSdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVpushSdList [ regNum=(c1215<<1)+D22-1; counter=c0007-1; ] { sp = sp - c0007 * 4; mult_addr = sp; build buildVpushSdList; } +vpushSdList: "{"^buildVpushSdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpushSdList [ regNum=(thv_c1215<<1)+thv_D22-1; counter=thv_c0007-1; ] { sp = sp - thv_c0007 * 4; mult_addr = sp; build buildVpushSdList; } + +buildVpushSd64List: Dreg is counter=0 & Dreg [ regNum=regNum+1; ] { * mult_addr = Dreg:8; mult_addr = mult_addr + 8; } +buildVpushSd64List: Dreg,buildVpushSd64List is Dreg & buildVpushSd64List [ counter=counter-1; regNum=regNum+1; ] { * mult_addr = Dreg:8; mult_addr = mult_addr + 8; build buildVpushSd64List; } + +vpushSd64List: "{"^buildVpushSd64List^"}" is TMode=0 & D22 & c1215 & c0007 & buildVpushSd64List [ regNum=(D22<<4)+c1215-1; counter=c0007 / 2 - 1; ] { sp = sp - c0007 * 4; mult_addr = sp; build buildVpushSd64List; } +vpushSd64List: "{"^buildVpushSd64List^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpushSd64List [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007 / 2 - 1; ] { sp = sp - thv_c0007 * 4; mult_addr = sp; build buildVpushSd64List; } + + +:vpush^COND vpushSd64List is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c1619=13 & c2121=1 & c2020=0 & c0811=11) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c1619=13 & thv_c2121=1 & thv_c2020=0 & thv_c0811=11) ) & vpushSd64List +{ + build vpushSd64List; +} + +:vpush^COND vpushSdList is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c1619=13 & c2121=1 & c2020=0 & c0811=10) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c1619=13 & thv_c2121=1 & thv_c2020=0 & thv_c0811=10) ) & vpushSdList +{ + build vpushSdList; +} + +buildVpopSdList: Sreg is counter=0 & Sreg [ regNum=regNum+1; ] + { tmp:4 = *mult_addr; Sreg = zext(tmp); mult_addr = mult_addr + 4; } +buildVpopSdList: Sreg,buildVpopSdList is Sreg & buildVpopSdList [ counter=counter-1; regNum=regNum+1; ] + { tmp:4 = *mult_addr; Sreg = zext(tmp); mult_addr = mult_addr + 4; } + +vpopSdList: "{"^buildVpopSdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVpopSdList [ regNum=(c1215<<1)+D22-1; counter=c0007-1; ] + { mult_addr = sp; sp = sp + c0007 * 4; build buildVpopSdList; } +vpopSdList: "{"^buildVpopSdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpopSdList [ regNum=(thv_c1215<<1)+thv_D22-1; counter=thv_c0007-1; ] + { mult_addr = sp; sp = sp + thv_c0007 * 4; build buildVpopSdList; } + +buildVpopSd64List: Dreg is counter=0 & Dreg [ regNum=regNum+1; ] + { Dreg = *mult_addr; mult_addr = mult_addr + 8; } +buildVpopSd64List: Dreg,buildVpopSd64List is Dreg & buildVpopSd64List [ counter=counter-1; regNum=regNum+1; ] + { Dreg = *mult_addr; mult_addr = mult_addr + 8; build buildVpopSd64List; } + +vpopSd64List: "{"^buildVpopSd64List^"}" is TMode=0 & D22 & c1215 & c0007 & buildVpopSd64List [ regNum=(D22<<4)+c1215-1; counter=c0007 / 2 - 1; ] + { mult_addr = sp; sp = sp + c0007 * 4; build buildVpopSd64List; } +vpopSd64List: "{"^buildVpopSd64List^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVpopSd64List [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007 / 2 - 1; ] + { mult_addr = sp; sp = sp + thv_c0007 * 4; build buildVpopSd64List; } + +:vpop^COND vpopSd64List is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x19 & c1619=13 & c2121=1 & c2020=1 & c0811=11 & c0000=0) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c1619=13 & thv_c2121=1 & thv_c2020=1 & thv_c0811=11 & thv_c0000=0) ) & vpopSd64List +{ + build vpopSd64List; +} + +:vpop^COND vpopSdList is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x19 & c1619=13 & c2121=1 & c2020=1 & c0811=10) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c1619=13 & thv_c2121=1 & thv_c2020=1 & thv_c0811=10) ) & vpopSdList +{ + build vpopSdList; +} + +@endif # VFPv2 || VFPv3 || SIMD + +@if defined(SIMD) + +define pcodeop SatQ; +define pcodeop SignedSatQ; + +:vqadd.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=0 & Q6=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=0 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm +{ + Dd = VectorAdd(Dn,Dm,esize2021,udt); + Dd = SatQ(Dd, esize2021, udt); +} + +:vqadd.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=0 & Q6=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=0 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd +{ + Qd = VectorAdd(Qn,Qm,esize2021,udt); + Qd = SatQ(Qd, esize2021, udt); +} + +:vqmovn.i^esize1819x2 Dd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=5 & c0606 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=5 & thv_c0404=0) ) & esize1819x2 & Dd & Qm +{ + Dd = VectorCopyNarrow(Qm,esize1819x2,c0606:1); + Dd = SatQ(Dd, esize1819x2,0:1); +} + +:vqmovun.i^esize1819x2 Dd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0611=9 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0611=9 & thv_c0404=0) ) & esize1819x2 & Dd & Qm +{ + Dd = VectorCopyNarrow(Qm,esize1819x2,0:1); + Dd = SatQ(Dd, esize1819x2,0:1); +} + +:vqdmlal.S^esize2021 Qd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2327=5 & (c2021=1 | c2021=2) & c0811=0x9 & c0606=0 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x9 & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd + +{ + Qd = VectorDoubleMultiplyAccumulateLong(Dn,Dm,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmlal.S^esize2021 Qd, Dn, vmlDmA is ( ( $(AMODE) & cond=15 & c2327=5 & (c2021=1 | c2021=2)& c0811=0x3 & c0606=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x3 & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Qd + +{ + Qd = VectorDoubleMultiplyAccumulateLong(Dn,vmlDmA,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmlsl.S^esize2021 Qd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2327=5 & (c2021=1 | c2021=2) & c0811=0xb & c0606=0 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd + +{ + Qd = VectorDoubleMultiplySubtractLong(Dn,Dm,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmlsl.S^esize2021 Qd, Dn, vmlDmA is ( ( $(AMODE) & cond=15 & c2327=5 & (c2021=1 | c2021=2)& c0811=0x7 & c0606=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0x7 & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Qd + +{ + Qd = VectorDoubleMultiplySubtractLong(Dn,vmlDmA,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmulh.S^esize2021 Dd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2527=1 & c2324=0 & (c2021=1 | c2021=2) & c0811=0xb & Q6=0 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Dd + +{ + Dd = VectorDoubleMultiplyHighHalf(Dn,Dm,esize2021,0:1); + Dd = SatQ(Dd, esize2021,0:1); +} + +:vqdmulh.S^esize2021 Qd, Qn, Qm is ( ( $(AMODE) & cond=15 & c2527=1 & c2324=0 & (c2021=1 | c2021=2) & c0811=0xb & Q6=1 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & Qm & Qn & Qd + +{ + Qd = VectorDoubleMultiplyHighHalf(Qn,Qm,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmulh.S^esize2021 Dd, Dn, vmlDmA is ( ( $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)& c0811=0xc & c0606=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xc & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Dd + +{ + Dd = VectorDoubleMultiplyLong(Dn,vmlDmA,esize2021,0:1); + Dd = SatQ(Dd, esize2021,0:1); +} + +:vqdmulh.S^esize2021 Qd, Qn, vmlDmA is ( ( $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0xc & c0606=1 & c0404=0) | + ( $(TMODE_F) & thv_c2327=0x1f & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xc & thv_c0606=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Qn & Qd + +{ + Qd = VectorDoubleMultiplyLong(Qn,vmlDmA,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmull.S^esize2021 Qd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2327=5 & c2021<3 & c0811=0xD & Q6=0 & c0404=0 ) | + ( $(TMODE_E) & thv_c2327=0x1f & thv_c2324=1 & thv_c2021<3 & thv_c0811=0xD & thv_Q6=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Qd + +{ + Qd = VectorDoubleMultiplyLong(Dn,Dm,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqdmull.S^esize2021 Qd, Dn, vmlDmA is ( ( $(AMODE) & cond=15 & c2327=5 & c2021<3 & c0811=0xb & Q6=1 & c0404=1 ) | + ( $(TMODE_E) & thv_c2327=0x1e & thv_c2324=1 & thv_c2021<3 & thv_c0811=0xb & thv_Q6=1 & thv_c0404=1 ) ) & esize2021 & vmlDmA & Dn & Qd + +{ + Qd = VectorDoubleMultiplyLong(Dn,vmlDmA,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqrdmulh.S^esize2021 Dd, Dn, Dm is ( ( $(AMODE) & cond=15 & c2527=1 & c2324=2 & (c2021=1 | c2021=2) & c0811=0xb & Q6=0 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_Q6=0 & thv_c0404=0 ) ) & esize2021 & Dm & Dn & Dd + +{ + Dd = VectorRoundDoubleMultiplyHighHalf(Dn,Dm,esize2021,0:1); + Dd = SatQ(Dd, esize2021,0:1); +} + +:vqrdmulh.S^esize2021 Qd, Qn, Qm is ( ( $(AMODE) & cond=15 & c2527=1 & c2324=2 & (c2021=1 | c2021=2) & c0811=0xb & Q6=1 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1e & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xb & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & Qm & Qn & Qd + +{ + Qd = VectorRoundDoubleMultiplyHighHalf(Qn,Qm,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + +:vqrdmulh.S^esize2021 Dd, Dn, vmlDmA is ( ( $(AMODE) & cond=15 & c2527=1 & c2424=0 & c2323=1 & (c2021=1 | c2021=2)& c0811=0xd & Q6=1 & c0404=0) | + ( $(TMODE_E) & thv_c2327=0x1f & thv_c2323=1 & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Dn & Dd + +{ + Dd = VectorRoundDoubleMultiplyHighHalf(Dn,vmlDmA,esize2021,0:1); + Dd = SatQ(Dd, esize2021,0:1); +} + +:vqrdmulh.S^esize2021 Qd, Qn, vmlDmA is ( ( $(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c2021=1 | c2021=2) & c0811=0xd & Q6=1 & c0404=0) | + ( $(TMODE_F) & thv_c2327=0x1f & thv_c2323=1 & (thv_c2021=1 | thv_c2021=2) & thv_c0811=0xd & thv_Q6=1 & thv_c0404=0 ) ) & esize2021 & vmlDmA & Qn & Qd + +{ + Qd = VectorRoundDoubleMultiplyHighHalf(Qn,vmlDmA,esize2021,0:1); + Qd = SatQ(Qd, esize2021,0:1); +} + + +:vqsub.^udt^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=2 & Q6=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=2 & thv_Q6=0 & thv_c0404=1)) & udt & esize2021 & Dn & Dd & Dm +{ + Dd = VectorSub(Dn,Dm,esize2021,udt); + Dd = SatQ(Dd, esize2021, udt); +} + +:vqsub.^udt^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=2 & Q6=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c2323=0 & thv_c0811=2 & thv_Q6=1 & thv_c0404=1) ) & udt & esize2021 & Qm & Qn & Qd +{ + Qd = VectorSub(Qn,Qm,esize2021,udt); + Qd = SatQ(Qd, esize2021, udt); +} + +####### +# TODO: lots of missing stuff +# + +####### +# VRECPE +define pcodeop VectorReciprocalEstimate; + +:vrecpe.^fdt^32 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=0 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=0 & thv_Q6=1 & thv_c0404=0) ) & fdt & Qm & Qd +{ + Qd = VectorReciprocalEstimate(Qm,fdt); +} + +:vrecpe.^fdt^32 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=0 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=0 & thv_Q6=0 & thv_c0404=0) ) & fdt & Dm & Dd +{ + Dd = VectorReciprocalEstimate(Dm,fdt); +} + +####### +# VRECPS +define pcodeop VectorReciprocalStep; + +:vrecps.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=0x4 & c2021=0 & c0811=0xf & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=0xf & thv_Q6=1 & thv_c0404=1) ) & Qn & Qm & Qd +{ + Qd = VectorReciprocalStep(Qn,Qm); +} + +:vrecps.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=0x4 & c2021=0 & c0811=0xf & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=0 & thv_c0811=0xf & thv_Q6=0 & thv_c0404=1) ) & Dn & Dm & Dd +{ + Dd = VectorReciprocalStep(Dn,Dm); +} + +####### +# VREV +# + +define pcodeop vrev; + +:vrev16.^esize1819x3 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=2 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=2 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3 +{ + Qd = vrev(Qm,esize1819x3); +} + +:vrev32.^esize1819x3 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=1 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=1 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3 +{ + Qd = vrev(Qm,esize1819x3); +} + +:vrev64.^esize1819x3 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=0 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=0 & thv_c0606=1 & thv_c0404=0) ) & Qd & Qm & esize1819x3 +{ + Qd = vrev(Qm,esize1819x3); +} + +:vrev16.^esize1819x3 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=2 & c0606=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=2 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3 +{ + Dd = vrev(Dm,esize1819x3); +} + +:vrev32.^esize1819x3 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=1 & c0606=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=1 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3 +{ + Dd = vrev(Dm,esize1819x3); +} + +:vrev64.^esize1819x3 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=0 & c0911=0 & c0708=0 & c0606=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=0 & thv_c0911=0 & thv_c0708=0 & thv_c0606=0 & thv_c0404=0) ) & Dd & Dm & esize1819x3 +{ + Dd = vrev(Dm,esize1819x3); +} + +####### +# VSH +# + +define pcodeop VectorShiftLeft; +define pcodeop VectorRoundShiftLeft; +define pcodeop VectorShiftRight; +define pcodeop VectorShiftLeftInsert; +define pcodeop VectorShiftRightInsert; +define pcodeop VectorShiftRightNarrow; +define pcodeop VectorShiftRightAccumulate; +define pcodeop VectorRoundShiftRight; +define pcodeop VectorRoundShiftRightNarrow; +define pcodeop VectorRoundShiftRightAccumulate; + +ShiftSize: "8" is TMode=0 & c1921=1 & L7=0 { export 8:8; } +ShiftSize: "16" is TMode=0 & c2021=1 & L7=0 { export 16:8; } +ShiftSize: "32" is TMode=0 & c2121=1 & L7=0 { export 32:8; } +ShiftSize: "64" is TMode=0 & L7=1 { export 64:8; } +ShiftSize: "8" is TMode=1 & thv_c1921=1 & thv_L7=0 { export 8:8; } +ShiftSize: "16" is TMode=1 & thv_c2021=1 & thv_L7=0 { export 16:8; } +ShiftSize: "32" is TMode=1 & thv_c2121=1 & thv_L7=0 { export 32:8; } +ShiftSize: "64" is TMode=1 & thv_L7=1 { export 64:8; } + + +ShiftImmRLI: "#"^shift_amt is TMode=0 & c1921=1 & L7=0 & c1621 [ shift_amt = 16 - c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=0 & c2021=1 & L7=0 & c1621 [ shift_amt = 32 - c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=0 & c2121=1 & L7=0 & c1621 [ shift_amt = 64 - c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=0 & L7=1 & c1621 [ shift_amt = 64 - c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c1921=1 & thv_L7=0 & thv_c1621 [ shift_amt = 16 - thv_c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c2021=1 & thv_L7=0 & thv_c1621 [ shift_amt = 32 - thv_c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_c2121=1 & thv_L7=0 & thv_c1621 [ shift_amt = 64 - thv_c1621; ] { export *[const]:8 shift_amt; } +ShiftImmRLI: "#"^shift_amt is TMode=1 & thv_L7=1 & thv_c1621 [ shift_amt = 64 - thv_c1621; ] { export *[const]:8 shift_amt; } + +ShiftImmLLI: "#"^shift_amt is TMode=0 & c1921=1 & L7=0 & c1621 [ shift_amt = c1621 - 8; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=0 & c2021=1 & L7=0 & c1621 [ shift_amt = c1621 - 16; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=0 & c2121=1 & L7=0 & c1621 [ shift_amt = c1621 - 32; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=0 & L7=1 & c1621 [ shift_amt = c1621 - 0; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c1921=1 & thv_L7=0 & thv_c1621 [ shift_amt = thv_c1621 - 8; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c2021=1 & thv_L7=0 & thv_c1621 [ shift_amt = thv_c1621 - 16; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_c2121=1 & thv_L7=0 & thv_c1621 [ shift_amt = thv_c1621 - 32; ] { export *[const]:8 shift_amt; } +ShiftImmLLI: "#"^shift_amt is TMode=1 & thv_L7=1 & thv_c1621 [ shift_amt = thv_c1621 - 0; ] { export *[const]:8 shift_amt; } + +:vqshrn.^udt^esize2021 Dd,Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & (c1919=1 | c2020=1 | c2121=1) & c0611=0x24 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x24 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm +{ + Dd = VectorShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt); + Dd = SatQ(Dd,esize2021,udt); +} + +:vqshrun.^udt^esize2021 Dd,Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c1919=1 | c2020=1 | c2121=1) & c0611=0x20 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x20 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm +{ + Dd = VectorShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt); + Dd = SatQ(Dd,esize2021,udt); +} + +:vqrshrn.^udt^esize2021 Dd,Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & (c1919=1 | c2020=1 | c2121=1) & c0611=0x25 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x25 & thv_c0404=1) ) & udt & esize2021 & ShiftSize & ShiftImmRLI & Dd & Qm +{ + Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt); + Dd = SatQ(Dd,esize2021,udt); +} + +:vqrshrun.^udt^esize2021 Dd,Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & (c1919=1 | c2020=1 | c2121=1) & c0611=0x21 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & (thv_c1919=1 | thv_c2020=1 | thv_c2121=1) & thv_c0611=0x21 & thv_c0404=1) ) & udt & esize2021 & ShiftImmRLI & Dd & Qm +{ + Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI,esize2021,udt); + Dd = SatQ(Dd,esize2021,udt); +} + + +:vqshl.^udt^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1621 & c0811=7 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1621 & thv_c0811=7 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Qm +{ + Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,udt); +} + +:vqshl.^udt^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1621 & c0811=7 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c1621 & thv_c0811=7 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Dd & Dm +{ + Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,udt); +} + +:vqshlu.^udt^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1621 & c0811=6 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2828=1 & thv_c2327=0x1f & thv_c1621 & thv_c0811=6 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Qm +{ + Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,udt); +} + +:vqshlu.^udt^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c1621 & c0811=6 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2828=1 & thv_c2327=0x1f & thv_c1621 & thv_c0811=6 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Dd & Dm +{ + Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,udt); +} + + +:vqshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=4 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=4 & thv_c0606=1 & thv_c0404=1) ) & udt & esize2021 & Qd & Qm & Qn +{ + Qd = VectorShiftLeft(Qm,Qn,esize2021,udt); +} + +:vqshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=4 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=4 & thv_c0606=0 & thv_c0404=1) ) & udt & esize2021 & Dd & Dm & Dn +{ + Dd = VectorShiftLeft(Dm,Dn,esize2021,udt); +} + + +:vshl.I^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2327=5 & c0811=5 & c0606=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c0811=5 & thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Qd & Qm +{ + Qd = VectorShiftLeft(Qm,ShiftImmLLI,ShiftSize,0:1); +} + +:vshl.I^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2327=5 & c0811=5 & c0606=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c0811=5 & thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Dd & Dm +{ + Dd = VectorShiftLeft(Dm,ShiftImmLLI,ShiftSize,0:1); +} + + +:vshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=4 & c0606=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=4 & thv_c0606=1 & thv_c0404=0) ) & udt & esize2021 & Qd & Qm & Qn +{ + Qd = VectorShiftLeft(Qm,Qn,esize2021,udt); +} + +:vshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=4 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=4 & thv_c0606=0 & thv_c0404=0) ) & udt & esize2021 & Dd & Dm & Dn +{ + Dd = VectorShiftLeft(Dm,Dn,esize2021,udt); +} + +define pcodeop VectorShiftLongLeft; + +:vshll.^udt^ShiftSize Qd, Dm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=10 & c0607=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=10 & thv_c0607=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmLLI & Qd & Dm +{ + Qd = VectorShiftLongLeft(Dm,ShiftImmLLI); +} + +:vshll.^udt^esize1819 Qd, Dm, "#"^esize1819x3 is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=2 & c0811=3 & c0607=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=3 & thv_c0607=0 & thv_c0404=0) ) & udt & esize1819 & esize1819x3 & Qd & Dm +{ + Qd = VectorShiftLongLeft(Dm,esize1819x3); +} + +:vrshl.^udt^esize2021 Qd, Qm, Qn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=5 & c0606=1 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=5 & thv_c0606=1 & thv_c0404=0) ) & udt & esize2021 & Qd & Qm & Qn +{ + Qd = VectorRoundShiftLeft(Qm,esize2021,Qn); +} + +:vrshl.^udt^esize2021 Dd, Dm, Dn is ( ($(AMODE) & cond=15 & c2527=1 & c2323=0 & c0811=5 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1e & thv_c0811=5 & thv_c0606=0 & thv_c0404=0) ) & udt & esize2021 & Dd & Dm & Dn +{ + Dd = VectorRoundShiftLeft(Dm,esize2021,Dn); +} + +:vrshr.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=2 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=2 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm +{ + Qd = VectorRoundShiftRight(Qm,ShiftImmRLI); +} + +:vrshr.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=2 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=2 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm +{ + Dd = VectorRoundShiftRight(Dm,ShiftImmRLI); +} + +:vrshrn.^ShiftSize Dd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2327=5 & c0811=8 & c0707=0 & c0606=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c0811=8 & thv_c0707=0 & thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Dd & Qm +{ + Dd = VectorRoundShiftRightNarrow(Qm,ShiftImmRLI); +} + +:vrsra.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=3 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=3 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm +{ + Qd = VectorRoundShiftRightAccumulate(Qd, Qm,ShiftImmRLI); +} + +:vrsra.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=3 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=3 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm +{ + Dd = VectorRoundShiftRightAccumulate(Dd, Dm,ShiftImmRLI); +} + +:vsli.^ShiftSize Dd, Dm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2327=7 & c0811=5 & c0606=0 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c0811=5 & thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Dd & Dm +{ + Dd = VectorShiftLeftInsert(Dd, Dm,ShiftImmLLI); +} + +:vsli.^ShiftSize Qd, Qm, ShiftImmLLI is ( ($(AMODE) & cond=15 & c2327=7 & c0811=5 & c0606=1 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c0811=5 & thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmLLI & Qd & Qm +{ + Qd = VectorShiftLeftInsert(Qd, Qm,ShiftImmLLI); +} + +:vsqrt^COND^".f32" Sd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=1 & c0811=10 & c0607=3 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=1 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sd +{ + build COND; + build Sd; + build Sm; + Sd = sqrt(Sm); +} + +:vsqrt^COND^".f64" Dd,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1d & c2021=3 & c1619=1 & c0811=11 & c0606=1 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1d & thv_c2021=3 & thv_c1619=1 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dd +{ + build COND; + build Dd; + build Dm; + Dd = sqrt(Dm); +} + +:vsra.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=1 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=1 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm +{ + Qd = VectorShiftRightAccumulate(Qd, Qm,ShiftImmRLI); +} + +:vsra.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=1 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=1 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm +{ + Dd = VectorShiftRightAccumulate(Dd, Dm,ShiftImmRLI); +} + +:vsri.^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c0811=4 & c0606=1 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c0811=4 & thv_c0606=1 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Qd & Qm +{ + Qd = VectorShiftRightInsert(Qd, Qm,ShiftImmRLI); +} + +:vsri.^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2424=1 & c2323=1 & c0811=4 & c0606=0 & c0404=1) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c0811=4 & thv_c0606=0 & thv_c0404=1) ) & ShiftSize & ShiftImmRLI & Dd & Dm +{ + Dd = VectorShiftRightInsert(Dd, Dm,ShiftImmRLI); +} + +####### +# VSHR +# + +:vshr.^udt^ShiftSize Qd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=0 & c0606=1 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=0 & thv_c0606=1 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Qd & Qm +{ + Qd = VectorShiftRight(Qm,ShiftImmRLI); +} + +:vshr.^udt^ShiftSize Dd, Dm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c0811=0 & c0606=0 & c0404=1) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c0811=0 & thv_c0606=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Dm +{ + Dd = VectorShiftRight(Dm,ShiftImmRLI); +} + +define pcodeop VectorShiftNarrowRight; + +:vshrn.^ShiftSize Dd, Qm, ShiftImmRLI is ( ($(AMODE) & cond=15 & c2327=5 & c0811=8 & c0607=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c0811=8 & thv_c0607=0 & thv_c0404=1) ) & udt & ShiftSize & ShiftImmRLI & Dd & Qm +{ + Dd = VectorShiftNarrowRight(Qm,ShiftImmRLI); +} + +####### +# VRSQRTE +define pcodeop VectorReciprocalSquareRootEstimate; + +:vrsqrte.^fdt^32 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=1 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=1 & thv_Q6=1 & thv_c0404=0) ) & fdt & Qm & Qd +{ + Qd = VectorReciprocalSquareRootEstimate(Qm,fdt); +} + +:vrsqrte.^fdt^32 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=0x7 & c2021=3 & c1619=0xb & c0911=2 & c0707=1 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1619=0xb & thv_c0911=2 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0) ) & fdt & Dm & Dd +{ + Dd = VectorReciprocalSquareRootEstimate(Dm,fdt); +} + +####### +# VRSQRTS +define pcodeop VectorReciprocalSquareRootStep; + +:vrsqrts.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=0x4 & c2021=2 & c0811=0xf & Q6=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=0xf & thv_Q6=1 & thv_c0404=1) ) & Qn & Qm & Qd +{ + Qd = VectorReciprocalSquareRootStep(Qn,Qm); +} + +:vrsqrts.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=0x4 & c2021=2 & c0811=0xf & Q6=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2021=2 & thv_c0811=0xf & thv_Q6=0 & thv_c0404=1) ) & Dn & Dm & Dd +{ + Dd = VectorReciprocalSquareRootStep(Dn,Dm); +} + + +####### +# VST1 (multiple single elements) +# + +buildVst1DdList: Dreg is Dreg & counter=1 [ counter=0; regNum=regNum+1; ] +{ + * mult_addr = Dreg; +} +buildVst1DdList: Dreg,buildVst1DdList is Dreg & buildVst1DdList [ counter=counter-1; regNum=regNum+1; ] +{ + * mult_addr = Dreg; + mult_addr = mult_addr + 8; + build buildVst1DdList; +} + +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 0 & c0811=7 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 0 & c0811=10 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 0 & c0811=6 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=3; ] { export 3:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 0 & c0811=2 & D22 & c1215 & buildVst1DdList [ regNum=(D22<<4)+c1215-1; counter=4; ] { export 4:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 1 & thv_c0811=7 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 1 & thv_c0811=10 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 1 & thv_c0811=6 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=3; ] { export 3:4; } +vst1DdList: "{"^buildVst1DdList^"}" is TMode = 1 & thv_c0811=2 & thv_D22 & thv_c1215 & buildVst1DdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=4; ] { export 4:4; } + +@define Vst1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10)" +@define T_Vst1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10)" + +:vst1.^esize0607 vst1DdList,RnAligned45 is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & c0003=15 & $(Vst1DdList)) | + ($(TMODE_F) &thv_c2327=18 & thv_c2021=0 & thv_c0003=15 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & vst1DdList +{ + mult_addr = RnAligned45; + build vst1DdList; +} + +:vst1.^esize0607 vst1DdList,RnAligned45^"!" is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & c0003=13 & $(Vst1DdList)) | + ($(TMODE_F) &thv_c2327=18 & thv_c2021=0 & thv_c0003=13 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & vst1DdList +{ + mult_addr = RnAligned45; + build vst1DdList; + RnAligned45 = RnAligned45 + (8 * vst1DdList); +} + +:vst1.^esize0607 vst1DdList,RnAligned45,VRm is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & $(Vst1DdList)) | + ($(TMODE_F) &thv_c2327=18 & thv_c2021=0 & $(T_Vst1DdList)) ) & RnAligned45 & esize0607 & VRm & vst1DdList +{ + mult_addr = RnAligned45; + build vst1DdList; + RnAligned45 = RnAligned45 + VRm; +} + +####### +# VST1 (single element to one lane) +# + +vst1Index: val is c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } + +vst1DdElement2: Dd^"["^vst1Index^"]" is Dd & vst1Index & c1011=0 +{ + ptr:4 = &Dd + vst1Index; + *:1 mult_addr = *[register]:1 ptr; +} +vst1DdElement2: Dd^"["^vst1Index^"]" is Dd & vst1Index & c1011=1 +{ + ptr:4 = &Dd + (2 * vst1Index); + *:2 mult_addr = *[register]:2 ptr; +} +vst1DdElement2: Dd^"["^vst1Index^"]" is Dd & vst1Index & c1011=2 +{ + ptr:4 = &Dd + (4 * vst1Index); + *:4 mult_addr = *[register]:4 ptr; +} + +@define Vst1DdElement2 "((c1011=0 & c0404=0) | (c1011=1 & c0505=0) | (c1011=2 & (c0406=0 | c0406=3))) & vst1DdElement2" + +:vst1.^esize1011 vst1DdElement2,RnAligned2 is $(AMODE) & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & c0003=15 & $(Vst1DdElement2) +{ + mult_addr = RnAligned2; + build vst1DdElement2; +} + +:vst1.^esize1011 vst1DdElement2,RnAligned2^"!" is $(AMODE) & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & c0003=13 & $(Vst1DdElement2) +{ + mult_addr = RnAligned2; + build vst1DdElement2; + RnAligned2 = RnAligned2 + esize1011; +} + +:vst1.^esize1011 vst1DdElement2,RnAligned2,VRm is $(AMODE) & cond=15 & c2327=9 & c2021=0 & RnAligned2 & esize1011 & c0809=0 & VRm & $(Vst1DdElement2) +{ + mult_addr = RnAligned2; + build vst1DdElement2; + RnAligned2 = RnAligned2 + VRm; +} + +thv_vst1Index: val is thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + +thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]" is Dd & thv_vst1Index & thv_c1011=0 +{ + ptr:4 = &Dd + thv_vst1Index; + *:1 mult_addr = *[register]:1 ptr; +} +thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]" is Dd & thv_vst1Index & thv_c1011=1 +{ + ptr:4 = &Dd + (2 * thv_vst1Index); + *:2 mult_addr = *[register]:2 ptr; +} +thv_vst1DdElement2: Dd^"["^thv_vst1Index^"]" is Dd & thv_vst1Index & thv_c1011=2 +{ + ptr:4 = &Dd + (4 * thv_vst1Index); + *:4 mult_addr = *[register]:4 ptr; +} + +@define T_Vst1DdElement2 "((thv_c1011=0 & thv_c0404=0) | (thv_c1011=1 & thv_c0505=0) | (thv_c1011=2 & (thv_c0406=0 | thv_c0406=3))) & thv_vst1DdElement2" + +:vst1.^esize1011 thv_vst1DdElement2,RnAligned2 is $(TMODE_F) &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & thv_c0003=15 & $(T_Vst1DdElement2) +{ + mult_addr = RnAligned2; + build thv_vst1DdElement2; +} + +:vst1.^esize1011 thv_vst1DdElement2,RnAligned2^"!" is $(TMODE_F) &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & thv_c0003=13 & $(T_Vst1DdElement2) +{ + mult_addr = RnAligned2; + build thv_vst1DdElement2; + RnAligned2 = RnAligned2 + esize1011; +} + +:vst1.^esize1011 thv_vst1DdElement2,RnAligned2,VRm is $(TMODE_F) &thv_c2327=19 & thv_c2021=0 & RnAligned2 & esize1011 & thv_c0809=0 & VRm & $(T_Vst1DdElement2) +{ + mult_addr = RnAligned2; + build thv_vst1DdElement2; + RnAligned2 = RnAligned2 + VRm; +} + + +####### +# VST2 +# + +####### +# VST2 (multiple 2-element structures) +# + +vst2Dd: Dreg is Dreg & ((TMode=0 & c0607=0) | (TMode=1 & thv_c0607=0)) & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 8; + + *:1 mult_addr = *[register]:1 ptr1; + mult_addr = mult_addr + 1; + *:1 mult_addr = *[register]:1 ptr2; + mult_addr = mult_addr + 1; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 1; + ptr2 = ptr2 + 1; + goto ; + +} +vst2Dd: Dreg is Dreg & ((TMode=0 & c0607=1) | (TMode=1 & thv_c0607=1)) & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 4; + + *:2 mult_addr = *[register]:2 ptr1; + mult_addr = mult_addr + 2; + *:2 mult_addr = *[register]:2 ptr2; + mult_addr = mult_addr + 2; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 2; + ptr2 = ptr2 + 2; + goto ; + +} +vst2Dd: Dreg is Dreg & ((TMode=0 & c0607=2) | (TMode=1 & thv_c0607=2)) & regInc +{ + ptr1:4 = &Dreg; +@if ENDIAN == "little" + ptr2:4 = &Dreg + (regInc * 8); +@else # ENDIAN == "big" + ptr2:4 = &Dreg - (regInc * 8); +@endif # ENDIAN = "big" + mult_dat8 = 2; + + *:4 mult_addr = *[register]:4 ptr1; + mult_addr = mult_addr + 4; + *:4 mult_addr = *[register]:4 ptr2; + mult_addr = mult_addr + 4; + mult_dat8 = mult_dat8 - 1; + if(mult_dat8 == 0) goto ; + ptr1 = ptr1 + 4; + ptr2 = ptr2 + 4; + goto ; + +} + +buildVst2DdListA: is counter=0 { } +buildVst2DdListA: vst2Dd,buildVst2DdListA is vst2Dd & buildVst2DdListA & esize0607 [ counter=counter-1; regNum=regNum+1; ] +{ + build vst2Dd; + build buildVst2DdListA; +} + +buildVst2DdListB: is counter2=0 { } +buildVst2DdListB: Dreg2 is Dreg2 & counter2=1 & esize0607 [ counter2=0; reg2Num=reg2Num+1; ] { } +buildVst2DdListB: Dreg2,buildVst2DdListB is Dreg2 & buildVst2DdListB & esize0607 [ counter2=counter2-1; reg2Num=reg2Num+1; ] { } + +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=0 & c0811=8 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; } +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=0 & c0811=9 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; } +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=0 & c0811=3 & D22 & c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(D22<<4)+c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVst2DdListA; build buildVst2DdListB; export 4:4; } +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=1 & thv_c0811=8 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; reg2Num=regNum+1; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; } +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=1 & thv_c0811=9 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=1; counter2=1; ] { build buildVst2DdListA; build buildVst2DdListB; export 2:4; } +vst2DdList: "{"^buildVst2DdListA^buildVst2DdListB^"}" is TMode=1 & thv_c0811=3 & thv_D22 & thv_c1215 & buildVst2DdListA & buildVst2DdListB [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=2; reg2Num=regNum+2; counter=2; counter2=2; ] { build buildVst2DdListA; build buildVst2DdListB; export 4:4; } + + +@define Vst2DdList "(c0811=3 | c0811=8 | c0811=9)" +@define T_Vst2DdList "(thv_c0811=3 | thv_c0811=8 | thv_c0811=9)" + +:vst2.^esize0607 vst2DdList,RnAligned45 is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0 & c0607<3 & c0003=15 & $(Vst2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & thv_c0003=15 & $(T_Vst2DdList) ) ) & RnAligned45 & esize0607 & vst2DdList +{ + mult_addr = RnAligned45; + build vst2DdList; +} + +:vst2.^esize0607 vst2DdList,RnAligned45^"!" is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0 & c0607<3 & c0003=13 & $(Vst2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & thv_c0003=13 & $(T_Vst2DdList) ) ) & RnAligned45 & esize0607 & vst2DdList +{ + mult_addr = RnAligned45; + build vst2DdList; + RnAligned45 = RnAligned45 + (8 * vst2DdList); +} + +:vst2.^esize0607 vst2DdList,RnAligned45,VRm is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0 & c0607<3 & $(Vst2DdList) ) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0607<3 & $(T_Vst2DdList) ) ) & RnAligned45 & VRm & esize0607 & vst2DdList +{ + mult_addr = RnAligned45; + build vst2DdList; + RnAligned45 = RnAligned45 + VRm; +} + +####### +# VST2 (single 2-element structure to one lane) +# + +vst2DdElement2: Dreg^"["^vld2Index^"]" is Dreg & vld2Index +{ +} + +vst2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vst2Align2: "@16" is TMode=0 & c1011=0 & c0404=1 { } +vst2Align2: "@32" is TMode=0 & c1011=1 & c0404=1 { } +vst2Align2: "@64" is TMode=0 & c1011=2 & c0405=1 { } +vst2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vst2Align2: "@16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vst2Align2: "@32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vst2Align2: "@64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } + +vst2RnAligned2: "["^VRn^vst2Align2^"]" is VRn & vst2Align2 { export VRn; } + +buildVst2DdList2: is counter=0 { } +buildVst2DdList2: vst2DdElement2 is counter=1 & vst2DdElement2 [ counter=0; regNum=regNum+regInc; ] { } +buildVst2DdList2: vst2DdElement2,buildVst2DdList2 is vst2DdElement2 & buildVst2DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vst2DdList2: "{"^buildVst2DdList2^"}" is TMode=0 & D22 & c1215 & buildVst2DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single +vst2DdList2: "{"^buildVst2DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst2DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double +vst2DdList2: "{"^buildVst2DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVst2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single +vst2DdList2: "{"^buildVst2DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVst2DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double + +:vst2.^esize1011 vst2DdList2,vst2RnAligned2 is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=1 & c0003=15 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 & thv_c0003=15 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 + unimpl + +:vst2.^esize1011 vst2DdList2,vst2RnAligned2^"!" is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=1 & c0003=13 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 & thv_c0003=13 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 + unimpl + +:vst2.^esize1011 vst2DdList2,vst2RnAligned2,VRm is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=1 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=1 ) ) & vst2RnAligned2 & esize1011 & vst2DdList2 & VRm + unimpl + + +####### +# VST3 +# + +####### +# VST3 (multiple 3-element structures) +# + + +vst3Align: is TMode=0 & c0404=0 { } +vst3Align: "@64" is TMode=0 & c0404=1 { } +vst3Align: is TMode=1 & thv_c0404=0 { } +vst3Align: "@64" is TMode=1 & thv_c0404=1 { } + + +vst3RnAligned: "["^VRn^vst3Align^"]" is VRn & vst3Align { export VRn; } + +buildvst3DdList: is counter=0 { } +buildvst3DdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildvst3DdList: Dreg,buildvst3DdList is buildvst3DdList & Dreg [ counter=counter-1; regNum=regNum+regInc; ] { } + +vst3DdList: "{"^buildvst3DdList^"}" is TMode=0 & c0811=4 & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=3; ] { } # Single +vst3DdList: "{"^buildvst3DdList^"}" is TMode=0 & c0811=5 & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=3; ] { } # Double +vst3DdList: "{"^buildvst3DdList^"}" is TMode=1 & thv_c0811=4 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=3; ] { } # Single +vst3DdList: "{"^buildvst3DdList^"}" is TMode=1 & thv_c0811=5 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=3; ] { } # Double + + +:vst3.^esize0607 vst3DdList,vst3RnAligned is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0 & c0003=15 ) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0003=15 ) ) & vst3RnAligned & esize0607 & vst3DdList + unimpl + +:vst3.^esize0607 vst3DdList,vst3RnAligned^"!" is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0 & c0003=13 ) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0003=13 ) ) & vst3RnAligned & esize0607 & vst3DdList + unimpl + +:vst3.^esize0607 vst3DdList,vst3RnAligned,VRm is ( ( $(AMODE) & cond=15 & c2327=8 & c2021=0) | + ( $(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 ) ) & vst3RnAligned & esize0607 & vst3DdList & VRm + unimpl + + +####### +# VST3 (single 3-element structure to one lane) +# + +vst3Rn: "["^VRn^"]" is VRn { export VRn; } + +vst3DdList2: "{"^buildvst3DdList^"}" is TMode=0 & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=2; ] { } # Single +vst3DdList2: "{"^buildvst3DdList^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildvst3DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=2; ] { } # Double +vst3DdList2: "{"^buildvst3DdList^"}" is TMode=1 & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=2; ] { } # Single +vst3DdList2: "{"^buildvst3DdList^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildvst3DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=2; ] { } # Double + +:vst3.^esize1011 vst3DdList2,vst3Rn is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=2 & c0003=15 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 & thv_c0003=15 ) ) & vst3Rn & esize1011 & vst3DdList2 + unimpl + +:vst3.^esize1011 vst3DdList2,vst3Rn^"!" is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=2 & c0003=13 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 & thv_c0003=13 ) ) & vst3Rn & esize1011 & vst3DdList2 + unimpl + +:vst3.^esize1011 vst3DdList2,vst3Rn,VRm is ( ( $(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=2 ) | + ( $(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=2 ) ) & vst3Rn & esize1011 & vst3DdList2 & VRm + unimpl + +####### +# VST4 (multiple 4-element structures) +# + +vst4Align: is TMode=0 & c0405=0 { } +vst4Align: "@64" is TMode=0 & c0405=1 { } +vst4Align: "@128" is TMode=0 & c0405=2 { } +vst4Align: "@256" is TMode=0 & c0405=3 { } +vst4Align: is TMode=1 & thv_c0405=0 { } +vst4Align: "@64" is TMode=1 & thv_c0405=1 { } +vst4Align: "@128" is TMode=1 & thv_c0405=2 { } +vst4Align: "@256" is TMode=1 & thv_c0405=3 { } + +vst4RnAligned: "["^VRn^vst4Align^"]" is VRn & vst4Align { export VRn; } + +buildVst4DdList: is counter=0 { } +buildVst4DdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } +buildVst4DdList: Dreg,buildVst4DdList is buildVst4DdList & Dreg [ counter=counter-1; regNum=regNum+regInc; ] { } + +vst4DdList: "{"^buildVst4DdList^"}" is TMode=0 & c0808=0 & D22 & c1215 & buildVst4DdList [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vst4DdList: "{"^buildVst4DdList^"}" is TMode=0 & c0808=1 & D22 & c1215 & buildVst4DdList [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vst4DdList: "{"^buildVst4DdList^"}" is TMode=1 & thv_c0808=0 & thv_D22 & thv_c1215 & buildVst4DdList [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single +vst4DdList: "{"^buildVst4DdList^"}" is TMode=1 & thv_c0808=1 & thv_D22 & thv_c1215 & buildVst4DdList [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double + +:vst4.^esize0607 vst4DdList,vst4RnAligned is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3 & c0003=15) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3 & thv_c0003=15) ) & vst4RnAligned & esize0607 & vst4DdList unimpl + +:vst4.^esize0607 vst4DdList,vst4RnAligned^"!" is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3 & c0003=13) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3 & thv_c0003=13) ) & vst4RnAligned & esize0607 & vst4DdList unimpl + +:vst4.^esize0607 vst4DdList,vst4RnAligned,VRm is ( ($(AMODE) & cond=15 & c2327=8 & c2021=0 & c0911=0 & c0607<3) | + ($(TMODE_F) & thv_c2327=0x12 & thv_c2021=0 & thv_c0911=0 & thv_c0607<3) ) & VRm & vst4RnAligned & esize0607 & vst4DdList unimpl + +####### +# VST4 (single 4-element structure from one lane) +# + +vst4Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } +vst4Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } + + +vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index +{ +} + +vst4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vst4Align2: "@32" is TMode=0 & c1011=0 & c0404=1 { } +vst4Align2: "@64" is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1)) { } +vst4Align2: "@128" is TMode=0 & c1011=2 & c0405=2 { } +vst4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vst4Align2: "@32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vst4Align2: "@64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } +vst4Align2: "@128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } + +vst4RnAligned2: "["^VRn^vst4Align2^"]" is VRn & vst4Align2 { export VRn; } + +buildVst4DdList2: is counter=0 { } +buildVst4DdList2: vst4DdElement2 is counter=1 & vst4DdElement2 [ counter=0; regNum=regNum+regInc; ] { } +buildVst4DdList2: vst4DdElement2,buildVst4DdList2 is vst4DdElement2 & buildVst4DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } + +vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=0 & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVst4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single +vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVst4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double + +:vst4.^esize1011 vst4DdList2,vst4RnAligned2 is ( ($(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=15) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15) ) & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl + +:vst4.^esize1011 vst4DdList2,vst4RnAligned2^"!" is ( ($(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=13) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13) ) & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl + +:vst4.^esize1011 vst4DdList2,vst4RnAligned2,VRm is ( ($(AMODE) & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3) ) & VRm & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) || defined(SIMD) + +####### +# VSTM (A1) +# + +buildVstmDdList: is counter=0 { } +buildVstmDdList: Dreg is counter=1 & Dreg [ counter=0; regNum=regNum+1; ] +{ + *mult_addr = Dreg; + mult_addr = mult_addr + 8; +} +buildVstmDdList: Dreg,buildVstmDdList is Dreg & buildVstmDdList [ counter=counter-1; regNum=regNum+1; ] +{ + *mult_addr = Dreg; + mult_addr = mult_addr + 8; + build buildVstmDdList; +} + +vstmDdList: "{"^buildVstmDdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVstmDdList [ regNum=(D22<<4)+c1215-1; counter=c0007>>1; ] { } +vstmDdList: "{"^buildVstmDdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVstmDdList [ regNum=(thv_D22<<4)+thv_c1215-1; counter=thv_c0007>>1; ] { } + +:vstmia^COND vldmRn,vstmDdList is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x19 & c2121 & c2020=0 & c0811=11 & c0000=0) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=0 & thv_c0811=11 & thv_c0000=0) ) & vldmRn & vstmDdList & vldmOffset & vldmUpdate +{ + mult_addr = vldmRn; + build vstmDdList; + build vldmUpdate; +} + +:vstmdb^COND vldmRn,vstmDdList is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c2121=1 & c2020=0 & c0811=11 & c0000=0) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=0 & thv_c0811=11 & thv_c0000=0) ) & vldmRn & vstmDdList & vldmOffset +{ + local start_addr = vldmRn - vldmOffset; + mult_addr = start_addr; + build vstmDdList; + vldmRn = start_addr; +} + +@endif # VFPv2 | VFPv3 | SIMD + +@if defined(VFPv2) || defined(VFPv3) + +####### +# VSTM (A2) +# + +buildVstmSdList: is counter=0 { } +buildVstmSdList: Sreg is counter=1 & Sreg [ counter=0; regNum=regNum+1; ] +{ + *mult_addr = Sreg; + mult_addr = mult_addr + 4; +} +buildVstmSdList: Sreg,buildVstmSdList is Sreg & buildVstmSdList [ counter=counter-1; regNum=regNum+1; ] +{ + *mult_addr = Sreg; + mult_addr = mult_addr + 4; + build buildVstmSdList; +} + +vstmSdList: "{"^buildVstmSdList^"}" is TMode=0 & D22 & c1215 & c0007 & buildVstmSdList [ regNum=(c1215<<1) + D22 -1; counter=c0007; ] { } +vstmSdList: "{"^buildVstmSdList^"}" is TMode=1 & thv_D22 & thv_c1215 & thv_c0007 & buildVstmSdList [ regNum=(thv_c1215<<1) + thv_D22 -1; counter=thv_c0007; ] { } + +:vstmia^COND vldmRn,vstmSdList is COND & ( ( $(AMODE) & ARMcond=1 & c2327=0x19 & c2121 & c2020=0 & c0811=10 ) | + ($(TMODE_E) & thv_c2327=0x19 & thv_c2121 & thv_c2020=0 & thv_c0811=10 ) ) & vldmRn & vstmSdList & vldmOffset & vldmUpdate +{ + mult_addr = vldmRn; + build vstmSdList; + build vldmUpdate; +} + +:vstmdb^COND vldmRn,vstmSdList is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1a & c2121=1 & c2020=0 & c0811=10 ) | + ($(TMODE_E) & thv_c2327=0x1a & thv_c2121=1 & thv_c2020=0 & thv_c0811=10) ) & vldmRn & vstmSdList & vldmOffset +{ + local start_addr = vldmRn - vldmOffset; + mult_addr = start_addr; + build vstmSdList; + vldmRn = start_addr; +} + + +####### +# VSTR +# + +:vstr^COND^".64" Dd,vldrRn is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=0 & c0811=11) | ($(TMODE_E) & thv_c2427=13 & thv_c2021=0 & thv_c0811=11)) & Dd & vldrRn +{ + *vldrRn = Dd; +} + +:vstr^COND^".32" Sd,vldrRn is COND & ( ($(AMODE) & ARMcond=1 & c2427=13 & c2021=0 & c0811=10) | ($(TMODE_E) & thv_c2427=13 & thv_c2021=0 & thv_c0811=10)) & Sd & vldrRn +{ + *vldrRn = Sd; +} + +@endif # VFPv2 || VFPv3 || SIMD + + +####### +# VSUB +# + +@if defined(SIMD) + +define pcodeop FloatVectorSub; +define pcodeop VectorSubAndNarrow; + +:vsub.i^esize2021 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=6 & c0811=8 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1e & thv_c0811=8 & thv_Q6=0 & thv_c0404=0)) & esize2021 & Dn & Dd & Dm +{ + Dd = VectorSub(Dn,Dm,esize2021); +} + +:vsub.i^esize2021 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=6 & c0811=8 & Q6=1 & c0404=0) | + ($(TMODE_F) &thv_c2327=0x1e & thv_c0811=8 & thv_Q6=1 & thv_c0404=0) ) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorSub(Qn,Qm,esize2021); +} + +:vsub.f32 Dd,Dn,Dm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_Q6=0 & thv_c0404=0) ) & Dm & Dn & Dd +{ + Dd = FloatVectorSub(Dn,Dm,2:1,32:1); +} + +:vsub.f32 Qd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=4 & c2121=1 & c0811=13 & Q6=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c2121=1 & thv_c0811=13 & thv_Q6=1 & thv_c0404=0) ) & Qn & Qd & Qm +{ + Qd = FloatVectorSub(Qn,Qm,2:1,32:1); +} + +:vsubhn.i^esize2021x2 Dd,Qn,Qm is ( ($(AMODE) & cond=15 & c2327=5 & c0811=6 & Q6=0 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1f & thv_c0811=6 & thv_Q6=0 & thv_c0404=0)) & esize2021x2 & Dd & Qn & Qm +{ + Dd = VectorSubAndNarrow(Qn,Qm,esize2021x2); +} + +:vsubl.^udt^esize2021 Qd,Dn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=2 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=2 & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Dn & Qd & Dm +{ + Qd = VectorSub(Dn,Dm,esize2021,udt); +} + +:vsubw.^udt^esize2021 Qd,Qn,Dm is ( ($(AMODE) & cond=15 & c2527=1 & c2323=1 & c2021<3 & c0811=3 & c0606=0 & c0404=0) | + ($(TMODE_EorF) & thv_c2327=0x1f & thv_c2021<3 & thv_c0811=3 & thv_c0606=0 & thv_c0404=0) ) & esize2021 & udt & Qn & Qd & Dm +{ + Qd = VectorSub(Qn,Dm,esize2021,udt); +} + +@endif # SIMD + +@if defined(VFPv2) || defined(VFPv3) + +:vsub^COND^".f32" Sd,Sm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=10 & c0606=1 & c0404=0) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=10 & thv_c0606=1 & thv_c0404=0) ) & Sm & Sn & Sd +{ + build COND; + build Sd; + build Sm; + build Sn; + Sd = Sn f- Sm; +} + +:vsub^COND^".f64" Dd,Dm is COND & ( ($(AMODE) & ARMcond=1 & c2327=0x1c & c2021=3 & c0811=11 & c0606=1 & c0404=0 ) | + ($(TMODE_E) & thv_c2327=0x1c & thv_c2021=3 & thv_c0811=11 & thv_c0606=1 & thv_c0404=0) ) & Dm & Dn & Dd +{ + build COND; + build Dd; + build Dm; + build Dn; + Dd = Dn f- Dm; +} + +@endif # VFPv2 || VFPv3 + +@if defined(SIMD) + + +####### +# VSWP +# + +:vswp Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=0 & Q6=0 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=0 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm +{ + tmp:8 = Dm; + Dm = Dd; + Dd = tmp; +} + +:vswp Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=0 & Q6=1 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=0 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm +{ + tmp:16 = Qm; + Qm = Qd; + Qd = tmp; +} + + +########### +# VTBL/VTBX +# + +define pcodeop VectorTableLookup; + +buildVtblDdList: is counter=0 { } +buildVtblDdList: Dreg is Dreg & counter=1 [ counter=0; regNum=regNum+1; ] { } +buildVtblDdList: Dreg,buildVtblDdList is Dreg & buildVtblDdList [ counter=counter-1; regNum=regNum+1; ] +{ + build buildVtblDdList; +} + +vtblDdList: "{"^buildVtblDdList^"}" is TMode=0 & c0809=0 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=1; ] { export 1:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=0 & c0809=1 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=2; ] { export 2:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=0 & c0809=2 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=3; ] { export 3:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=0 & c0809=3 & N7 & c1619 & buildVtblDdList [ regNum=(N7<<4)+c1619-1; counter=4; ] { export 4:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=1 & thv_c0809=0 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=1; ] { export 1:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=1 & thv_c0809=1 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=2; ] { export 2:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=1 & thv_c0809=2 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=3; ] { export 3:4; } +vtblDdList: "{"^buildVtblDdList^"}" is TMode=1 & thv_c0809=3 & thv_N7 & thv_c1619 & buildVtblDdList [ regNum=(thv_N7<<4)+thv_c1619-1; counter=4; ] { export 4:4; } + + +:vtbl.8 VRd,vtblDdList,VRm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1011=2 & c0606=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1011=2 & thv_c0606=0 & thv_c0404=0 ) ) & VRm & VRd & VRn & vtblDdList +{ + VRd = VectorTableLookup(VRm,VRn,vtblDdList); +} + +:vtbx.8 VRd,vtblDdList,VRm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1011=2 & c0606=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1011=2 & thv_c0606=1 & thv_c0404=0 ) ) & VRm & VRd & VRn & vtblDdList +{ + VRd = VectorTableLookup(VRm,VRn,vtblDdList); +} + + +###### +# VTST +# + +define pcodeop VectorTest; + +:vtst.^esize2021 Qd, Qn, Qm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=8 & c0606=1 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=8 & thv_c0606=1 & thv_c0404=1) ) & esize2021 & Qm & Qn & Qd +{ + Qd = VectorTest(Qn, Qm); +} + +:vtst.^esize2021 Dd, Dn, Dm is ( ($(AMODE) & cond=15 & c2327=4 & c0811=8 & c0606=0 & c0404=1) | + ($(TMODE_E) & thv_c2327=0x1e & thv_c0811=8 & thv_c0606=0 & thv_c0404=1) ) & esize2021 & Dm & Dn & Dd +{ + Dd = VectorTest(Dn, Dm); +} + +define pcodeop VectorTranspose; + +:vtrn^"."^esize1819 Dd,Dm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=2 & c0811=0 & c0707=1 & Q6=0 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=0 & thv_c0707=1 & thv_Q6=0 & thv_c0404=0)) & esize1819 & Dd & Dm +{ + Dd = VectorTranspose(Dm,esize1819); +} + +:vtrn^"."^esize1819 Qd,Qm is ( ($(AMODE) & cond=15 & c2327=7 & c2021=3 & c1617=2 & c0811=0 & c0707=1 & Q6=1 & c0404=0) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1617=2 & thv_c0811=0 & thv_c0707=1 & thv_Q6=1 & thv_c0404=0) ) & esize1819 & Qm & Qd +{ + Qd = VectorTranspose(Qm,esize1819); +} + + +####### +# VUZP +# + +define pcodeop VectorUnzip; + +:vuzp^esize1819 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=3 & Q6=0 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=3 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819 +{ + Dd = VectorUnzip(Dm,esize1819); +} + +:vuzp^esize1819 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=3 & Q6=1 & c0404=0 ) | + ( $(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=3 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819 +{ + Qd = VectorUnzip(Qm,esize1819); +} + + +####### +# VZIP +# + +define pcodeop VectorZip; + +:vuzp^esize1819 Dd,Dm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=2 & Q6=0 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=2 & thv_c0606=0 & thv_c0404=0 ) ) & Dd & Dm & esize1819 +{ + Dd = VectorZip(Dm,esize1819); +} + +:vuzp^esize1819 Qd,Qm is ( ( $(AMODE) & cond=15 & c2327=7 & c2021=3 & c1819<3 & c1617=2 & c0711=2 & Q6=1 & c0404=0 ) | + ($(TMODE_F) & thv_c2327=0x1f & thv_c2021=3 & thv_c1819<3 & thv_c1617=2 & thv_c0711=2 & thv_c0606=1 & thv_c0404=0 ) ) & Qd & Qm & esize1819 +{ + Qd = VectorZip(Qm,esize1819); +} + + +@endif # SIMD + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMt.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARMt.pspec new file mode 100644 index 00000000..17d32acd --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMt.pspec @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMtTHUMB.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARMtTHUMB.pspec new file mode 100644 index 00000000..cc30cec1 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMtTHUMB.pspec @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v45.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v45.pspec new file mode 100644 index 00000000..1d04e809 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v45.pspec @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v6.pspec b/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v6.pspec new file mode 100644 index 00000000..68d853b1 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMt_v6.pspec @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/ARMv8.sinc b/src/third-party/sleigh/processors/ARM/data/languages/ARMv8.sinc new file mode 100644 index 00000000..a4555820 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/ARMv8.sinc @@ -0,0 +1,1443 @@ + +# This macro is always defined in this file, but the ifdef may be +# useful if it is moved to ARMinstructions.sinc. + +crc32_type: "b" is TMode=0 & c2122=0b00 & c0909=0 { } +crc32_type: "h" is TMode=0 & c2122=0b01 & c0909=0 { } +crc32_type: "w" is TMode=0 & c2122=0b10 & c0909=0 { } +crc32_type: "cb" is TMode=0 & c2122=0b00 & c0909=1 { } +crc32_type: "ch" is TMode=0 & c2122=0b01 & c0909=1 { } +crc32_type: "cw" is TMode=0 & c2122=0b10 & c0909=1 { } +crc32_type: "b" is TMode=1 & thv_c0405=0b00 { } +crc32_type: "h" is TMode=1 & thv_c0405=0b01 { } +crc32_type: "w" is TMode=1 & thv_c0405=0b10 { } + +define pcodeop Crc32Calc; + +# F5.1.39,40 p2650,2653 CRC32,CRC32C A1 +:crc32^crc32_type Rd,Rn,Rm + is TMode=0 & c2831=0b1110 & c2327=0b00010 & c2020=0 & c0407=0b0100 & c1011=0b00 & c0808=0 + & crc32_type & Rn & Rd & Rm + { Rd = Crc32Calc(Rn,Rm); } + +# F5.1.39 p2650 CRC32 T1 +:crc32^crc32_type thv_Rt2,thv_Rn,thv_Rm + is TMode=1 & thv_c2031=0b111110101100 & thv_c1215=0b1111 & thv_c0607=0b10 + & crc32_type & thv_Rn & thv_Rt2 & thv_Rm + { thv_Rt2 = Crc32Calc(thv_Rn,thv_Rm); } + +# F5.1.40 p2653 CRC32C T1 +:crc32c^crc32_type thv_Rt2,thv_Rn,thv_Rm + is TMode=1 & thv_c2031=0b111110101101 & thv_c1215=0b1111 & thv_c0607=0b10 + & crc32_type & thv_Rn & thv_Rt2 & thv_Rm + { thv_Rt2 = Crc32Calc(thv_Rn,thv_Rm); } + +define pcodeop DCPSInstruction; + +dcps_lev:1 is TMode=1 & thv_c0001=0b01 { export 1:1; } +dcps_lev:2 is TMode=1 & thv_c0001=0b10 { export 2:1; } +dcps_lev:3 is TMode=1 & thv_c0001=0b11 { export 3:1; } + +# F5.1.42 p2657 DCPS1,DCPS2,DCPS3 DSPS1 variant +:dcps^dcps_lev + is TMode=1 & thv_c1631=0b1111011110001111 & thv_c0215=0b10000000000000 & (thv_c0101=1 | thv_c0000=1) & dcps_lev + { DCPSInstruction(dcps_lev:1); } + +# F5.1.53 p2683 LDA +:lda^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x19 & Rn & Rd & c0011=0xc9f + { + build COND; + Rd = *Rn; + } + +# F5.1.53 p2683 LDA +:lda thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1010 + & ItCond & thv_Rn & thv_Rt + { + build ItCond; + thv_Rt = *thv_Rn; + } + +# F5.1.54 p2684 LDAB +:ldab^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1d & Rn & Rd & c0011=0xc9f + { + build COND; + val:1 = *Rn; + Rd = zext(val); + } + +# F5.1.54 p2684 LDAB +:ldab thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1000 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + val:1 = *thv_Rn; + thv_Rt = zext(val); + } + +# F5.1.55 p2685 LDAEX +:ldaex^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x19 & Rn & Rd & c0011=0xe9f + { + build COND; + Rd = *Rn; + } + +# F5.1.55 p2685 LDAEX +:ldaex thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1110 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + thv_Rt = *thv_Rn; + } + +# F5.1.56 p2687 LDAEXB +:ldaexb^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1d & Rn & Rd & c0011=0xe9f + { + build COND; + val:1 = *Rn; + Rd = zext(val); + } + +# F5.1.56 p2687 LDAEXB +:ldaexb thv_Rt,thv_Rn + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1100 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + val:1 = *thv_Rn; + thv_Rt = zext(val); + } + +# F5.1.57 p2689 LDAEXD +:ldaexd^COND Rd,Rd2,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1b & Rn & Rd & Rd2 & c0011=0xe9f + { + build COND; +@if ENDIAN == "big" + Rd = *(Rn + 4); + Rd2 = *(Rn); +@else # ENDIAN == "little" + Rd = *(Rn); + Rd2 = *(Rn + 4); +@endif # ENDIAN == "little" + } + +# F5.1.57 p2689 LDAEXD +:ldaexd thv_Rt,thv_Rt2,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1111 + & ItCond & thv_Rt & thv_Rt2 & thv_Rn + { + build ItCond; +@if ENDIAN == "big" + thv_Rt = *(thv_Rn + 4); + thv_Rt2 = *(thv_Rn); +@else # ENDIAN == "little" + thv_Rt = *(thv_Rn); + thv_Rt2 = *(thv_Rn + 4); +@endif # ENDIAN == "little" + } + +# F5.1.58 p2691 LDAEXH +:ldaexh^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1f & Rn & Rd & c0011=0xe9f + { + build COND; + val:2 = *Rn; + Rd = zext(val); + } + +# F5.1.58 p2691 LDAEXH +:ldaexh thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1101 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + val:2 = *thv_Rn; + thv_Rt = zext(val); + } + +# F5.1.59 p2693 LDAH +:ldah^COND Rd,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1f & Rn & Rd & c0011=0xc9f + { + build COND; + val:2 = *Rn; + Rd = zext(val); + } + +# F5.1.59 p2693 LDAH +:ldah thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001101 & thv_c0407=0b1001 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + val:2 = *thv_Rn; + thv_Rt = zext(val); + } + +# F5.1.178 p2969 SEVL A1 variant +:sevl^COND + is TMode=0 & ARMcond=1 & COND & c1627=0b001100100000 & c0007=0b00000101 + { + build COND; + SendEvent(); + } + +# F5.1.178 p2969 SEVL T2 variant +:sevl.w + is TMode=1 & thv_c2031=0b111100111010 & thv_c1415=0b10 & thv_c1212=0 & thv_c0010=0b00000000101 + & ItCond + { + build ItCond; + SendEvent(); + } + +# F5.1.209 p3035 STL +:stl^COND Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x18 & Rn & c0415=0xfc9 & Rm + { + build COND; + *Rn = Rm; + } + +# F5.1.209 p3035 STL +:stl thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1010 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + *thv_Rn = thv_Rt; + } + +# F5.1.210 p3036 STLB +:stlb^COND Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1c & Rn & c0415=0xfc9 & Rm + { + build COND; + *:1 Rn = Rm[0,8]; + } + +# F5.1.210 p3036 STLB +:stlb thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1000 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + *:1 thv_Rn = thv_Rt[0,8]; + } + +# F5.1.211 p3037 STLEX +:stlex^COND Rd,Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x18 & Rn & Rd & c0411=0xe9 & Rm + { + build COND; + *Rn = Rm; + Rd = 0; + } + +# F5.1.211 p3037 STLEX +:stlex thv_Rm,thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1110 + & ItCond & thv_Rm & thv_Rt & thv_Rn + { + build ItCond; + *thv_Rn = thv_Rt; + thv_Rm = 0; + } + +# F5.1.212 p3040 STLEXB +:stlexb^COND Rd,Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1c & Rn & Rd & c0411=0xe9 & Rm + { + build COND; + *:1 Rn = Rm[0,8]; + Rd = 0; + } + +# F5.1.212 p3040 STLEXB +:stlexb thv_Rm,thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1100 + & ItCond & thv_Rm & thv_Rt & thv_Rn + { + build ItCond; + *:1 thv_Rn = thv_Rt[0,8]; + thv_Rm = 0; + } + +# F5.1.213 p3042 STLEXD +:stlexd^COND Rd,Rm,Rm2,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1a & Rn & Rd & c0411=0xe9 & Rm & Rm2 + { + build COND; +@if ENDIAN == "big" + *Rn = Rm; + *(Rn + 4) = Rm2; +@else # ENDIAN == "little" + *Rn = Rm2; + *(Rn + 4) = Rm; +@endif # ENDIAN == "little" + Rd = 0; + } + +# F5.1.213 p3042 STLEXD +:stlexd thv_Rm,thv_Rt,thv_Rt2,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1111 + & ItCond & thv_Rm & thv_Rt & thv_Rt2 & thv_Rn + { + build ItCond; +@if ENDIAN == "big" + *thv_Rn = thv_Rt; + *(thv_Rn + 4) = thv_Rt2; +@else # ENDIAN == "little" + *thv_Rn = thv_Rt2; + *(thv_Rn + 4) = thv_Rt; +@endif # ENDIAN == "little" + thv_Rm = 0; + } + +# F5.1.214 p3045 STLEXH +:stlexh^COND Rd,Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1e & Rn & Rd & c0411=0xe9 & Rm + { + build COND; + *:2 Rn = Rm[0,16]; + Rd = 0; + } + +# F5.1.214 p3045 STLEXH +:stlexh thv_Rm,thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1101 + & ItCond & thv_Rm & thv_Rt & thv_Rn + { + build ItCond; + *:2 thv_Rn = thv_Rt[0,16]; + thv_Rm = 0; + } + +# F5.1.215 p3048 STLH +:stlh^COND Rm,[Rn] + is TMode=0 & ARMcond=1 & COND & c2027=0x1e & Rn & c0415=0xfc9 & Rm + { + build COND; + *:2 Rn = Rm[0,16]; + } + +# F5.1.215 p3048 STLH +:stlh thv_Rt,[thv_Rn] + is TMode=1 & thv_c2031=0b111010001100 & thv_c0407=0b1001 + & ItCond & thv_Rt & thv_Rn + { + build ItCond; + *:2 thv_Rn = thv_Rt[0,16]; + } + +@ifdef INCLUDE_NEON + +# Advanced SIMD support / NEON in ARMv8 + +####### +# macro declarations + +# The Inexact flag is bit 4 of FPEXC +@define FPEXC_IXF "fpexc[3,1]" + +# Rounding modes, as used in pseudocode, defined as an enumeration +# '01' N +@define FPRounding_TIEEVEN "0:1" +# '10' P +@define FPRounding_POSINF "1:1" +# '11' M +@define FPRounding_NEGINF "2:1" +@define FPRounding_ZERO "3:1" +# '00' A +@define FPRounding_TIEAWAY "4:1" +@define FPRounding_ODD "5:1" + +####### +# pcodeop declarations + +# CryptOp(val) +# Various crypto algorithms, too numerous for explication at +# this time + +define pcodeop CryptOp; + +# FixedToFP(fp, M, N, fbits, unsigned, rounding) +# Convert M-bit fixed point with fbits fractional bits to N-bit +# floating point, controlled by unsigned flag and rounding. Can +# also be used with packed "SIMD" floats. + +define pcodeop FixedToFP; + +# FPConvert(fp, M, N [, rounding]) +# Convert floating point between from M-bit to N-bit precision. +# Can also be used with packed "SIMD" floats. Sometimes +# equivalent to float2float. M, N are the input and output sizes +# (16, 32, 64), implied by pseudocode, but given explicitly +# here. Rounding is only required when converting to integral +# type. + +define pcodeop FPConvert; + +# FPConvertInexact() +# At the end of any rounding or conversion operation, the +# pseudocode tests whether the converted value is identical to +# the original value. If it is not identical, and if the "exact" +# argument is true, then it sets the floating point exception +# FPEXC.Inexact bit. This function is understood to return 0/1 +# depending on whether converstion was exact (0) or inexact (1). +# + +define pcodeop FPConvertInexact; + +# FPToFixed(fp, M, N, fbits, unsigned, rounding) +# Convert M-bit floating point to N-bit fixed point with fbits +# fractional bits, controlled by unsigned flag and rounding. +# between different precisions. Can also be used with packed +# "SIMD" floats. + +define pcodeop FPToFixed; + +# FPRoundInt(fp, N, rounding, exact) +# Round fp to nearest integral floating point, controlled by +# rounding. If exact is true, set FPSR.IXC flag. Can also be +# used with packed "SIMD" floats. + +define pcodeop FPRoundInt; + +# PolynomialMult(op1, op2) + +define pcodeop PolynomialMult; + +####### +# AESD single round decryption + +# F6.1.1 p3235 A1/T1 +:aesd.8 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b00 & c1617=0b00 & c0611=0b001101 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001101 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qd | Qm); } + +####### +# AESE single round encryption + +# F6.1.2 p3237 A1/T1 +:aese.8 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b00 & c1617=0b00 & c0611=0b001100 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001100 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qd | Qm); } + +####### +# AESIMC inverse mix columns + +# F6.1.3 p3239 A1/T1 +:aesimc.8 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b00 & c1617=0b00 & c0611=0b001111 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001111 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qm); } + +####### +# AESMC mix columns + +# F6.1.4 p3240 A1/T1 +:aesmc.8 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b00 & c1617=0b00 & c0611=0b001110 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b00 & thv_c1617=0b00 & thv_c0611=0b001110 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qm); } + +####### +# SHA1C SHA1 hash update (choose) + +# F6.1.7 p3248 A1/T1 +:sha1c.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00100 & c2021=0b00 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA1H SHA1 fixed rotate + +# F6.1.8 p3250 A1/T1 +:sha1h.32 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b01 & c0611=0b001011 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b01 & thv_c0611=0b001011 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qm); } + +####### +# SHA1M SHA1 hash update (majority) + +# F6.1.9 p3251 A1/T1 +:sha1m.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00100 & c2021=0b10 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA1P SHA1 hash update (parity) + +# F6.1.10 p3253 A1/T1 +:sha1p.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00100 & c2021=0b01 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA1SU0 SHA1 schedule update 0 + +# F6.1.11 p3255 A1/T1 +:sha1su0.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00100 & c2021=0b11 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11110 & thv_c2021=0b11 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA1SU1 SHA1 schedule update 1 + +# F6.1.12 p3257 A1/T1 +:sha1su1.32 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b10 & c0611=0b001110 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c0611=0b001110 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qd,Qm); } + +####### +# SHA256H SHA256 hash update part 1 + +# F6.1.13 p3259 A1/T1 +:sha256h.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b00 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA256H2 SHA256 hash update part 2 + +# F6.1.14 p3260 A1/T1 +:sha256h2.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b01 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# SHA256SU0 SHA256 schedule update 0 + +# F6.1.15 p3261 A1/T1 +:sha256su0.32 Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b10 & c0611=0b001111 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c0611=0b001111 & thv_c0404=0)) + & Qd & Qm + { Qd = CryptOp(Qd,Qm); } + +####### +# SHA256SU1 SHA256 schedule update 1 + +# F6.1.16 p3263 A1/T1 +:sha256su1.32 Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b10 & c0811=0b1100 & c0606=1 & c0404=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1100 & thv_c0606=1 & thv_c0404=0)) + & Qn & Qd & Qm + { Qd = CryptOp(Qd,Qn,Qm); } + +####### +# The VCVT instructions are a large family for converting between +# floating point numbers and integers, of all sizes and combinations + +# F6.1.54 p3350 A1 cases size = 10 (c0809) +:vcvt^COND^".f64.f32" Dd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11011 & c1616=1 & c1011=0b10 & c0707=1 & c0606=1 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11011 & thv_c1616=1 & thv_c1011=0b10 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b10)) + & COND & Dd & Sm + { build COND; Dd = float2float(Sm); } + +# F6.1.54 p3350 A1 cases size = 11 (c0809) +:vcvt^COND^".f32.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11011 & c1616=1 & c1011=0b10 & c0707=1 & c0606=1 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11011 & thv_c1616=1 & thv_c1011=0b10 & thv_c0707=1 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b11)) + & COND & Sd & Dm + { build COND; Sd = float2float(Dm); } + +# F6.1.55 p3352 A1 op == 1 (c0808) +:vcvt.f32.f16 Qd,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b01 & c1617=0b10 & c0911=0b011 & c0607=0b00 & c0404=0 & c0808=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b01 & thv_c1617=0b10 & thv_c0911=0b011 & thv_c0607=0b00 & thv_c0404=0 & thv_c0808=1)) + & Qd & Dm + { + Qd = float2float(Dm:2); + } + +# F6.1.55 p3352 A1 op == 0 (c0808) +:vcvt.f16.f32 Dd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b01 & c1617=0b10 & c0911=0b011 & c0607=0b00 & c0404=0 & c0808=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b01 & thv_c1617=0b10 & thv_c0911=0b011 & thv_c0607=0b00 & thv_c0404=0 & thv_c0808=0)) + & Dd & Qm + { Dd = float2float(Qm); } + +vcvt_56_64_dt: ".f32.s32" + is ((TMode=0 & c0708=0b00) + | (TMode=1 & thv_c0708=0b00)) + & Dd & Dm + { Dd = FixedToFP(Dm, 32:1, 32:1, 0:1, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_56_64_dt: ".f32.u32" + is ((TMode=0 & c0708=0b01) + | (TMode=1 & thv_c0708=0b01)) + & Dd & Dm + { Dd = FixedToFP(Dm, 32:1, 32:1, 0:1, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_56_64_dt: ".s32.f32" + is ((TMode=0 & c0708=0b10) + | (TMode=1 & thv_c0708=0b10)) + & Dd & Dm + { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 0:1, $(FPRounding_ZERO)); } +vcvt_56_64_dt: ".u32.f32" + is ((TMode=0 & c0708=0b11) + | (TMode=1 & thv_c0708=0b11)) + & Dd & Dm + { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 1:1, $(FPRounding_ZERO)); } + +vcvt_56_128_dt: ".f32.s32" + is ((TMode=0 & c0708=0b00) + | (TMode=1 & thv_c0708=0b00)) + & Qd & Qm + { Qd = FixedToFP(Qm, 32:1, 32:1, 0:1, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_56_128_dt: ".f32.u32" + is ((TMode=0 & c0708=0b01) + | (TMode=1 & thv_c0708=0b01)) + & Qd & Qm + { Qd = FixedToFP(Qm, 32:1, 32:1, 0:1, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_56_128_dt: ".s32.f32" + is ((TMode=0 & c0708=0b10) + | (TMode=1 & thv_c0708=0b10)) + & Qd & Qm + { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 0:1, $(FPRounding_ZERO)); } +vcvt_56_128_dt: ".u32.f32" + is ((TMode=0 & c0708=0b11) + | (TMode=1 & thv_c0708=0b11)) + & Qd & Qm + { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 1:1, $(FPRounding_ZERO)); } + +# F6.1.56 p3354 A1 Q == 0 (c0606) +:vcvt^vcvt_56_64_dt Dd,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c0911=0b011 & c0404=0 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c0911=0b011 & thv_c0404=0 & thv_c0606=0)) + & vcvt_56_64_dt & Dd & Dm + { } + +# F6.1.56 p3354 A1 Q == 1 (c0606) +:vcvt^vcvt_56_128_dt Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c0911=0b011 & c0404=0 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c0911=0b011 & thv_c0404=0 & thv_c0606=1)) + & vcvt_56_128_dt & Qd & Qm + { } + +# F6.1.57 p3356 A1 opc2==100 && size==10 (c1618, c0809) +:vcvt^COND^".u32.f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b100 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b100 & thv_c0809=0b10)) + & COND & Sd & Sm + { build COND; Sd = zext(round(Sm)); } + +# F6.1.57 p3356 A1 opc2==101 && size==10 (c1618, c0809) +:vcvt^COND^".s32.f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b101 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b10)) + & COND & Sd & Sm + { build COND; Sd = sext(round(Sm)); } + +# F6.1.57 p3356 A1 opc2==100 && size==11 (c1618, c0809) +:vcvt^COND^".u32.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b100 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b100 & thv_c0809=0b11)) + & COND & Sd & Dm + { build COND; local tmp:8 = zext(round(Dm)); Sd = tmp:4; } + +# F6.1.57 p3356 A1 opc2==101 && size==11 (c1618, c0809) +:vcvt^COND^".s32.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b101 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b11)) + & COND & Sd & Dm + { build COND; local tmp:8 = sext(round(Dm)); Sd = tmp:4; } + +# The rounding mode depends on c0707=0 => FPSCR else ZERO + +vcvt_58_3232_dt: ".f32.u32" + is ((TMode=0 & c0708=0b00) + | (TMode=1 & thv_c0708=0b00)) + & Sd & Sm + { local tmp:8 = zext(Sm); Sd = int2float(tmp); } +vcvt_58_3232_dt: ".f32.s32" + is ((TMode=0 & c0708=0b01) + | (TMode=1 & thv_c0708=0b01)) + & Sd & Sm + { local tmp:8 = sext(Sm); Sd = int2float(tmp); } + +vcvt_58_6432_dt: ".f64.u32" + is ((TMode=0 & c0708=0b10) + | (TMode=1 & thv_c0708=0b10)) + & Dd & Sm + { local tmp:8 = zext(Sm); Dd = int2float(tmp); } +vcvt_58_6432_dt: ".f64.s32" + is ((TMode=0 & c0708=0b11) + | (TMode=1 & thv_c0708=0b11)) + & Dd & Sm + { local tmp:8 = sext(Sm); Dd = int2float(tmp); } + +# F6.1.58 p3359 A1 size == 10 (c0809) +:vcvt^COND^vcvt_58_3232_dt Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11100 & c1616=0 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11100 & thv_c1616=0 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b10)) + & COND & vcvt_58_3232_dt & Sd & Sm + { build COND; build vcvt_58_3232_dt; } + +# F6.1.58 p3359 A1 size == 11 (c0809) +:vcvt^COND^vcvt_58_6432_dt Dd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11100 & c1616=0 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11100 & thv_c1616=0 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b11)) + & COND & vcvt_58_6432_dt & Dd & Sm + { build COND; build vcvt_58_6432_dt; } + +vcvt_59_fbits_built: fbits is TMode=0 & c1621 [ fbits = 64 - c1621; ] { export * [const]:1 fbits; } +vcvt_59_fbits_built: fbits is TMode=1 & thv_c1621 [ fbits = 64 - thv_c1621; ] { export * [const]:1 fbits; } +vcvt_59_fbits: "#"^fbits is TMode=0 & c1621 [ fbits = 64 - c1621; ] { } +vcvt_59_fbits: "#"^fbits is TMode=1 & thv_c1621 [ fbits = 64 - thv_c1621; ] { } + +vcvt_59_32_dt: ".f32.s32" + is ((TMode=0 & c0808=0 & c2424=0) + | (TMode=1 & thv_c0808=0 & thv_c2828=0)) + & Dd & Dm & vcvt_59_fbits_built + { Dd = FixedToFP(Dm, 32:1, 32:1, vcvt_59_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_59_32_dt: ".f32.u32" + is ((TMode=0 & c0808=0 & c2424=1) + | (TMode=1 & thv_c0808=0 & thv_c2828=1)) + & Dd & Dm & vcvt_59_fbits_built + { Dd = FixedToFP(Dm, 32:1, 32:1, vcvt_59_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_59_32_dt: ".s32.f32" + is ((TMode=0 & c0808=1 & c2424=0) + | (TMode=1 & thv_c0808=1 & thv_c2828=0)) + & Dd & Dm & vcvt_59_fbits_built + { Dd = FPToFixed(Dm, 32:1, 32:1, vcvt_59_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_59_32_dt: ".u32.f32" + is ((TMode=0 & c0808=1 & c2424=1) + | (TMode=1 & thv_c0808=1 & thv_c2828=1)) + & Dd & Dm & vcvt_59_fbits_built + { Dd = FPToFixed(Dm, 32:1, 32:1, vcvt_59_fbits_built, 1:1, $(FPRounding_ZERO)); } + +vcvt_59_64_dt: ".f32.s32" + is ((TMode=0 & c0808=0 & c2424=0) + | (TMode=1 & thv_c0808=0 & thv_c2828=0)) + & Qd & Qm & vcvt_59_fbits_built + { Qd = FixedToFP(Qm, 32:1, 32:1, vcvt_59_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_59_64_dt: ".f32.u32" + is ((TMode=0 & c0808=0 & c2424=1) + | (TMode=1 & thv_c0808=0 & thv_c2828=1)) + & Qd & Qm & vcvt_59_fbits_built + { Qd = FixedToFP(Qm, 32:1, 32:1, vcvt_59_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_59_64_dt: ".s32.f32" + is ((TMode=0 & c0808=1 & c2424=0) + | (TMode=1 & thv_c0808=1 & thv_c2828=0)) + & Qd & Qm & vcvt_59_fbits_built + { Qd = FPToFixed(Qm, 32:1, 32:1, vcvt_59_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_59_64_dt: ".u32.f32" + is ((TMode=0 & c0808=1 & c2424=1) + | (TMode=1 & thv_c0808=1 & thv_c2828=1)) + & Qd & Qm & vcvt_59_fbits_built + { Qd = FPToFixed(Qm, 32:1, 32:1, vcvt_59_fbits_built, 1:1, $(FPRounding_ZERO)); } + +# Should add rounding here, if dt2 is s32 or u32 then rounding is +# FPRounding_ZERO otherwise FPROunding_TIEEVEN + +# F6.1.59 p3361 A1 Q = 0 (c0606) +:vcvt^vcvt_59_32_dt Dd,Dm,vcvt_59_fbits + is ((TMode=0 & c2831=0b1111 & c2527=0b001 & c2323=1 & c2121=1 & c0911=0b111 & c0707=0 & c0404=1 & c0606=0) + | (TMode=1 & thv_c2931=0b111 & thv_c2327=0b11111 & thv_c2121=1 & thv_c0911=0b111 & thv_c0707=0 & thv_c0404=1 & thv_c0606=0)) + & vcvt_59_32_dt & vcvt_59_fbits & Dd & Dm + { } + +# F6.1.59 p3361 A1 Q = 1 (c0606) +:vcvt^vcvt_59_64_dt Qd,Qm,vcvt_59_fbits + is ((TMode=0 & c2831=0b1111 & c2527=0b001 & c2323=1 & c2121=1 & c0911=0b111 & c0707=0 & c0404=1 & c0606=1) + | (TMode=1 & thv_c2931=0b111 & thv_c2327=0b11111 & thv_c2121=1 & thv_c0911=0b111 & thv_c0707=0 & thv_c0404=1 & thv_c0606=1)) + & vcvt_59_64_dt & vcvt_59_fbits & Qd & Qm + { } + +vcvt_60_fbits_built: fbits is TMode=0 & c0707=0 & c0505 & c0003 [fbits = 16 - ( c0003 * 2 + c0505); ] { export * [const]:1 fbits; } +vcvt_60_fbits_built: fbits is TMode=1 & thv_c0707=0 & thv_c0505 & thv_c0003 [fbits = 16 - (thv_c0003 * 2 + thv_c0505); ] { export * [const]:1 fbits; } +vcvt_60_fbits_built: fbits is TMode=0 & c0707=1 & c0505 & c0003 [fbits = 32 - ( c0003 * 2 + c0505); ] { export * [const]:1 fbits; } +vcvt_60_fbits_built: fbits is TMode=1 & thv_c0707=1 & thv_c0505 & thv_c0003 [fbits = 32 - (thv_c0003 * 2 + thv_c0505); ] { export * [const]:1 fbits; } +vcvt_60_fbits: "#"^fbits is TMode=0 & c0707=0 & c0505 & c0003 [fbits = 16 - ( c0003 * 2 + c0505); ] { } +vcvt_60_fbits: "#"^fbits is TMode=1 & thv_c0707=0 & thv_c0505 & thv_c0003 [fbits = 16 - (thv_c0003 * 2 + thv_c0505); ] { } +vcvt_60_fbits: "#"^fbits is TMode=0 & c0707=1 & c0505 & c0003 [fbits = 32 - ( c0003 * 2 + c0505); ] { } +vcvt_60_fbits: "#"^fbits is TMode=1 & thv_c0707=1 & thv_c0505 & thv_c0003 [fbits = 32 - (thv_c0003 * 2 + thv_c0505); ] { } + +vcvt_60_32_dt: ".f32.s16" + is ((TMode=0 & c1818=0 & c1616=0 & c0809=0b10 & c0707=0) + | (TMode=1 & thv_c1818=0 & thv_c1616=0 & thv_c0809=0b10 & thv_c0707=0)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FixedToFP(Sd2, 16:1, 32:1, vcvt_60_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_60_32_dt: ".f32.s32" + is ((TMode=0 & c1818=0 & c1616=0 & c0809=0b10 & c0707=1) + | (TMode=1 & thv_c1818=0 & thv_c1616=0 & thv_c0809=0b10 & thv_c0707=1)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FixedToFP(Sd2, 32:1, 32:1, vcvt_60_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_60_32_dt: ".f32.u16" + is ((TMode=0 & c1818=0 & c1616=1 & c0809=0b10 & c0707=0) + | (TMode=1 & thv_c1818=0 & thv_c1616=1 & thv_c0809=0b10 & thv_c0707=0)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FixedToFP(Sd2, 16:1, 32:1, vcvt_60_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_60_32_dt: ".f32.u32" + is ((TMode=0 & c1818=0 & c1616=1 & c0809=0b10 & c0707=1) + | (TMode=1 & thv_c1818=0 & thv_c1616=1 & thv_c0809=0b10 & thv_c0707=1)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FixedToFP(Sd2, 32:1, 32:1, vcvt_60_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_60_32_dt: ".s16.f32" + is ((TMode=0 & c1818=1 & c1616=0 & c0809=0b10 & c0707=0) + | (TMode=1 & thv_c1818=1 & thv_c1616=0 & thv_c0809=0b10 & thv_c0707=0)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FPToFixed(Sd2, 32:1, 16:1, vcvt_60_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_60_32_dt: ".s32.f32" + is ((TMode=0 & c1818=1 & c1616=0 & c0809=0b10 & c0707=1) + | (TMode=1 & thv_c1818=1 & thv_c1616=0 & thv_c0809=0b10 & thv_c0707=1)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FPToFixed(Sd2, 32:1, 32:1, vcvt_60_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_60_32_dt: ".u16.f32" + is ((TMode=0 & c1818=1 & c1616=1 & c0809=0b10 & c0707=0) + | (TMode=1 & thv_c1818=1 & thv_c1616=1 & thv_c0809=0b10 & thv_c0707=0)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FPToFixed(Sd2, 32:1, 16:1, vcvt_60_fbits_built, 1:1, $(FPRounding_ZERO)); } +vcvt_60_32_dt: ".u32.f32" + is ((TMode=0 & c1818=1 & c1616=1 & c0809=0b10 & c0707=1) + | (TMode=1 & thv_c1818=1 & thv_c1616=1 & thv_c0809=0b10 & thv_c0707=1)) + & Sd & Sd2 & vcvt_60_fbits_built + { Sd = FPToFixed(Sd2, 32:1, 32:1, vcvt_60_fbits_built, 1:1, $(FPRounding_ZERO)); } + +vcvt_60_64_dt: ".f64.s16" + is ((TMode=0 & c1818=0 & c1616=0 & c0809=0b11 & c0707=0) + | (TMode=1 & thv_c1818=0 & thv_c1616=0 & thv_c0809=0b11 & thv_c0707=0)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FixedToFP(Dd2, 16:1, 64:1, vcvt_60_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_60_64_dt: ".f64.s32" + is ((TMode=0 & c1818=0 & c1616=0 & c0809=0b11 & c0707=1) + | (TMode=1 & thv_c1818=0 & thv_c1616=0 & thv_c0809=0b11 & thv_c0707=1)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FixedToFP(Dd2, 32:1, 64:1, vcvt_60_fbits_built, 0:1, $(FPRounding_TIEEVEN)); } +vcvt_60_64_dt: ".f64.u16" + is ((TMode=0 & c1818=0 & c1616=1 & c0809=0b11 & c0707=0) + | (TMode=1 & thv_c1818=0 & thv_c1616=1 & thv_c0809=0b11 & thv_c0707=0)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FixedToFP(Dd2, 16:1, 64:1, vcvt_60_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_60_64_dt: ".f64.u32" + is ((TMode=0 & c1818=0 & c1616=1 & c0809=0b11 & c0707=1) + | (TMode=1 & thv_c1818=0 & thv_c1616=1 & thv_c0809=0b11 & thv_c0707=1)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FixedToFP(Dd2, 32:1, 64:1, vcvt_60_fbits_built, 1:1, $(FPRounding_TIEEVEN)); } +vcvt_60_64_dt: ".s16.f64" + is ((TMode=0 & c1818=1 & c1616=0 & c0809=0b11 & c0707=0) + | (TMode=1 & thv_c1818=1 & thv_c1616=0 & thv_c0809=0b11 & thv_c0707=0)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FPToFixed(Dd2, 64:1, 16:1, vcvt_60_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_60_64_dt: ".s32.f64" + is ((TMode=0 & c1818=1 & c1616=0 & c0809=0b11 & c0707=1) + | (TMode=1 & thv_c1818=1 & thv_c1616=0 & thv_c0809=0b11 & thv_c0707=1)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FPToFixed(Dd2, 64:1, 32:1, vcvt_60_fbits_built, 0:1, $(FPRounding_ZERO)); } +vcvt_60_64_dt: ".u16.f64" + is ((TMode=0 & c1818=1 & c1616=1 & c0809=0b11 & c0707=0) + | (TMode=1 & thv_c1818=1 & thv_c1616=1 & thv_c0809=0b11 & thv_c0707=0)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FPToFixed(Dd2, 64:1, 16:1, vcvt_60_fbits_built, 1:1, $(FPRounding_ZERO)); } +vcvt_60_64_dt: ".u32.f64" + is ((TMode=0 & c1818=1 & c1616=1 & c0809=0b11 & c0707=1) + | (TMode=1 & thv_c1818=1 & thv_c1616=1 & thv_c0809=0b11 & thv_c0707=1)) + & Dd & Dd2 & vcvt_60_fbits_built + { Dd = FPToFixed(Dd2, 64:1, 32:1, vcvt_60_fbits_built, 1:1, $(FPRounding_ZERO)); } + +# F6.1.60 p3364 A1 op=0/1 sf=10 (c1818, c0809) +:vcvt^COND^vcvt_60_32_dt Sd,Sd2,vcvt_60_fbits + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1717=1 & c1011=0b10 & c0606=1 & c0404=0 & c1818 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1717=1 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c1818 & thv_c0809=0b10)) + & COND & vcvt_60_fbits & vcvt_60_32_dt & Sd & Sd2 + { build COND; build vcvt_60_32_dt; } + +# F6.1.60 p3364 A1 op=0/1 sf=11 (c1818, c0809) +:vcvt^COND^vcvt_60_64_dt Dd,Dd2,vcvt_60_fbits + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1717=1 & c1011=0b10 & c0606=1 & c0404=0 & c1818 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1717=1 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c1818 & thv_c0809=0b11)) + & COND & vcvt_60_fbits & vcvt_60_64_dt & Dd & Dd2 + { build COND; build vcvt_60_64_dt; } + +# vcvta, vcvtm, vcvtn, and vcvtp + +vcvt_amnp_simd_RM: "a" + is ((TMode=0 & c0809=0b00) + | (TMode=1 & thv_c0809=0b00)) + { export $(FPRounding_TIEAWAY); } +vcvt_amnp_simd_RM: "n" + is ((TMode=0 & c0809=0b01) + | (TMode=1 & thv_c0809=0b01)) + { export $(FPRounding_TIEEVEN); } +vcvt_amnp_simd_RM: "p" + is ((TMode=0 & c0809=0b10) + | (TMode=1 & thv_c0809=0b10)) + { export $(FPRounding_POSINF); } +vcvt_amnp_simd_RM: "m" + is ((TMode=0 & c0809=0b11) + | (TMode=1 & thv_c0809=0b11)) + { export $(FPRounding_NEGINF); } + +# These RM values need to be converted properly +vcvt_amnp_simd_64_dt: ".s32" is TMode=0 & c0707=0 & c0809 & vcvt_amnp_simd_RM & Dd & Dm { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_64_dt: ".s32" is TMode=1 & thv_c0707=0 & thv_c0809 & vcvt_amnp_simd_RM & Dd & Dm { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_64_dt: ".u32" is TMode=0 & c0707=1 & c0809 & vcvt_amnp_simd_RM & Dd & Dm { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_64_dt: ".u32" is TMode=1 & thv_c0707=1 & thv_c0809 & vcvt_amnp_simd_RM & Dd & Dm { Dd = FPToFixed(Dm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_simd_RM); } + +vcvt_amnp_simd_128_dt: ".s32" is TMode=0 & c0707=0 & c0809 & vcvt_amnp_simd_RM & Qd & Qm { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_128_dt: ".s32" is TMode=1 & thv_c0707=0 & thv_c0809 & vcvt_amnp_simd_RM & Qd & Qm { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_128_dt: ".u32" is TMode=0 & c0707=1 & c0809 & vcvt_amnp_simd_RM & Qd & Qm { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_simd_RM); } +vcvt_amnp_simd_128_dt: ".u32" is TMode=1 & thv_c0707=1 & thv_c0809 & vcvt_amnp_simd_RM & Qd & Qm { Qd = FPToFixed(Qm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_simd_RM); } + +# F6.1.61,64,66,68 p3367,3374,3378,3384 A1 64-bit SIMD vector variant Q = 0 (c0606) +:vcvt^vcvt_amnp_simd_RM^vcvt_amnp_simd_64_dt^".f32" Dd,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c1011=0b00 & c0404=0 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c1011=0b00 & thv_c0404=0 & thv_c0606=0)) + & vcvt_amnp_simd_RM & vcvt_amnp_simd_64_dt & Dd & Dm + { } + +# F6.1.61,64,66,68 p3367,3374,3378,3384 A1 128-bit SIMD vector variant Q = 1(c0606) +:vcvt^vcvt_amnp_simd_RM^vcvt_amnp_simd_128_dt^".f32" Qd,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c1011=0b00 & c0404=0 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c1011=0b00 & thv_c0404=0 & thv_c0606=1)) + & vcvt_amnp_simd_RM & vcvt_amnp_simd_128_dt & Qd & Qm + { } + +vcvt_amnp_fp_RM: "a" + is ((TMode=0 & c1617=0b00) + | (TMode=1 & thv_c1617=0b00)) + { export $(FPRounding_TIEAWAY); } +vcvt_amnp_fp_RM: "n" + is ((TMode=0 & c1617=0b01) + | (TMode=1 & thv_c1617=0b01)) + { export $(FPRounding_TIEEVEN); } +vcvt_amnp_fp_RM: "p" + is ((TMode=0 & c1617=0b10) + | (TMode=1 & thv_c1617=0b10)) + { export $(FPRounding_POSINF); } +vcvt_amnp_fp_RM: "m" + is ((TMode=0 & c1617=0b11) + | (TMode=1 & thv_c1617=0b11)) + { export $(FPRounding_NEGINF); } + +vcvt_amnp_fp_s_dt: ".u32" is TMode=0 & c0707=0 & c1617 & vcvt_amnp_fp_RM & Sd & Sm { Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_s_dt: ".u32" is TMode=1 & thv_c0707=0 & thv_c1617 & vcvt_amnp_fp_RM & Sd & Sm { Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 1:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_s_dt: ".s32" is TMode=0 & c0707=1 & c1617 & vcvt_amnp_fp_RM & Sd & Sm { Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_s_dt: ".s32" is TMode=1 & thv_c0707=1 & thv_c1617 & vcvt_amnp_fp_RM & Sd & Sm { Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 0:1, vcvt_amnp_fp_RM); } + +vcvt_amnp_fp_d_dt: ".u32" is TMode=0 & c0707=0 & c1617 & vcvt_amnp_fp_RM & Sd & Dm { Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 1:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_d_dt: ".u32" is TMode=1 & thv_c0707=0 & thv_c1617 & vcvt_amnp_fp_RM & Sd & Dm { Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 1:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_d_dt: ".s32" is TMode=0 & c0707=1 & c1617 & vcvt_amnp_fp_RM & Sd & Dm { Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 0:1, vcvt_amnp_fp_RM); } +vcvt_amnp_fp_d_dt: ".s32" is TMode=1 & thv_c0707=1 & thv_c1617 & vcvt_amnp_fp_RM & Sd & Dm { Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 0:1, vcvt_amnp_fp_RM); } + +# F6.1.62,65,67,69 p3369,3376,3380,3384 Single-precision scalar variant size = 11 (c0809) +:vcvt^vcvt_amnp_fp_RM^vcvt_amnp_fp_s_dt^".f32" Sd,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b11 & c1819=0b11 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b11 & thv_c1819=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b10)) + & vcvt_amnp_fp_RM & vcvt_amnp_fp_s_dt & Sd & Sm + { } + +# F6.1.62,65,67,69 p3369,3376,3380,3384 Double-precision scalar variant size = 10 (c0809) +:vcvt^vcvt_amnp_fp_RM^vcvt_amnp_fp_d_dt^".f64" Sd,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b11 & c1819=0b11 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b11 & thv_c1819=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b11)) + & vcvt_amnp_fp_RM & vcvt_amnp_fp_d_dt & Sd & Dm + { } + +# vcvtb and vcvtt + +vcvt_bt3216_op: "b" + is ((TMode=0 & c0707=0) + | (TMode=1 & thv_c0707=0)) + & Sd & Sm + { Sd = float2float(Sm:2); } +vcvt_bt3216_op: "t" + is ((TMode=0 & c0707=1) + | (TMode=1 & thv_c0707=1)) + & Sd & Sm + { w:2 = Sm(2); Sd = float2float(w); } + +vcvt_bt6416_op: "b" + is ((TMode=0 & c0707=0) + | (TMode=1 & thv_c0707=0)) + & Dd & Sm + { Dd = float2float(Sm:2); } +vcvt_bt6416_op: "t" + is ((TMode=0 & c0707=1) + | (TMode=1 & thv_c0707=1)) + & Dd & Sm + { w:2 = Sm(2); Dd = float2float(w); } + +vcvt_bt1632_op: "b" + is ((TMode=0 & c0707=0) + | (TMode=1 & thv_c0707=0)) + & Sd & Sm + { Sd[0,16] = float2float(Sm); } +vcvt_bt1632_op: "t" + is ((TMode=0 & c0707=1) + | (TMode=1 & thv_c0707=1)) + & Sd & Sm + { tmp:2 = float2float(Sm); Sd = (zext(tmp)<<16) | zext(Sd[0,16]); } + +vcvt_bt1664_op: "b" + is ((TMode=0 & c0707=0) + | (TMode=1 & thv_c0707=0)) + & Sd & Dm + { Sd[0,16] = float2float(Dm); } +vcvt_bt1664_op: "t" + is ((TMode=0 & c0707=1) + | (TMode=1 & thv_c0707=1)) + & Sd & Dm + { tmp:2 = float2float(Dm); Sd = (zext(tmp)<<16) | zext(Sd[0,16]); } + +# F6.1.63 p3371 A1 cases op:sz = 00 (c1616, c0808) +# F6.1.71 p3389 A1 cases op:sz = 00 (c1616, c0808) +:vcvt^vcvt_bt3216_op^COND^".f32.f16" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11001 & c0911=0b101 & c0606=1 & c0404=0 & c1616=0 & c0808=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11001 & thv_c0911=0b101 & thv_c0606=1 & thv_c0404=0 & thv_c1616=0 & thv_c0808=0)) + & COND & vcvt_bt3216_op & Sd & Sm + { build COND; build vcvt_bt3216_op; } + +# F6.1.63 p3371 A1 cases op:sz = 01 (c1616, c0808) +# F6.1.71 p3389 A1 cases op:sz = 01 (c1616, c0808) +:vcvt^vcvt_bt6416_op^COND^".f64.f16" Dd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11001 & c0911=0b101 & c0606=1 & c0404=0 & c1616=0 & c0808=1) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11001 & thv_c0911=0b101 & thv_c0606=1 & thv_c0404=0 & thv_c1616=0 & thv_c0808=1)) + & COND & vcvt_bt6416_op & Dd & Sm + { build COND; build vcvt_bt6416_op; } + +# F6.1.63 p3371 A1 cases op:sz = 10 (c1616, c0808) +# F6.1.71 p3389 A1 cases op:sz = 10 (c1616, c0808) +:vcvt^vcvt_bt1632_op^COND^".f16.f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11001 & c0911=0b101 & c0606=1 & c0404=0 & c1616=1 & c0808=0) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11001 & thv_c0911=0b101 & thv_c0606=1 & thv_c0404=0 & thv_c1616=1 & thv_c0808=0)) + & COND & vcvt_bt1632_op & Sd & Sm + { build COND; build vcvt_bt1632_op; } + +# F6.1.63 p3371 A1 cases op:sz = 11 (c1616, c0808) +# F6.1.71 p3389 A1 cases op:sz = 11 (c1616, c0808) +:vcvt^vcvt_bt1664_op^COND^".f16.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1721=0b11001 & c0911=0b101 & c0606=1 & c0404=0 & c1616=1 & c0808=1) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1721=0b11001 & thv_c0911=0b101 & thv_c0606=1 & thv_c0404=0 & thv_c1616=1 & thv_c0808=1)) + & COND & vcvt_bt1664_op & Sd & Dm + { build COND; build vcvt_bt1664_op; } + +# vcvtr + +# F6.1.70 p3386 A1 case opc2=100 size=10 (c1618, c0809) +:vcvtr^COND^".u32.f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b01 & c0404=0 & c1618=0b100 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c1618=0b100 & thv_c0809=0b10)) + & COND & Sd & Sm + { build COND; Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 1:1, $(FPSCR_RMODE)); } + +# F6.1.70 p3386 A1 case opc2=101 size=10 +:vcvtr^COND^".s32.f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b01 & c0404=0 & c1618=0b101 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b10)) + & COND & Sd & Sm + { build COND; Sd = FPToFixed(Sm, 32:1, 32:1, 0:1, 0:1, $(FPSCR_RMODE)); } + +# F6.1.70 p3386 A1 case opc2=100 size=11 +:vcvtr^COND^".u32.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b01 & c0404=0 & c1618=0b100 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c1618=0b100 & thv_c0809=0b11)) + & COND & Sd & Dm + { build COND; Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 1:1, $(FPSCR_RMODE)); } + +# F6.1.70 p3386 A1 case opc2=101 size=11 +:vcvtr^COND^".s32.f64" Sd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b01 & c0404=0 & c1618=0b101 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b11)) + & COND & Sd & Dm + { build COND; Sd = FPToFixed(Dm, 64:1, 32:1, 0:1, 0:1, $(FPSCR_RMODE)); } + +####### +# VMAXNM/VMINNM + + +# FPMaxNum(Vn, Vm) +# Return the maximum of two floating point numbers. +# Includes FP and SIMD variants of all lane sizes. + +define pcodeop FPMaxNum; + +# FPMinNum(Vn, Vm) +# Return the minimum of two floating point numbers. +# Includes FP and SIMD variants of all lane sizes. + +define pcodeop FPMinNum; + +# F6.1.101 p3471 A1/T1 Q = 0 (c0606) +:vmaxnm^".f32" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b00 & c0811=0b1111 & c0404=1 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=0)) + & Dd & Dn & Dm + { Dd = FPMaxNum(Dn, Dm); } + +# F6.1.101 p3471 A1/T1 Q = 1 (c0606) +:vmaxnm^".f32" Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b00 & c0811=0b1111 & c0404=1 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b00 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=1)) + & Qd & Qn & Qm + { Qd = FPMaxNum(Qn, Qm); } + +# F6.1.101 p3471 A1/T1 Q = 0 (c0606) +:vmaxnm^".f16" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b01 & c0811=0b1111 & c0404=1 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=0)) + & Dd & Dn & Dm + { Dd = FPMaxNum(Dn, Dm); } + +# F6.1.101 p3471 A1/T1 Q = 1 (c0606) +:vmaxnm^".f16" Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b01 & c0811=0b1111 & c0404=1 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b01 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=1)) + & Qd & Qn & Qm + { Qd = FPMaxNum(Qn, Qm); } + +# F6.1.101 p3471 A2/T2 size = 01 (c0809) +:vmaxnm^".f16" Sd,Sn,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=0 & c0404=0 & c0809=0b01) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=0 & thv_c0404=0 & thv_c0809=0b01)) + & Sd & Sn & Sm + { Sd = FPMaxNum(Sn, Sm); } + +# F6.1.101 p3471 A2/T2 size = 10 (c0809) +:vmaxnm^".f32" Sd,Sn,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=0 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=0 & thv_c0404=0 & thv_c0809=0b10)) + & Sd & Sn & Sm + { Sd = FPMaxNum(Sn, Sm); } + +# F6.1.101 p3471 A2/T2 size = 11 (c0809) +:vmaxnm^".f64" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=0 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=0 & thv_c0404=0 & thv_c0809=0b11)) + & Dd & Dn & Dm + { Dd = FPMaxNum(Dn, Dm); } + +# F6.1.104 p3478 A1/T1 Q = 0 (c0606) +:vminnm^".f32" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b10 & c0811=0b1111 & c0404=1 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=0)) + & Dd & Dn & Dm + { Dd = FPMinNum(Dn, Dm); } + +# F6.1.104 p3478 A1/T1 Q = 1 (c0606) +:vminnm^".f32" Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b10 & c0811=0b1111 & c0404=1 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b10 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=1)) + & Qd & Qn & Qm + { Qd = FPMinNum(Qn, Qm); } + +# F6.1.104 p3478 A1/T1 Q = 0 (c0606) +:vminnm^".f16" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b11 & c0811=0b1111 & c0404=1 & c0606=0) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b11 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=0)) + & Dd & Dn & Dm + { Dd = FPMinNum(Dn, Dm); } + +# F6.1.104 p3478 A1/T1 Q = 1 (c0606) +:vminnm^".f16" Qd,Qn,Qm + is ((TMode=0 & c2831=0b1111 & c2327=0b00110 & c2021=0b11 & c0811=0b1111 & c0404=1 & c0606=1) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11110 & thv_c2021=0b11 & thv_c0811=0b1111 & thv_c0404=1 & thv_c0606=1)) + & Qd & Qn & Qm + { Qd = FPMinNum(Qn, Qm); } + +# F6.1.104 p3478 A2/T2 size = 01 (c0809) +:vminnm^".f16" Sd,Sn,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b01) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b01)) + & Sd & Sn & Sm + { Sd = FPMinNum(Sn, Sm); } + +# F6.1.104 p3478 A2/T2 size = 10 (c0809) +:vminnm^".f32" Sd,Sn,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b10)) + & Sd & Sn & Sm + { Sd = FPMinNum(Sn, Sm); } + +# F6.1.104 p3478 A2/T2 size = 11 (c0809) +:vminnm^".f64" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b00 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b00 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b11)) + & Dd & Dn & Dm + { Dd = FPMinNum(Dn, Dm); } + +####### +# VMULL instructions vector/polynomial multiplication + +vmull_dt: ".s8" + is ((TMode=0 & c0909=0 & c2424=0 & c2021=0b00) + | (TMode=1 & thv_c0909=0 & thv_c2828=0 & thv_c2021=0b00)) + { } + +vmull_dt: ".s16" + is ((TMode=0 & c0909=0 & c2424=0 & c2021=0b01) + | (TMode=1 & thv_c0909=0 & thv_c2828=0 & thv_c2021=0b01)) + { } + +vmull_dt: ".s32" + is ((TMode=0 & c0909=0 & c2424=0 & c2021=0b10) + | (TMode=1 & thv_c0909=0 & thv_c2828=0 & thv_c2021=0b10)) + { } + +vmull_dt: ".u8" + is ((TMode=0 & c0909=0 & c2424=1 & c2021=0b00) + | (TMode=1 & thv_c0909=0 & thv_c2828=1 & thv_c2021=0b00)) + { } + +vmull_dt: ".u16" + is ((TMode=0 & c0909=0 & c2424=1 & c2021=0b01) + | (TMode=1 & thv_c0909=0 & thv_c2828=1 & thv_c2021=0b01)) + { } + +vmull_dt: ".u32" + is ((TMode=0 & c0909=0 & c2424=1 & c2021=0b10) + | (TMode=1 & thv_c0909=0 & thv_c2828=1 & thv_c2021=0b10)) + { } + +vmull_dt: ".p8" + is ((TMode=0 & c0909=1 & c2424=0 & c2021=0b00) + | (TMode=1 & thv_c0909=1 & thv_c2828=0 & thv_c2021=0b00)) + { } + +vmull_dt: ".p64" + is ((TMode=0 & c0909=1 & c2424=0 & c2021=0b10) + | (TMode=1 & thv_c0909=1 & thv_c2828=0 & thv_c2021=0b10)) + { } + +# F6.1.130 p3537 VMULL (-integer and +polynomial) op=1 (c0909) (with condition U!=1 and size!=0b11 and size!=01) +:vmull^vmull_dt Qd,Dn,Dm + is ((TMode=0 & c2531=0b1111001 & c2424=0 & c2323=1 & ( c2121 & c2020=0) & c1011=0b11 & c0808=0 & c0606=0 & c0404=0 & c0909=1) + | (TMode=1 & thv_c2931=0b111 & thv_c2828=0 & thv_c2327=0b11111 & (thv_c2121 & thv_c2020=0) & thv_c1011=0b11 & thv_c0808=0 & thv_c0606=0 & thv_c0404=0 & thv_c0909=1)) + & vmull_dt & Qd & Dn & Dm + { Qd = PolynomialMult(Dn, Dm); } + +# F6.1.130 p3537 VMULL (+integer and -polynomial) op=0 (c0909) (with condition size!=0b11) +:vmull^vmull_dt Qd,Dn,Dm + is ((TMode=0 & c2531=0b1111001 & c2424 & c2323=1 & ( c2121=0 | c2020=0) & c1011=0b11 & c0808=0 & c0606=0 & c0404=0 & c0909=0) + | (TMode=1 & thv_c2931=0b111 & thv_c2828 & thv_c2327=0b11111 & (thv_c2121=0 | thv_c2020=0) & thv_c1011=0b11 & thv_c0808=0 & thv_c0606=0 & thv_c0404=0 & thv_c0909=0)) + & vmull_dt & Qd & Dn & Dm + { Qd = VectorMultiply(Dn, Dm); } + +####### +# The VRINT instructions round a "floating-point to an integral +# floating point value of the same size", i.e. trunc. +# The arguments are +# 1: floating point value (can be 2 packed in a Q register) +# 2: rounding mode +# 3: boolean exact, if true then raise the Inexact exception if the +# result differs from the original + +vrint_simd_RM: "a" + is ((TMode=0 & c0709=0b010) + | (TMode=1 & thv_c0709=0b010)) + { export $(FPRounding_TIEAWAY); } + +vrint_simd_RM: "m" + is ((TMode=0 & c0709=0b101) + | (TMode=1 & thv_c0709=0b101)) + { export $(FPRounding_NEGINF); } + +vrint_simd_RM: "n" + is ((TMode=0 & c0709=0b000) + | (TMode=1 & thv_c0709=0b000)) + { export $(FPRounding_TIEEVEN); } + +vrint_simd_RM: "p" + is ((TMode=0 & c0709=0b111) + | (TMode=1 & thv_c0709=0b111)) + { export $(FPRounding_POSINF); } + +vrint_simd_RM: "x" + is ((TMode=0 & c0709=0b001) + | (TMode=1 & thv_c0709=0b001)) + { export $(FPRounding_TIEEVEN); } + +vrint_simd_RM: "z" + is ((TMode=0 & c0709=0b011) + | (TMode=1 & thv_c0709=0b011)) + { export $(FPRounding_ZERO); } + +# For vrintx, the exact flag is 1, and the IXF flag is set (inexact) + +vrint_simd_exact: "x" + is ((TMode=0 & c0709=0b001) + | (TMode=1 & thv_c0709=0b001)) + { export 1:1; } + +vrint_simd_exact: + is ((TMode=0 & ( c0707=1 | c0808=1 | c0909=0)) + | (TMode=1 & ( thv_c0707=1 | thv_c0808=1 | thv_c0909=0))) + { export 0:1; } + +vrint_simd_ixf: + is ((TMode=0 & c0709=0b001) + | (TMode=1 & thv_c0709=0b001)) + { $(FPEXC_IXF) = FPConvertInexact(); } + +vrint_simd_ixf: + is ((TMode=0 & ( c0707=1 | c0808=1 | c0909=0)) + | (TMode=1 & ( thv_c0707=1 | thv_c0808=1 | thv_c0909=0))) + { } + + +# F6.1.178,180,182,184,187,189 p3646,3650,3654,3658,3664,3668 Q = 0 (c0606) +:vrint^vrint_simd_RM^".f32" Dd,Dm + is ((TMode=0 & c2331=0b111100111 & c2021=0b11 & c1819=0b10 & c1617=0b10 & c1011=0b01 & (( c0707=0 & c0909=0) | ( c0707=1 & c0909=1) | ( c0707=1 & c0909=0)) & c0404=0 & c0606=0) + | (TMode=1 & thv_c2331=0b111111111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c1011=0b01 & ((thv_c0707=0 & thv_c0909=0) | (thv_c0707=1 & thv_c0909=1) | (thv_c0707=1 & thv_c0909=0)) & thv_c0404=0 & thv_c0606=0)) + & vrint_simd_RM & vrint_simd_exact & vrint_simd_ixf & Dd & Dm + { Dd = FPRoundInt(Dm, 32:1, vrint_simd_RM, 0:1); build vrint_simd_ixf; } + +# F6.1.178,180,182,184,187,189 p3646,3650,3654,3658,3664,3668 Q = 1 (c0606) +:vrint^vrint_simd_RM^".f32" Qd,Qm + is ((TMode=0 & c2331=0b111100111 & c2021=0b11 & c1819=0b10 & c1617=0b10 & c1011=0b01 & c0404=0 & c0606=1) + | (TMode=1 & thv_c2331=0b111111111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b10 & thv_c1011=0b01 & thv_c0404=0 & thv_c0606=1)) + & vrint_simd_RM & vrint_simd_exact & vrint_simd_ixf & Qd & Qm + { Qd = FPRoundInt(Qm, 32:1, vrint_simd_RM, 0:1); build vrint_simd_ixf; } + +vrint_fp_RM: "a" + is ((TMode=0 & c1617=0b00) + | (TMode=1 & thv_c1617=0b00)) + { export $(FPRounding_TIEAWAY); } + +vrint_fp_RM: "m" + is ((TMode=0 & c1617=0b11) + | (TMode=1 & thv_c1617=0b11)) + { export $(FPRounding_NEGINF); } + +vrint_fp_RM: "n" + is ((TMode=0 & c1617=0b01) + | (TMode=1 & thv_c1617=0b01)) + { export $(FPRounding_TIEEVEN); } + +vrint_fp_RM: "p" + is ((TMode=0 & c1617=0b10) + | (TMode=1 & thv_c1617=0b10)) + { export $(FPRounding_POSINF); } + +# F6.1.179,181,183,185 p3648,3652,3656,3660 size = 10 (c0809) +:vrint^vrint_fp_RM^".f32" Sd,Sm + is ((TMode=0 & c2331=0b111111101 & c1821=0b1110 & c1011=0b10 & c0607=0b01 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2331=0b111111101 & thv_c1821=0b1110 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c0809=0b10)) + & vrint_fp_RM & Sd & Sm + { Sd = FPRoundInt(Sm, 32:1, vrint_fp_RM, 0:1); } + +# F6.1.179,181,183,185 p3648,3652,3656,3660 size = 11 (c0809) +:vrint^vrint_fp_RM^".f64" Dd,Dm + is ((TMode=0 & c2331=0b111111101 & c1821=0b1110 & c1011=0b10 & c0607=0b01 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2331=0b111111101 & thv_c1821=0b1110 & thv_c1011=0b10 & thv_c0607=0b01 & thv_c0404=0 & thv_c0809=0b11)) + & vrint_fp_RM & Dd & Dm + { Dd = FPRoundInt(Dm, 32:1, vrint_fp_RM, 0:1); } + +vrint_rxz_RM: "r" + is ((TMode=0 & c1616=0 & c0707=0) + | (TMode=1 & thv_c1616=0 & thv_c0707=0)) + { tmp:1 = $(FPSCR_RMODE); export tmp; } + +vrint_rxz_RM: "x" + is ((TMode=0 & c1616=1 & c0707=0) + | (TMode=1 & thv_c1616=1 & thv_c0707=0)) + { tmp:1 = $(FPSCR_RMODE); export tmp; } + +vrint_rxz_RM: "z" + is ((TMode=0 & c1616=0 & c0707=1) + | (TMode=1 & thv_c1616=0 & thv_c0707=1)) + { export $(FPRounding_ZERO); } + +# For vrintx, the exact flag is 1, and the IXF flag is set (inexact) + +vrint_rxz_exact: "x" + is ((TMode=0 & c1616=1 & c0707=0) + | (TMode=1 & thv_c1616=1 & thv_c0707=0)) + { export 1:1; } + +vrint_rxz_exact: + is ((TMode=0 & ( c1616=0 | c0707=1)) + | (TMode=1 & (thv_c1616=0 | thv_c0707=1))) + { export 0:1; } + +vrint_rxz_ixf: + is ((TMode=0 & c1616=1 & c0707=0) + | (TMode=1 & thv_c1616=1 & thv_c0707=0)) + { $(FPEXC_IXF) = FPConvertInexact(); } + +vrint_rxz_ixf: + is ((TMode=0 & ( c1616=0 | c0707=1)) + | (TMode=1 & (thv_c1616=0 | thv_c0707=1))) + { } + +# F6.1.186,188,190 p3662,3666,3670 A1 size = 10 (c0809) +:vrint^vrint_rxz_RM^COND^".f32" Sd,Sm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b110 & c1718=0b11 & c1011=0b10 & c0606=1 & c0404=0 & (( c1616=0) | ( c1616=1 & c0707=0)) & c0809=0b10) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b110 & thv_c1718=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & ((thv_c1616=0) | (thv_c1616=1 & thv_c0707=0)) & thv_c0809=0b10)) + & vrint_rxz_RM & vrint_rxz_exact & vrint_rxz_ixf & COND & Sd & Sm + { build COND; Sd = FPRoundInt(Sm, 32:1, vrint_rxz_RM, vrint_rxz_exact); build vrint_rxz_ixf; } + +# F6.1.186,188,190 p3662,3666,3670 A1 size = 11 (c0809) +:vrint^vrint_rxz_RM^COND^".f64" Dd,Dm + is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b110 & c1718=0b11 & c1011=0b10 & c0606=1 & c0404=0 & (( c1616=0) | ( c1616=1 & c0707=0)) & c0809=0b11) + | (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b110 & thv_c1718=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & ((thv_c1616=0) | (thv_c1616=1 & thv_c0707=0)) & thv_c0809=0b11)) + & vrint_rxz_RM & vrint_rxz_exact & vrint_rxz_ixf & COND & Dd & Dm + { build COND; Dd = FPRoundInt(Dm, 32:1, vrint_rxz_RM, vrint_rxz_exact); build vrint_rxz_ixf; } + +####### +# VSEL + +vselcond: "eq" + is ((TMode=0 & c2021=0b00) + | (TMode=1 & thv_c2021=0b00)) + { tmp:1 = ZR; export tmp; } +vselcond: "ge" + is ((TMode=0 & c2021=0b10) + | (TMode=1 & thv_c2021=0b10)) + { tmp:1 = (NG==OV); export tmp; } +vselcond: "gt" + is ((TMode=0 & c2021=0b11) + | (TMode=1 & thv_c2021=0b11)) + { tmp:1 = (!ZR); export tmp; } +vselcond: "vs" + is ((TMode=0 & c2021=0b01) + | (TMode=1 & thv_c2021=0b01)) + { tmp:1 = OV; export tmp; } + +# F6.1.200 p3690 A1/T1 size = 11 doubleprec (c0809) +:vsel^vselcond^".f64" Dd,Dn,Dm + is ((TMode=0 & c2831=0b1111 & c2327=0b11100 & c1011=0b10 & c0606=0 & c0404=0 & c0809=0b11) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11100 & thv_c1011=0b10 & thv_c0606=0 & thv_c0404=0 & thv_c0809=0b11)) + & vselcond & Dn & Dd & Dm + { Dd = zext(vselcond != 0) * Dn + zext(vselcond == 0) * Dm; } + +# F6.1.200 p3690 A1/T1 size = 10 singleprec (c0809) +:vsel^vselcond".f32" Sd,Sn,Sm + is ((TMode=0 & c2831=0b1111 & c2327=0b11100 & c1011=0b10 & c0606=0 & c0404=0 & c0809=0b10) + | (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11100 & thv_c1011=0b10 & thv_c0606=0 & thv_c0404=0 & thv_c0809=0b10)) + & vselcond & Sn & Sd & Sm + { Sd = zext(vselcond != 0) * Sn + zext(vselcond == 0) * Sm; } + +@endif # INCLUDE_NEON diff --git a/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.lang b/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.lang new file mode 100644 index 00000000..03ce0149 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.lang @@ -0,0 +1,62 @@ + + + + ARM:LE:32:DEPRECATED ARM V5 + ARM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.trans b/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.trans new file mode 100644 index 00000000..9c8858d0 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/old/ARMv5.trans @@ -0,0 +1,6 @@ + + + Sleigh-ARMv5 + ARM:LE:32:v5 + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.lang b/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.lang new file mode 100644 index 00000000..773cc611 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.lang @@ -0,0 +1,55 @@ + + + + ARM:LE:32:DEPRECATED THUMB V2 + ARM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.trans b/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.trans new file mode 100644 index 00000000..781a37a9 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/languages/old/THUMBv2.trans @@ -0,0 +1,11 @@ + + + Sleigh-THUMBv2 + ARM:LE:32:v5t + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/manuals/ARM.idx b/src/third-party/sleigh/processors/ARM/data/manuals/ARM.idx new file mode 100644 index 00000000..f898a8bd --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/manuals/ARM.idx @@ -0,0 +1,6461 @@ +@Armv7AR_errata.pdf[ARM Architecture Reference Manual - ARMv7A and ARMv7-R edition Errata markup, July, 2011 (ARM DDI 0406B_errata_2011_Q2)] + +adc, 326 +adceq, 326 +adcne, 326 +adcmi, 326 +adcpl, 326 +adcvs, 326 +adcvc, 326 +adchi, 326 +adcls, 326 +adcge, 326 +adclt, 326 +adcgt, 326 +adcle, 326 +adcal, 326 +adclo, 326 +adccc, 326 +adchs, 326 +adccs, 326 +adcnv, 326 +adcs, 326 +adceqs, 326 +adcnes, 326 +adcmis, 326 +adcpls, 326 +adcvss, 326 +adcvcs, 326 +adchis, 326 +adclss, 326 +adcges, 326 +adclts, 326 +adcgts, 326 +adcles, 326 +adcals, 326 +adclos, 326 +adcccs, 326 +adchss, 326 +adccss, 326 +adcnvs, 326 +adcseq, 326 +adcsne, 326 +adcsmi, 326 +adcspl, 326 +adcsvs, 326 +adcsvc, 326 +adcshi, 326 +adcsls, 326 +adcsge, 326 +adcslt, 326 +adcsgt, 326 +adcsle, 326 +adcsal, 326 +adcslo, 326 +adcscc, 326 +adcshs, 326 +adcscs, 326 +adcsnv, 326 +add, 332 +addeq, 332 +addne, 332 +addmi, 332 +addpl, 332 +addvs, 332 +addvc, 332 +addhi, 332 +addls, 332 +addge, 332 +addlt, 332 +addgt, 332 +addle, 332 +addal, 332 +addlo, 332 +addcc, 332 +addhs, 332 +addcs, 332 +addnv, 332 +adds, 332 +addeqs, 332 +addnes, 332 +addmis, 332 +addpls, 332 +addvss, 332 +addvcs, 332 +addhis, 332 +addlss, 332 +addges, 332 +addlts, 332 +addgts, 332 +addles, 332 +addals, 332 +addlos, 332 +addccs, 332 +addhss, 332 +addcss, 332 +addnvs, 332 +addseq, 332 +addsne, 332 +addsmi, 332 +addspl, 332 +addsvs, 332 +addsvc, 332 +addshi, 332 +addsls, 332 +addsge, 332 +addslt, 332 +addsgt, 332 +addsle, 332 +addsal, 332 +addslo, 332 +addscc, 332 +addshs, 332 +addscs, 332 +addsnv, 332 +addw, 332 +addeq, 332 +addne, 332 +addmi, 332 +addpl, 332 +addvs, 332 +addvc, 332 +addhi, 332 +addls, 332 +addge, 332 +addlt, 332 +addgt, 332 +addle, 332 +addal, 332 +addlo, 332 +addcc, 332 +addhs, 332 +addcs, 332 +addnv, 332 +adr, 344 +adreq, 344 +adrne, 344 +adrmi, 344 +adrpl, 344 +adrvs, 344 +adrvc, 344 +adrhi, 344 +adrls, 344 +adrge, 344 +adrlt, 344 +adrgt, 344 +adrle, 344 +adral, 344 +adrlo, 344 +adrcc, 344 +adrhs, 344 +adrcs, 344 +adrnv, 344 +and, 346 +andeq, 346 +andne, 346 +andmi, 346 +andpl, 346 +andvs, 346 +andvc, 346 +andhi, 346 +andls, 346 +andge, 346 +andlt, 346 +andgt, 346 +andle, 346 +andal, 346 +andlo, 346 +andcc, 346 +andhs, 346 +andcs, 346 +andnv, 346 +ands, 346 +andeqs, 346 +andnes, 346 +andmis, 346 +andpls, 346 +andvss, 346 +andvcs, 346 +andhis, 346 +andlss, 346 +andges, 346 +andlts, 346 +andgts, 346 +andles, 346 +andals, 346 +andlos, 346 +andccs, 346 +andhss, 346 +andcss, 346 +andnvs, 346 +andseq, 346 +andsne, 346 +andsmi, 346 +andspl, 346 +andsvs, 346 +andsvc, 346 +andshi, 346 +andsls, 346 +andsge, 346 +andslt, 346 +andsgt, 346 +andsle, 346 +andsal, 346 +andslo, 346 +andscc, 346 +andshs, 346 +andscs, 346 +andsnv, 346 +asr, 352 +asreq, 352 +asrne, 352 +asrmi, 352 +asrpl, 352 +asrvs, 352 +asrvc, 352 +asrhi, 352 +asrls, 352 +asrge, 352 +asrlt, 352 +asrgt, 352 +asrle, 352 +asral, 352 +asrlo, 352 +asrcc, 352 +asrhs, 352 +asrcs, 352 +asrnv, 352 +b, 356 +beq, 356 +bne, 356 +bmi, 356 +bpl, 356 +bvs, 356 +bvc, 356 +bhi, 356 +bls, 356 +bge, 356 +blt, 356 +bgt, 356 +ble, 356 +bal, 356 +blo, 356 +bcc, 356 +bhs, 356 +bcs, 356 +bnv, 356 +bfc, 358 +bfceq, 358 +bfcne, 358 +bfcmi, 358 +bfcpl, 358 +bfcvs, 358 +bfcvc, 358 +bfchi, 358 +bfcls, 358 +bfcge, 358 +bfclt, 358 +bfcgt, 358 +bfcle, 358 +bfcal, 358 +bfclo, 358 +bfccc, 358 +bfchs, 358 +bfccs, 358 +bfcnv, 358 +bfi, 360 +bfieq, 360 +bfine, 360 +bfimi, 360 +bfipl, 360 +bfivs, 360 +bfivc, 360 +bfihi, 360 +bfils, 360 +bfige, 360 +bfilt, 360 +bfigt, 360 +bfile, 360 +bfial, 360 +bfilo, 360 +bficc, 360 +bfihs, 360 +bfics, 360 +bfinv, 360 +bic, 362 +biceq, 362 +bicne, 362 +bicmi, 362 +bicpl, 362 +bicvs, 362 +bicvc, 362 +bichi, 362 +bicls, 362 +bicge, 362 +biclt, 362 +bicgt, 362 +bicle, 362 +bical, 362 +biclo, 362 +biccc, 362 +bichs, 362 +biccs, 362 +bicnv, 362 +bics, 362 +biceqs, 362 +bicnes, 362 +bicmis, 362 +bicpls, 362 +bicvss, 362 +bicvcs, 362 +bichis, 362 +biclss, 362 +bicges, 362 +biclts, 362 +bicgts, 362 +bicles, 362 +bicals, 362 +biclos, 362 +bicccs, 362 +bichss, 362 +biccss, 362 +bicnvs, 362 +bicseq, 362 +bicsne, 362 +bicsmi, 362 +bicspl, 362 +bicsvs, 362 +bicsvc, 362 +bicshi, 362 +bicsls, 362 +bicsge, 362 +bicslt, 362 +bicsgt, 362 +bicsle, 362 +bicsal, 362 +bicslo, 362 +bicscc, 362 +bicshs, 362 +bicscs, 362 +bicsnv, 362 +bkpt, 368 +bl, 370 +bleq, 370 +blne, 370 +blmi, 370 +blpl, 370 +blvs, 370 +blvc, 370 +blhi, 370 +blls, 370 +blge, 370 +bllt, 370 +blgt, 370 +blle, 370 +blal, 370 +bllo, 370 +blcc, 370 +blhs, 370 +blcs, 370 +blnv, 370 +blx, 370 +blxeq, 370 +blxne, 370 +blxmi, 370 +blxpl, 370 +blxvs, 370 +blxvc, 370 +blxhi, 370 +blxls, 370 +blxge, 370 +blxlt, 370 +blxgt, 370 +blxle, 370 +blxal, 370 +blxlo, 370 +blxcc, 370 +blxhs, 370 +blxcs, 370 +blxnv, 370 +bx, 374 +bxeq, 374 +bxne, 374 +bxmi, 374 +bxpl, 374 +bxvs, 374 +bxvc, 374 +bxhi, 374 +bxls, 374 +bxge, 374 +bxlt, 374 +bxgt, 374 +bxle, 374 +bxal, 374 +bxlo, 374 +bxcc, 374 +bxhs, 374 +bxcs, 374 +bxnv, 374 +bxj, 376 +bxjeq, 376 +bxjne, 376 +bxjmi, 376 +bxjpl, 376 +bxjvs, 376 +bxjvc, 376 +bxjhi, 376 +bxjls, 376 +bxjge, 376 +bxjlt, 376 +bxjgt, 376 +bxjle, 376 +bxjal, 376 +bxjlo, 376 +bxjcc, 376 +bxjhs, 376 +bxjcs, 376 +bxjnv, 376 +cbnz, 378 +cbz, 378 +cdp, 380 +cdpeq, 380 +cdpne, 380 +cdpmi, 380 +cdppl, 380 +cdpvs, 380 +cdpvc, 380 +cdphi, 380 +cdpls, 380 +cdpge, 380 +cdplt, 380 +cdpgt, 380 +cdple, 380 +cdpal, 380 +cdplo, 380 +cdpcc, 380 +cdphs, 380 +cdpcs, 380 +cdpnv, 380 +cdp2, 380 +cdp2eq, 380 +cdp2ne, 380 +cdp2mi, 380 +cdp2pl, 380 +cdp2vs, 380 +cdp2vc, 380 +cdp2hi, 380 +cdp2ls, 380 +cdp2ge, 380 +cdp2lt, 380 +cdp2gt, 380 +cdp2le, 380 +cdp2al, 380 +cdp2lo, 380 +cdp2cc, 380 +cdp2hs, 380 +cdp2cs, 380 +cdp2nv, 380 +chka, 1141 +clrex, 382 +clrexeq, 382 +clrexne, 382 +clrexmi, 382 +clrexpl, 382 +clrexvs, 382 +clrexvc, 382 +clrexhi, 382 +clrexls, 382 +clrexge, 382 +clrexlt, 382 +clrexgt, 382 +clrexle, 382 +clrexal, 382 +clrexlo, 382 +clrexcc, 382 +clrexhs, 382 +clrexcs, 382 +clrexnv, 382 +clz, 384 +clzeq, 384 +clzne, 384 +clzmi, 384 +clzpl, 384 +clzvs, 384 +clzvc, 384 +clzhi, 384 +clzls, 384 +clzge, 384 +clzlt, 384 +clzgt, 384 +clzle, 384 +clzal, 384 +clzlo, 384 +clzcc, 384 +clzhs, 384 +clzcs, 384 +clznv, 384 +cmn, 386 +cmneq, 386 +cmnne, 386 +cmnmi, 386 +cmnpl, 386 +cmnvs, 386 +cmnvc, 386 +cmnhi, 386 +cmnls, 386 +cmnge, 386 +cmnlt, 386 +cmngt, 386 +cmnle, 386 +cmnal, 386 +cmnlo, 386 +cmncc, 386 +cmnhs, 386 +cmncs, 386 +cmnnv, 386 +cmp, 392 +cmpeq, 392 +cmpne, 392 +cmpmi, 392 +cmppl, 392 +cmpvs, 392 +cmpvc, 392 +cmphi, 392 +cmpls, 392 +cmpge, 392 +cmplt, 392 +cmpgt, 392 +cmple, 392 +cmpal, 392 +cmplo, 392 +cmpcc, 392 +cmphs, 392 +cmpcs, 392 +cmpnv, 392 +cps, 1561 +cpy, 398 +dbg, 400 +dbgeq, 400 +dbgne, 400 +dbgmi, 400 +dbgpl, 400 +dbgvs, 400 +dbgvc, 400 +dbghi, 400 +dbgls, 400 +dbgge, 400 +dbglt, 400 +dbggt, 400 +dbgle, 400 +dbgal, 400 +dbglo, 400 +dbgcc, 400 +dbghs, 400 +dbgcs, 400 +dbgnv, 400 +dmb, 402 +dmbeq, 402 +dmbne, 402 +dmbmi, 402 +dmbpl, 402 +dmbvs, 402 +dmbvc, 402 +dmbhi, 402 +dmbls, 402 +dmbge, 402 +dmblt, 402 +dmbgt, 402 +dmble, 402 +dmbal, 402 +dmblo, 402 +dmbcc, 402 +dmbhs, 402 +dmbcs, 402 +dmbnv, 402 +dsb, 404 +dsbeq, 404 +dsbne, 404 +dsbmi, 404 +dsbpl, 404 +dsbvs, 404 +dsbvc, 404 +dsbhi, 404 +dsbls, 404 +dsbge, 404 +dsblt, 404 +dsbgt, 404 +dsble, 404 +dsbal, 404 +dsblo, 404 +dsbcc, 404 +dsbhs, 404 +dsbcs, 404 +dsbnv, 404 +enterx, 1133 +eor, 406 +eoreq, 406 +eorne, 406 +eormi, 406 +eorpl, 406 +eorvs, 406 +eorvc, 406 +eorhi, 406 +eorls, 406 +eorge, 406 +eorlt, 406 +eorgt, 406 +eorle, 406 +eoral, 406 +eorlo, 406 +eorcc, 406 +eorhs, 406 +eorcs, 406 +eornv, 406 +eors, 406 +eoreqs, 406 +eornes, 406 +eormis, 406 +eorpls, 406 +eorvss, 406 +eorvcs, 406 +eorhis, 406 +eorlss, 406 +eorges, 406 +eorlts, 406 +eorgts, 406 +eorles, 406 +eorals, 406 +eorlos, 406 +eorccs, 406 +eorhss, 406 +eorcss, 406 +eornvs, 406 +eorseq, 406 +eorsne, 406 +eorsmi, 406 +eorspl, 406 +eorsvs, 406 +eorsvc, 406 +eorshi, 406 +eorsls, 406 +eorsge, 406 +eorslt, 406 +eorsgt, 406 +eorsle, 406 +eorsal, 406 +eorslo, 406 +eorscc, 406 +eorshs, 406 +eorscs, 406 +eorsnv, 406 +hb, 1142 +hbeq, 1142 +hbne, 1142 +hbmi, 1142 +hbpl, 1142 +hbvs, 1142 +hbvc, 1142 +hbhi, 1142 +hbls, 1142 +hbge, 1142 +hblt, 1142 +hbgt, 1142 +hble, 1142 +hbal, 1142 +hblo, 1142 +hbcc, 1142 +hbhs, 1142 +hbcs, 1142 +hbnv, 1142 +hbl, 1142 +hbleq, 1142 +hblne, 1142 +hblmi, 1142 +hblpl, 1142 +hblvs, 1142 +hblvc, 1142 +hblhi, 1142 +hblls, 1142 +hblge, 1142 +hbllt, 1142 +hblgt, 1142 +hblle, 1142 +hblal, 1142 +hbllo, 1142 +hblcc, 1142 +hblhs, 1142 +hblcs, 1142 +hblnv, 1142 +hblp, 1143 +hblpeq, 1143 +hblpne, 1143 +hblpmi, 1143 +hblppl, 1143 +hblpvs, 1143 +hblpvc, 1143 +hblphi, 1143 +hblpls, 1143 +hblpge, 1143 +hblplt, 1143 +hblpgt, 1143 +hblple, 1143 +hblpal, 1143 +hblplo, 1143 +hblpcc, 1143 +hblphs, 1143 +hblpcs, 1143 +hblpnv, 1143 +hbp, 1144 +hbpeq, 1144 +hbpne, 1144 +hbpmi, 1144 +hbppl, 1144 +hbpvs, 1144 +hbpvc, 1144 +hbphi, 1144 +hbpls, 1144 +hbpge, 1144 +hbplt, 1144 +hbpgt, 1144 +hbple, 1144 +hbpal, 1144 +hbplo, 1144 +hbpcc, 1144 +hbphs, 1144 +hbpcs, 1144 +hbpnv, 1144 +isb, 414 +isbeq, 414 +isbne, 414 +isbmi, 414 +isbpl, 414 +isbvs, 414 +isbvc, 414 +isbhi, 414 +isbls, 414 +isbge, 414 +isblt, 414 +isbgt, 414 +isble, 414 +isbal, 414 +isblo, 414 +isbcc, 414 +isbhs, 414 +isbcs, 414 +isbnv, 414 +it, 416 +itT, 416 +itE, 416 +itTT, 416 +itET, 416 +itTE, 416 +itEE, 416 +itTTT, 416 +itETT, 416 +itTET, 416 +itEET, 416 +itTTE, 416 +itETE, 416 +itTEE, 416 +itEEE, 416 +ldc, 418 +ldceq, 418 +ldcne, 418 +ldcmi, 418 +ldcpl, 418 +ldcvs, 418 +ldcvc, 418 +ldchi, 418 +ldcls, 418 +ldcge, 418 +ldclt, 418 +ldcgt, 418 +ldcle, 418 +ldcal, 418 +ldclo, 418 +ldccc, 418 +ldchs, 418 +ldccs, 418 +ldcnv, 418 +ldcl, 418 +ldceql, 418 +ldcnel, 418 +ldcmil, 418 +ldcpll, 418 +ldcvsl, 418 +ldcvcl, 418 +ldchil, 418 +ldclsl, 418 +ldcgel, 418 +ldcltl, 418 +ldcgtl, 418 +ldclel, 418 +ldcall, 418 +ldclol, 418 +ldcccl, 418 +ldchsl, 418 +ldccsl, 418 +ldcnvl, 418 +ldcleq, 418 +ldclne, 418 +ldclmi, 418 +ldclpl, 418 +ldclvs, 418 +ldclvc, 418 +ldclhi, 418 +ldclls, 418 +ldclge, 418 +ldcllt, 418 +ldclgt, 418 +ldclle, 418 +ldclal, 418 +ldcllo, 418 +ldclcc, 418 +ldclhs, 418 +ldclcs, 418 +ldclnv, 418 +ldc2, 418 +ldc2eq, 418 +ldc2ne, 418 +ldc2mi, 418 +ldc2pl, 418 +ldc2vs, 418 +ldc2vc, 418 +ldc2hi, 418 +ldc2ls, 418 +ldc2ge, 418 +ldc2lt, 418 +ldc2gt, 418 +ldc2le, 418 +ldc2al, 418 +ldc2lo, 418 +ldc2cc, 418 +ldc2hs, 418 +ldc2cs, 418 +ldc2nv, 418 +ldc2l, 418 +ldc2leq, 418 +ldc2lne, 418 +ldc2lmi, 418 +ldc2lpl, 418 +ldc2lvs, 418 +ldc2lvc, 418 +ldc2lhi, 418 +ldc2lls, 418 +ldc2lge, 418 +ldc2llt, 418 +ldc2lgt, 418 +ldc2lle, 418 +ldc2lal, 418 +ldc2llo, 418 +ldc2lcc, 418 +ldc2lhs, 418 +ldc2lcs, 418 +ldc2lnv, 418 +ldm, 422 +ldmeq, 422 +ldmne, 422 +ldmmi, 422 +ldmpl, 422 +ldmvs, 422 +ldmvc, 422 +ldmhi, 422 +ldmls, 422 +ldmge, 422 +ldmlt, 422 +ldmgt, 422 +ldmle, 422 +ldmal, 422 +ldmlo, 422 +ldmcc, 422 +ldmhs, 422 +ldmcs, 422 +ldmnv, 422 +ldmia, 422 +ldmeqia, 422 +ldmneia, 422 +ldmmiia, 422 +ldmplia, 422 +ldmvsia, 422 +ldmvcia, 422 +ldmhiia, 422 +ldmlsia, 422 +ldmgeia, 422 +ldmltia, 422 +ldmgtia, 422 +ldmleia, 422 +ldmalia, 422 +ldmloia, 422 +ldmccia, 422 +ldmhsia, 422 +ldmcsia, 422 +ldmnvia, 422 +ldmfd, 422 +ldmeqfd, 422 +ldmnefd, 422 +ldmmifd, 422 +ldmplfd, 422 +ldmvsfd, 422 +ldmvcfd, 422 +ldmhifd, 422 +ldmlsfd, 422 +ldmgefd, 422 +ldmltfd, 422 +ldmgtfd, 422 +ldmlefd, 422 +ldmalfd, 422 +ldmlofd, 422 +ldmccfd, 422 +ldmhsfd, 422 +ldmcsfd, 422 +ldmnvfd, 422 +ldmda, 424 +ldmdaeq, 424 +ldmdane, 424 +ldmdami, 424 +ldmdapl, 424 +ldmdavs, 424 +ldmdavc, 424 +ldmdahi, 424 +ldmdals, 424 +ldmdage, 424 +ldmdalt, 424 +ldmdagt, 424 +ldmdale, 424 +ldmdaal, 424 +ldmdalo, 424 +ldmdacc, 424 +ldmdahs, 424 +ldmdacs, 424 +ldmdanv, 424 +ldmeqda,424 +ldmneda, 424 +ldmmida, 424 +ldmplda, 424 +ldmvsda, 424 +ldmvcda, 424 +ldmhida, 424 +ldmlsda, 424 +ldmgeda, 424 +ldmltda, 424 +ldmgtda, 424 +ldmleda, 424 +ldmalda, 424 +ldmloda, 424 +ldmccda, 424 +ldmhsda, 424 +ldmcsda, 424 +ldmnvda, 424 +ldmeqfa,424 +ldmnefa, 424 +ldmmifa, 424 +ldmplfa, 424 +ldmvsfa, 424 +ldmvcfa, 424 +ldmhifa, 424 +ldmlsfa, 424 +ldmgefa, 424 +ldmltfa, 424 +ldmgtfa, 424 +ldmlefa, 424 +ldmalfa, 424 +ldmlofa, 424 +ldmccfa, 424 +ldmhsfa, 424 +ldmcsfa, 424 +ldmnvfa, 424 +ldmdb, 426 +ldmdbeq, 426 +ldmdbne, 426 +ldmdbmi, 426 +ldmdbpl, 426 +ldmdbvs, 426 +ldmdbvc, 426 +ldmdbhi, 426 +ldmdbls, 426 +ldmdbge, 426 +ldmdblt, 426 +ldmdbgt, 426 +ldmdble, 426 +ldmdbal, 426 +ldmdblo, 426 +ldmdbcc, 426 +ldmdbhs, 426 +ldmdbcs, 426 +ldmdbnv, 426 +ldmeqdb,426 +ldmnedb, 426 +ldmmidb, 426 +ldmpldb, 426 +ldmvsdb, 426 +ldmvcdb, 426 +ldmhidb, 426 +ldmlsdb, 426 +ldmgedb, 426 +ldmltdb, 426 +ldmgtdb, 426 +ldmledb, 426 +ldmaldb, 426 +ldmlodb, 426 +ldmccdb, 426 +ldmhsdb, 426 +ldmcsdb, 426 +ldmnvdb, 426 +ldmeqea,426 +ldmneea, 426 +ldmmiea, 426 +ldmplea, 426 +ldmvsea, 426 +ldmvcea, 426 +ldmhiea, 426 +ldmlsea, 426 +ldmgeea, 426 +ldmltea, 426 +ldmgtea, 426 +ldmleea, 426 +ldmalea, 426 +ldmloea, 426 +ldmccea, 426 +ldmhsea, 426 +ldmcsea, 426 +ldmnvea, 426 +ldmib, 428 +ldmibeq, 428 +ldmibne, 428 +ldmibmi, 428 +ldmibpl, 428 +ldmibvs, 428 +ldmibvc, 428 +ldmibhi, 428 +ldmibls, 428 +ldmibge, 428 +ldmiblt, 428 +ldmibgt, 428 +ldmible, 428 +ldmibal, 428 +ldmiblo, 428 +ldmibcc, 428 +ldmibhs, 428 +ldmibcs, 428 +ldmibnv, 428 +ldmeqib,428 +ldmneib, 428 +ldmmiib, 428 +ldmplib, 428 +ldmvsib, 428 +ldmvcib, 428 +ldmhiib, 428 +ldmlsib, 428 +ldmgeib, 428 +ldmltib, 428 +ldmgtib, 428 +ldmleib, 428 +ldmalib, 428 +ldmloib, 428 +ldmccib, 428 +ldmhsib, 428 +ldmcsib, 428 +ldmnvib, 428 +ldmeqed,428 +ldmneed, 428 +ldmmied, 428 +ldmpled, 428 +ldmvsed, 428 +ldmvced, 428 +ldmhied, 428 +ldmlsed, 428 +ldmgeed, 428 +ldmlted, 428 +ldmgted, 428 +ldmleed, 428 +ldmaled, 428 +ldmloed, 428 +ldmcced, 428 +ldmhsed, 428 +ldmcsed, 428 +ldmnved, 428 +ldr, 430 +ldreq, 430 +ldrne, 430 +ldrmi, 430 +ldrpl, 430 +ldrvs, 430 +ldrvc, 430 +ldrhi, 430 +ldrls, 430 +ldrge, 430 +ldrlt, 430 +ldrgt, 430 +ldrle, 430 +ldral, 430 +ldrlo, 430 +ldrcc, 430 +ldrhs, 430 +ldrcs, 430 +ldrnv, 430 +ldreqb, 430 +ldrneb, 430 +ldrmib, 430 +ldrplb, 430 +ldrvsb, 430 +ldrvcb, 430 +ldrhib, 430 +ldrlsb, 430 +ldrgeb, 430 +ldrltb, 430 +ldrgtb, 430 +ldrleb, 430 +ldralb, 430 +ldrlob, 430 +ldrccb, 430 +ldrhsb, 430 +ldrcsb, 430 +ldrnvb, 430 +ldrb, 438 +ldrbeq, 438 +ldrbne, 438 +ldrbmi, 438 +ldrbpl, 438 +ldrbvs, 438 +ldrbvc, 438 +ldrbhi, 438 +ldrbls, 438 +ldrbge, 438 +ldrblt, 438 +ldrbgt, 438 +ldrble, 438 +ldrbal, 438 +ldrblo, 438 +ldrbcc, 438 +ldrbhs, 438 +ldrbcs, 438 +ldrbnv, 438 +ldrbt, 446 +ldreqbt, 446 +ldrnebt, 446 +ldrmibt, 446 +ldrplbt, 446 +ldrvsbt, 446 +ldrvcbt, 446 +ldrhibt, 446 +ldrlsbt, 446 +ldrgebt, 446 +ldrltbt, 446 +ldrgtbt, 446 +ldrlebt, 446 +ldralbt, 446 +ldrlobt, 446 +ldrccbt, 446 +ldrhsbt, 446 +ldrcsbt, 446 +ldrnvbt, 446 +ldrbteq,446 +ldrbtne, 446 +ldrbtmi, 446 +ldrbtpl, 446 +ldrbtvs, 446 +ldrbtvc, 446 +ldrbthi, 446 +ldrbtls, 446 +ldrbtge, 446 +ldrbtlt, 446 +ldrbtgt, 446 +ldrbtle, 446 +ldrbtal, 446 +ldrbtlo, 446 +ldrbtcc, 446 +ldrbths, 446 +ldrbtcs, 446 +ldrbtnv, 446 +ldrd, 448 +ldreqd, 448 +ldrned, 448 +ldrmid, 448 +ldrpld, 448 +ldrvsd, 448 +ldrvcd, 448 +ldrhid, 448 +ldrlsd, 448 +ldrged, 448 +ldrltd, 448 +ldrgtd, 448 +ldrled, 448 +ldrald, 448 +ldrlod, 448 +ldrccd, 448 +ldrhsd, 448 +ldrcsd, 448 +ldrnvd, 448 +ldrdeq, 448 +ldrdne, 448 +ldrdmi, 448 +ldrdpl, 448 +ldrdvs, 448 +ldrdvc, 448 +ldrdhi, 448 +ldrdls, 448 +ldrdge, 448 +ldrdlt, 448 +ldrdgt, 448 +ldrdle, 448 +ldrdal, 448 +ldrdlo, 448 +ldrdcc, 448 +ldrdhs, 448 +ldrdcs, 448 +ldrdnv, 448 +ldrex, 454 +ldrexeq, 454 +ldrexne, 454 +ldrexmi, 454 +ldrexpl, 454 +ldrexvs, 454 +ldrexvc, 454 +ldrexhi, 454 +ldrexls, 454 +ldrexge, 454 +ldrexlt, 454 +ldrexgt, 454 +ldrexle, 454 +ldrexal, 454 +ldrexlo, 454 +ldrexcc, 454 +ldrexhs, 454 +ldrexcs, 454 +ldrexnv, 454 +ldrexb, 456 +ldrexbeq, 456 +ldrexbne, 456 +ldrexbmi, 456 +ldrexbpl, 456 +ldrexbvs, 456 +ldrexbvc, 456 +ldrexbhi, 456 +ldrexbls, 456 +ldrexbge, 456 +ldrexblt, 456 +ldrexbgt, 456 +ldrexble, 456 +ldrexbal, 456 +ldrexblo, 456 +ldrexbcc, 456 +ldrexbhs, 456 +ldrexbcs, 456 +ldrexbnv, 456 +ldrexd, 458 +ldrexdeq, 458 +ldrexdne, 458 +ldrexdmi, 458 +ldrexdpl, 458 +ldrexdvs, 458 +ldrexdvc, 458 +ldrexdhi, 458 +ldrexdls, 458 +ldrexdge, 458 +ldrexdlt, 458 +ldrexdgt, 458 +ldrexdle, 458 +ldrexdal, 458 +ldrexdlo, 458 +ldrexdcc, 458 +ldrexdhs, 458 +ldrexdcs, 458 +ldrexdnv, 458 +ldrexh, 460 +ldrexheq, 460 +ldrexhne, 460 +ldrexhmi, 460 +ldrexhpl, 460 +ldrexhvs, 460 +ldrexhvc, 460 +ldrexhhi, 460 +ldrexhls, 460 +ldrexhge, 460 +ldrexhlt, 460 +ldrexhgt, 460 +ldrexhle, 460 +ldrexhal, 460 +ldrexhlo, 460 +ldrexhcc, 460 +ldrexhhs, 460 +ldrexhcs, 460 +ldrexhnv, 460 +ldrh, 462 +ldreqh, 462 +ldrneh, 462 +ldrmih, 462 +ldrplh, 462 +ldrvsh, 462 +ldrvch, 462 +ldrhih, 462 +ldrlsh, 462 +ldrgeh, 462 +ldrlth, 462 +ldrgth, 462 +ldrleh, 462 +ldralh, 462 +ldrloh, 462 +ldrcch, 462 +ldrhsh, 462 +ldrcsh, 462 +ldrnvh, 462 +ldrheq, 462 +ldrhne, 462 +ldrhmi, 462 +ldrhpl, 462 +ldrhvs, 462 +ldrhvc, 462 +ldrhhi, 462 +ldrhls, 462 +ldrhge, 462 +ldrhlt, 462 +ldrhgt, 462 +ldrhle, 462 +ldrhal, 462 +ldrhlo, 462 +ldrhcc, 462 +ldrhhs, 462 +ldrhcs, 462 +ldrhnv, 462 +ldrht, 470 +ldrhteq, 470 +ldrhtne, 470 +ldrhtmi, 470 +ldrhtpl, 470 +ldrhtvs, 470 +ldrhtvc, 470 +ldrhthi, 470 +ldrhtls, 470 +ldrhtge, 470 +ldrhtlt, 470 +ldrhtgt, 470 +ldrhtle, 470 +ldrhtal, 470 +ldrhtlo, 470 +ldrhtcc, 470 +ldrhths, 470 +ldrhtcs, 470 +ldrhtnv, 470 +ldrsb, 472 +ldreqsb, 472 +ldrnesb, 472 +ldrmisb, 472 +ldrplsb, 472 +ldrvssb, 472 +ldrvcsb, 472 +ldrhisb, 472 +ldrlssb, 472 +ldrgesb, 472 +ldrltsb, 472 +ldrgtsb, 472 +ldrlesb, 472 +ldralsb, 472 +ldrlosb, 472 +ldrccsb, 472 +ldrhssb, 472 +ldrcssb, 472 +ldrnvsb, 472 +ldrsbeq,472 +ldrsbne, 472 +ldrsbmi, 472 +ldrsbpl, 472 +ldrsbvs, 472 +ldrsbvc, 472 +ldrsbhi, 472 +ldrsbls, 472 +ldrsbge, 472 +ldrsblt, 472 +ldrsbgt, 472 +ldrsble, 472 +ldrsbal, 472 +ldrsblo, 472 +ldrsbcc, 472 +ldrsbhs, 472 +ldrsbcs, 472 +ldrsbnv, 472 +ldrsbt, 478 +ldrsbteq, 478 +ldrsbne, 478 +ldrsbmi, 478 +ldrsbpl, 478 +ldrsbvs, 478 +ldrsbvc, 478 +ldrsbhi, 478 +ldrsbls, 478 +ldrsbge, 478 +ldrsblt, 478 +ldrsbgt, 478 +ldrsble, 478 +ldrsbal, 478 +ldrsblo, 478 +ldrsbcc, 478 +ldrsbhs, 478 +ldrsbcs, 478 +ldrsbnv, 478 +ldrsh, 480 +ldreqsh, 480 +ldrnesh, 480 +ldrmish, 480 +ldrplsh, 480 +ldrvssh, 480 +ldrvcsh, 480 +ldrhish, 480 +ldrlssh, 480 +ldrgesh, 480 +ldrltsh, 480 +ldrgtsh, 480 +ldrlesh, 480 +ldralsh, 480 +ldrlosh, 480 +ldrccsh, 480 +ldrhssh, 480 +ldrcshs, 480 +ldrnvsh, 480 +ldrsheq,480 +ldrshne, 480 +ldrshmi, 480 +ldrshpl, 480 +ldrshvs, 480 +ldrshvc, 480 +ldrshhi, 480 +ldrshls, 480 +ldrshge, 480 +ldrshlt, 480 +ldrshgt, 480 +ldrshle, 480 +ldrshal, 480 +ldrshlo, 480 +ldrshcc, 480 +ldrshhs, 480 +ldrshcs, 480 +ldrshnv, 480 +ldrsht, 486 +ldrshteq, 486 +ldrshtne, 486 +ldrshtmi, 486 +ldrshtpl, 486 +ldrshtvs, 486 +ldrshtvc, 486 +ldrshthi, 486 +ldrshtls, 486 +ldrshtge, 486 +ldrshtlt, 486 +ldrshtgt, 486 +ldrshtle, 486 +ldrshtal, 486 +ldrshtlo, 486 +ldrshtcc, 486 +ldrshths, 486 +ldrshtcs, 486 +ldrshtnv, 486 +ldrt, 488 +ldreqt, 488 +ldrnet, 488 +ldrmit, 488 +ldrplt, 488 +ldrvst, 488 +ldrvct, 488 +ldrhit, 488 +ldrlst, 488 +ldrget, 488 +ldrltt, 488 +ldrgtt, 488 +ldrlet, 488 +ldralt, 488 +ldrlot, 488 +ldrcct, 488 +ldrhst, 488 +ldrcst, 488 +ldrnvt, 488 +ldrteq, 488 +ldrtne, 488 +ldrtmi, 488 +ldrtpl, 488 +ldrtvs, 488 +ldrtvc, 488 +ldrthi, 488 +ldrtls, 488 +ldrtge, 488 +ldrtlt, 488 +ldrtgt, 488 +ldrtle, 488 +ldrtal, 488 +ldrtlo, 488 +ldrtcc, 488 +ldrths, 488 +ldrtcs, 488 +ldrtnv, 488 +leavex, 1133 +lsl, 490 +lsleq, 490 +lslne, 490 +lslmi, 490 +lslpl, 490 +lslvs, 490 +lslvc, 490 +lslhi, 490 +lslls, 490 +lslge, 490 +lsllt, 490 +lslgt, 490 +lslle, 490 +lslal, 490 +lsllo, 490 +lslcc, 490 +lslhs, 490 +lslcs, 490 +lslnv, 490 +lsls, 490 +lsleqs, 490 +lslnes, 490 +lslmis, 490 +lslpls, 490 +lslvss, 490 +lslvcs, 490 +lslhis, 490 +lsllss, 490 +lslges, 490 +lsllts, 490 +lslgts, 490 +lslles, 490 +lslals, 490 +lsllos, 490 +lslccs, 490 +lslhss, 490 +lslcss, 490 +lslnvs, 490 +lsr, 494 +lsreq, 494 +lsrne, 494 +lsrmi, 494 +lsrpl, 494 +lsrvs, 494 +lsrvc, 494 +lsrhi, 494 +lsrls, 494 +lsrge, 494 +lsrlt, 494 +lsrgt, 494 +lsrle, 494 +lsral, 494 +lsrlo, 494 +lsrcc, 494 +lsrhs, 494 +lsrcs, 494 +lsrnv, 494 +lsrs, 494 +lsreqs, 494 +lsrnes, 494 +lsrmis, 494 +lsrpls, 494 +lsrvss, 494 +lsrvcs, 494 +lsrhis, 494 +lsrlss, 494 +lsrges, 494 +lsrlts, 494 +lsrgts, 494 +lsrles, 494 +lsrals, 494 +lsrlos, 494 +lsrccs, 494 +lsrhss, 494 +lsrcss, 494 +lsrnvs, 494 +mcr, 498 +mcreq, 498 +mcrne, 498 +mcrmi, 498 +mcrpl, 498 +mcrvs, 498 +mcrvc, 498 +mcrhi, 498 +mcrls, 498 +mcrge, 498 +mcrlt, 498 +mcrgt, 498 +mcrle, 498 +mcral, 498 +mcrlo, 498 +mcrcc, 498 +mcrhs, 498 +mcrcs, 498 +mcrnv, 498 +mcr2, 498 +mcr2eq, 498 +mcr2ne, 498 +mcr2mi, 498 +mcr2pl, 498 +mcr2vs, 498 +mcr2vc, 498 +mcr2hi, 498 +mcr2ls, 498 +mcr2ge, 498 +mcr2lt, 498 +mcr2gt, 498 +mcr2le, 498 +mcr2al, 498 +mcr2lo, 498 +mcr2cc, 498 +mcr2hs, 498 +mcr2cs, 498 +mcr2nv, 498 +mcrr, 500 +mcrreq, 500 +mcrrne, 500 +mcrrmi, 500 +mcrrpl, 500 +mcrrvs, 500 +mcrrvc, 500 +mcrrhi, 500 +mcrrls, 500 +mcrrge, 500 +mcrrlt, 500 +mcrrgt, 500 +mcrrle, 500 +mcrral, 500 +mcrrlo, 500 +mcrrcc, 500 +mcrrhs, 500 +mcrrcs, 500 +mcrrnv, 500 +mcrr2, 500 +mcrr2eq, 500 +mcrr2ne, 500 +mcrr2mi, 500 +mcrr2pl, 500 +mcrr2vs, 500 +mcrr2vc, 500 +mcrr2hi, 500 +mcrr2ls, 500 +mcrr2ge, 500 +mcrr2lt, 500 +mcrr2gt, 500 +mcrr2le, 500 +mcrr2al, 500 +mcrr2lo, 500 +mcrr2cc, 500 +mcrr2hs, 500 +mcrr2cs, 500 +mcrr2nv, 500 +mla, 502 +mlaeq, 502 +mlane, 502 +mlami, 502 +mlapl, 502 +mlavs, 502 +mlavc, 502 +mlahi, 502 +mlals, 502 +mlage, 502 +mlalt, 502 +mlagt, 502 +mlale, 502 +mlaal, 502 +mlalo, 502 +mlacc, 502 +mlahs, 502 +mlacs, 502 +mlanv, 502 +mlas, 502 +mlaeqs, 502 +mlanes, 502 +mlamis, 502 +mlapls, 502 +mlavss, 502 +mlavcs, 502 +mlahis, 502 +mlalss, 502 +mlages, 502 +mlalts, 502 +mlagts, 502 +mlales, 502 +mlaals, 502 +mlalos, 502 +mlaccs, 502 +mlahss, 502 +mlacss, 502 +mlanvs, 502 +mlaseq, 502 +mlasne, 502 +mlasmi, 502 +mlaspl, 502 +mlasvs, 502 +mlasvc, 502 +mlashi, 502 +mlasls, 502 +mlasge, 502 +mlaslt, 502 +mlasgt, 502 +mlasle, 502 +mlasal, 502 +mlaslo, 502 +mlascc, 502 +mlashs, 502 +mlascs, 502 +mlasnv, 502 +mls, 504 +mlseq, 504 +mlsne, 504 +mlsmi, 504 +mlspl, 504 +mlsvs, 504 +mlsvc, 504 +mlshi, 504 +mlsls, 504 +mlsge, 504 +mlslt, 504 +mlsgt, 504 +mlsle, 504 +mlsal, 504 +mlslo, 504 +mlscc, 504 +mlshs, 504 +mlscs, 504 +mlsnv, 504 +mov, 506 +moveq, 506 +movne, 506 +movmi, 506 +movpl, 506 +movvs, 506 +movvc, 506 +movhi, 506 +movls, 506 +movge, 506 +movlt, 506 +movgt, 506 +movle, 506 +moval, 506 +movlo, 506 +movcc, 506 +movhs, 506 +movcs, 506 +movnv, 506 +movs, 506 +moveqs, 506 +movnes, 506 +movmis, 506 +movpls, 506 +movvss, 506 +movvcs, 506 +movhis, 506 +movlss, 506 +movges, 506 +movlts, 506 +movgts, 506 +movles, 506 +movals, 506 +movlos, 506 +movccs, 506 +movhss, 506 +movcss, 506 +movnvs, 506 +movseq, 506 +movsne, 506 +movsmi, 506 +movspl, 506 +movsvs, 506 +movsvc, 506 +movshi, 506 +movsls, 506 +movsge, 506 +movslt, 506 +movsgt, 506 +movsle, 506 +movsal, 506 +movslo, 506 +movscc, 506 +movshs, 506 +movscs, 506 +movsnv, 506 +movw, 506 +movweq, 506 +movwne, 506 +movwmi, 506 +movwpl, 506 +movwvs, 506 +movwvc, 506 +movwhi, 506 +movwls, 506 +movwge, 506 +movwlt, 506 +movwgt, 506 +movwle, 506 +movwal, 506 +movwlo, 506 +movwcc, 506 +movwhs, 506 +movwcs, 506 +movwnv, 506 +movt, 512 +moveqt, 512 +movnet, 512 +movmit, 512 +movplt, 512 +movvst, 512 +movvct, 512 +movhit, 512 +movlst, 512 +movget, 512 +movltt, 512 +movgtt, 512 +movlet, 512 +movalt, 512 +movlot, 512 +movcct, 512 +movhst, 512 +movcst, 512 +movnvt, 512 +mrc, 514 +mrceq, 514 +mrcne, 514 +mrcmi, 514 +mrcpl, 514 +mrcvs, 514 +mrcvc, 514 +mrchi, 514 +mrcls, 514 +mrcge, 514 +mrclt, 514 +mrcgt, 514 +mrcle, 514 +mrcal, 514 +mrclo, 514 +mrccc, 514 +mrchs, 514 +mrccs, 514 +mrcnv, 514 +mrc2, 514 +mrc2eq, 514 +mrc2ne, 514 +mrc2mi, 514 +mrc2pl, 514 +mrc2vs, 514 +mrc2vc, 514 +mrc2hi, 514 +mrc2ls, 514 +mrc2ge, 514 +mrc2lt, 514 +mrc2gt, 514 +mrc2le, 514 +mrc2al, 514 +mrc2lo, 514 +mrc2cc, 514 +mrc2hs, 514 +mrc2cs, 514 +mrc2nv, 514 +mrrc, 516 +mrrceq, 516 +mrrcne, 516 +mrrcmi, 516 +mrrcpl, 516 +mrrcvs, 516 +mrrcvc, 516 +mrrchi, 516 +mrrcls, 516 +mrrcge, 516 +mrrclt, 516 +mrrcgt, 516 +mrrcle, 516 +mrrcal, 516 +mrrclo, 516 +mrrccc, 516 +mrrchs, 516 +mrrccs, 516 +mrrcnv, 516 +mrrc2, 516 +mrrc2eq, 516 +mrrc2ne, 516 +mrrc2mi, 516 +mrrc2pl, 516 +mrrc2vs, 516 +mrrc2vc, 516 +mrrc2hi, 516 +mrrc2ls, 516 +mrrc2ge, 516 +mrrc2lt, 516 +mrrc2gt, 516 +mrrc2le, 516 +mrrc2al, 516 +mrrc2lo, 516 +mrrc2cc, 516 +mrrc2hs, 516 +mrrc2cs, 516 +mrrc2nv, 516 +mrs, 518 +mrseq, 518 +mrsne, 518 +mrsmi, 518 +mrspl, 518 +mrsvs, 518 +mrsvc, 518 +mrshi, 518 +mrsls, 518 +mrsge, 518 +mrslt, 518 +mrsgt, 518 +mrsle, 518 +mrsal, 518 +mrslo, 518 +mrscc, 518 +mrshs, 518 +mrscs, 518 +mrsnv, 518 +msr, 520 +msreq, 520 +msrne, 520 +msrmi, 520 +msrpl, 520 +msrvs, 520 +msrvc, 520 +msrhi, 520 +msrls, 520 +msrge, 520 +msrlt, 520 +msrgt, 520 +msrle, 520 +msral, 520 +msrlo, 520 +msrcc, 520 +msrhs, 520 +msrcs, 520 +msrnv, 520 +mul, 524 +muleq, 524 +mulne, 524 +mulmi, 524 +mulpl, 524 +mulvs, 524 +mulvc, 524 +mulhi, 524 +mulls, 524 +mulge, 524 +mullt, 524 +mulgt, 524 +mulle, 524 +mulal, 524 +mullo, 524 +mulcc, 524 +mulhs, 524 +mulcs, 524 +mulnv, 524 +muls, 524 +muleqs, 524 +mulnes, 524 +mulmis, 524 +mulpls, 524 +mulvss, 524 +mulvcs, 524 +mulhis, 524 +mullss, 524 +mulges, 524 +mullts, 524 +mulgts, 524 +mulles, 524 +mulals, 524 +mullos, 524 +mulccs, 524 +mulhss, 524 +mulcss, 524 +mulnvs, 524 +mvn, 526 +mvneq, 526 +mvnne, 526 +mvnmi, 526 +mvnpl, 526 +mvnvs, 526 +mvnvc, 526 +mvnhi, 526 +mvnls, 526 +mvnge, 526 +mvnlt, 526 +mvngt, 526 +mvnle, 526 +mvnal, 526 +mvnlo, 526 +mvncc, 526 +mvnhs, 526 +mvncs, 526 +mvnnv, 526 +mvns, 526 +mvneqs, 526 +mvnnes, 526 +mvnmis, 526 +mvnpls, 526 +mvnvss, 526 +mvnvcs, 526 +mvnhis, 526 +mvnlss, 526 +mvnges, 526 +mvnlts, 526 +mvngts, 526 +mvnles, 526 +mvnals, 526 +mvnlos, 526 +mvnccs, 526 +mvnhss, 526 +mvncss, 526 +mvnnvs, 526 +mvnseq, 526 +mvnsne, 526 +mvnsmi, 526 +mvnspl, 526 +mvnsvs, 526 +mvnsvc, 526 +mvnshi, 526 +mvnsls, 526 +mvnsge, 526 +mvnslt, 526 +mvnsgt, 526 +mvnsle, 526 +mvnsal, 526 +mvnslo, 526 +mvnscc, 526 +mvnshs, 526 +mvnscs, 526 +mvnsnv, 526 +neg, 532 +nop, 534 +orn, 536 +orneq, 536 +ornne, 536 +ornmi, 536 +ornpl, 536 +ornvs, 536 +ornvc, 536 +ornhi, 536 +ornls, 536 +ornge, 536 +ornlt, 536 +orngt, 536 +ornle, 536 +ornal, 536 +ornlo, 536 +orncc, 536 +ornhs, 536 +orncs, 536 +ornnv, 536 +orns, 536 +orneqs, 536 +ornnes, 536 +ornmis, 536 +ornpls, 536 +ornvss, 536 +ornvcs, 536 +ornhis, 536 +ornlss, 536 +ornges, 536 +ornlts, 536 +orngts, 536 +ornles, 536 +ornals, 536 +ornlos, 536 +ornccs, 536 +ornhss, 536 +orncss, 536 +ornnvs, 536 +orr, 540 +orreq, 540 +orrne, 540 +orrmi, 540 +orrpl, 540 +orrvs, 540 +orrvc, 540 +orrhi, 540 +orrls, 540 +orrge, 540 +orrlt, 540 +orrgt, 540 +orrle, 540 +orral, 540 +orrlo, 540 +orrcc, 540 +orrhs, 540 +orrcs, 540 +orrnv, 540 +orrs, 540 +orreqs, 540 +orrnes, 540 +orrmis, 540 +orrpls, 540 +orrvss, 540 +orrvcs, 540 +orrhis, 540 +orrlss, 540 +orrges, 540 +orrlts, 540 +orrgts, 540 +orrles, 540 +orrals, 540 +orrlos, 540 +orrccs, 540 +orrhss, 540 +orrcss, 540 +orrnvs, 540 +orrseq, 540 +orrsne, 540 +orrsmi, 540 +orrspl, 540 +orrsvs, 540 +orrsvc, 540 +orrshi, 540 +orrsls, 540 +orrsge, 540 +orrslt, 540 +orrsgt, 540 +orrsle, 540 +orrsal, 540 +orrslo, 540 +orrscc, 540 +orrshs, 540 +orrscs, 540 +orrsnv, 540 +pkhbt, 546 +pkhbteq, 546 +pkhbtne, 546 +pkhbtmi, 546 +pkhbtpl, 546 +pkhbtvs, 546 +pkhbtvc, 546 +pkhbthi, 546 +pkhbtls, 546 +pkhbtge, 546 +pkhbtlt, 546 +pkhbtgt, 546 +pkhbtle, 546 +pkhbtal, 546 +pkhbtlo, 546 +pkhbtcc, 546 +pkhbths, 546 +pkhbtcs, 546 +pkhbtnv, 546 +pkhtb, 546 +pkhtbeq, 546 +pkhtbne, 546 +pkhtbmi, 546 +pkhtbpl, 546 +pkhtbvs, 546 +pkhtbvc, 546 +pkhtbhi, 546 +pkhtbls, 546 +pkhtbge, 546 +pkhtblt, 546 +pkhtbgt, 546 +pkhtble, 546 +pkhtbal, 546 +pkhtblo, 546 +pkhtbcc, 546 +pkhtbhs, 546 +pkhtbcs, 546 +pkhtbnv, 546 +pld, 548 +pldeq, 548 +pldne, 548 +pldmi, 548 +pldpl, 548 +pldvs, 548 +pldvc, 548 +pldhi, 548 +pldls, 548 +pldge, 548 +pldlt, 548 +pldgt, 548 +pldle, 548 +pldal, 548 +pldlo, 548 +pldcc, 548 +pldhs, 548 +pldcs, 548 +pldnv, 548 +pldw, 548 +pldweq, 548 +pldwne, 548 +pldwmi, 548 +pldwpl, 548 +pldwvs, 548 +pldwvc, 548 +pldwhi, 548 +pldwls, 548 +pldwge, 548 +pldwlt, 548 +pldwgt, 548 +pldwle, 548 +pldwal, 548 +pldwlo, 548 +pldwcc, 548 +pldwhs, 548 +pldwcs, 548 +pldwnv, 548 +pli, 554 +plieq, 554 +pline, 554 +plimi, 554 +plipl, 554 +plivs, 554 +plivc, 554 +plihi, 554 +plils, 554 +plige, 554 +plilt, 554 +pligt, 554 +plile, 554 +plial, 554 +plilo, 554 +plicc, 554 +plihs, 554 +plics, 554 +plinv, 554 +pop, 558 +popeq, 558 +popne, 558 +popmi, 558 +poppl, 558 +popvs, 558 +popvc, 558 +pophi, 558 +popls, 558 +popge, 558 +poplt, 558 +popgt, 558 +pople, 558 +popal, 558 +poplo, 558 +popcc, 558 +pophs, 558 +popcs, 558 +popnv, 558 +push, 560 +pusheq, 560 +pushne, 560 +pushmi, 560 +pushpl, 560 +pushvs, 560 +pushvc, 560 +pushhi, 560 +pushls, 560 +pushge, 560 +pushlt, 560 +pushgt, 560 +pushle, 560 +pushal, 560 +pushlo, 560 +pushcc, 560 +pushhs, 560 +pushcs, 560 +pushnv, 560 +qadd, 562 +qaddeq, 562 +qaddne, 562 +qaddmi, 562 +qaddpl, 562 +qaddvs, 562 +qaddvc, 562 +qaddhi, 562 +qaddls, 562 +qaddge, 562 +qaddlt, 562 +qaddgt, 562 +qaddle, 562 +qaddal, 562 +qaddlo, 562 +qaddcc, 562 +qaddhs, 562 +qaddcs, 562 +qaddnv, 562 +qadd16, 564 +qadd16eq, 564 +qadd16ne, 564 +qadd16mi, 564 +qadd16pl, 564 +qadd16vs, 564 +qadd16vc, 564 +qadd16hi, 564 +qadd16ls, 564 +qadd16ge, 564 +qadd16lt, 564 +qadd16gt, 564 +qadd16le, 564 +qadd16al, 564 +qadd16lo, 564 +qadd16cc, 564 +qadd16hs, 564 +qadd16cs, 564 +qadd16nv, 564 +qadd8, 566 +qadd8eq, 566 +qadd8ne, 566 +qadd8mi, 566 +qadd8pl, 566 +qadd8vs, 566 +qadd8vc, 566 +qadd8hi, 566 +qadd8ls, 566 +qadd8ge, 566 +qadd8lt, 566 +qadd8gt, 566 +qadd8le, 566 +qadd8al, 566 +qadd8lo, 566 +qadd8cc, 566 +qadd8hs, 566 +qadd8cs, 566 +qadd8nv, 566 +qaddsubx,568 +qaddsubxeq, 568 +qaddsubxne, 568 +qaddsubxmi, 568 +qaddsubxpl, 568 +qaddsubxvs, 568 +qaddsubxvc, 568 +qaddsubxhi, 568 +qaddsubxls, 568 +qaddsubxge, 568 +qaddsubxlt, 568 +qaddsubxgt, 568 +qaddsubxle, 568 +qaddsubxal, 568 +qaddsubxlo, 568 +qaddsubxcc, 568 +qaddsubxhs, 568 +qaddsubxcs, 568 +qaddsubxnv, 568 +qasx, 568 +qasxeq, 568 +qasxne, 568 +qasxmi, 568 +qasxpl, 568 +qasxvs, 568 +qasxvc, 568 +qasxhi, 568 +qasxls, 568 +qasxge, 568 +qasxlt, 568 +qasxgt, 568 +qasxle, 568 +qasxal, 568 +qasxlo, 568 +qasxcc, 568 +qasxhs, 568 +qasxcs, 568 +qasxnv, 568 +qdadd, 570 +qdaddeq, 570 +qdaddne, 570 +qdaddmi, 570 +qdaddpl, 570 +qdaddvs, 570 +qdaddvc, 570 +qdaddhi, 570 +qdaddls, 570 +qdaddge, 570 +qdaddlt, 570 +qdaddgt, 570 +qdaddle, 570 +qdaddal, 570 +qdaddlo, 570 +qdaddcc, 570 +qdaddhs, 570 +qdaddcs, 570 +qdaddnv, 570 +qdsub, 572 +qdsubeq, 572 +qdsubne, 572 +qdsubmi, 572 +qdsubpl, 572 +qdsubvs, 572 +qdsubvc, 572 +qdsubhi, 572 +qdsubls, 572 +qdsubge, 572 +qdsublt, 572 +qdsubgt, 572 +qdsuble, 572 +qdsubal, 572 +qdsublo, 572 +qdsubcc, 572 +qdsubhs, 572 +qdsubcs, 572 +qdsubnv, 572 +qsubaddx,574 +qsubaddxeq, 574 +qsubaddxne, 574 +qsubaddxmi, 574 +qsubaddxpl, 574 +qsubaddxvs, 574 +qsubaddxvc, 574 +qsubaddxhi, 574 +qsubaddxls, 574 +qsubaddxge, 574 +qsubaddxlt, 574 +qsubaddxgt, 574 +qsubaddxle, 574 +qsubaddxal, 574 +qsubaddxlo, 574 +qsubaddxcc, 574 +qsubaddxhs, 574 +qsubaddxcs, 574 +qsubaddxnv, 574 +qsax, 574 +qsaxeq, 574 +qsaxne, 574 +qsaxmi, 574 +qsaxpl, 574 +qsaxvs, 574 +qsaxvc, 574 +qsaxhi, 574 +qsaxls, 574 +qsaxge, 574 +qsaxlt, 574 +qsaxgt, 574 +qsaxle, 574 +qsaxal, 574 +qsaxlo, 574 +qsaxcc, 574 +qsaxhs, 574 +qsaxcs, 574 +qsaxnv, 574 +qsub, 576 +qsubeq, 576 +qsubne, 576 +qsubmi, 576 +qsubpl, 576 +qsubvs, 576 +qsubvc, 576 +qsubhi, 576 +qsubls, 576 +qsubge, 576 +qsublt, 576 +qsubgt, 576 +qsuble, 576 +qsubal, 576 +qsublo, 576 +qsubcc, 576 +qsubhs, 576 +qsubcs, 576 +qsubnv, 576 +qsub16, 578 +qsub16eq, 578 +qsub16ne, 578 +qsub16mi, 578 +qsub16pl, 578 +qsub16vs, 578 +qsub16vc, 578 +qsub16hi, 578 +qsub16ls, 578 +qsub16ge, 578 +qsub16lt, 578 +qsub16gt, 578 +qsub16le, 578 +qsub16al, 578 +qsub16lo, 578 +qsub16cc, 578 +qsub16hs, 578 +qsub16cs, 578 +qsub16nv, 578 +qsub8, 580 +qsub8eq, 580 +qsub8ne, 580 +qsub8mi, 580 +qsub8pl, 580 +qsub8vs, 580 +qsub8vc, 580 +qsub8hi, 580 +qsub8ls, 580 +qsub8ge, 580 +qsub8lt, 580 +qsub8gt, 580 +qsub8le, 580 +qsub8al, 580 +qsub8lo, 580 +qsub8cc, 580 +qsub8hs, 580 +qsub8cs, 580 +qsub8nv, 580 +rbit, 582 +rbiteq, 582 +rbitne, 582 +rbitmi, 582 +rbitpl, 582 +rbitvs, 582 +rbitvc, 582 +rbithi, 582 +rbitls, 582 +rbitge, 582 +rbitlt, 582 +rbitgt, 582 +rbitle, 582 +rbital, 582 +rbitlo, 582 +rbitcc, 582 +rbiths, 582 +rbitcs, 582 +rbitnv, 582 +rev, 584 +reveq, 584 +revne, 584 +revmi, 584 +revpl, 584 +revvs, 584 +revvc, 584 +revhi, 584 +revls, 584 +revge, 584 +revlt, 584 +revgt, 584 +revle, 584 +reval, 584 +revlo, 584 +revcc, 584 +revhs, 584 +revcs, 584 +revnv, 584 +rev16, 586 +rev16eq, 586 +rev16ne, 586 +rev16mi, 586 +rev16pl, 586 +rev16vs, 586 +rev16vc, 586 +rev16hi, 586 +rev16ls, 586 +rev16ge, 586 +rev16lt, 586 +rev16gt, 586 +rev16le, 586 +rev16al, 586 +rev16lo, 586 +rev16cc, 586 +rev16hs, 586 +rev16cs, 586 +rev16nv, 586 +revsh, 588 +revsheq, 588 +revshne, 588 +revshmi, 588 +revshpl, 588 +revshvs, 588 +revshvc, 588 +revshhi, 588 +revshls, 588 +revshge, 588 +revshlt, 588 +revshgt, 588 +revshle, 588 +revshal, 588 +revshlo, 588 +revshcc, 588 +revshhs, 588 +revshcs, 588 +revshnv, 588 +rfeda, `1574 +rfedaeq, 1574 +rfedane, 1574 +rfedami, 1574 +rfedapl, 1574 +rfedavs, 1574 +rfedavc, 1574 +rfedahi, 1574 +rfedals, 1574 +rfedage, 1574 +rfedalt, 1574 +rfedagt, 1574 +rfedale, 1574 +rfedaal, 1574 +rfedalo, 1574 +rfedacc, 1574 +rfedahs, 1574 +rfedacs, 1574 +rfedanv, 1574 +rfedb, 1574 +rfedbeq, 1574 +rfedbne, 1574 +rfedbmi, 1574 +rfedbpl, 1574 +rfedbvs, 1574 +rfedbvc, 1574 +rfedbhi, 1574 +rfedbls, 1574 +rfedbge, 1574 +rfedblt, 1574 +rfedbgt, 1574 +rfedble, 1574 +rfedbal, 1574 +rfedblo, 1574 +rfedbcc, 1574 +rfedbhs, 1574 +rfedbcs, 1574 +rfedbnv, 1574 +rfeia, 1574 +rfeiaeq, 1574 +rfeiane, 1574 +rfeiami, 1574 +rfeiapl, 1574 +rfeiavs, 1574 +rfeiavc, 1574 +rfeiahi, 1574 +rfeials, 1574 +rfeiage, 1574 +rfeialt, 1574 +rfeiagt, 1574 +rfeiale, 1574 +rfeiaal, 1574 +rfeialo, 1574 +rfeiacc, 1574 +rfeiahs, 1574 +rfeiacs, 1574 +rfeianv, 1574 +rfeib, 1574 +rfeibeq, 1574 +rfeibne, 1574 +rfeibmi, 1574 +rfeibpl, 1574 +rfeibvs, 1574 +rfeibvc, 1574 +rfeibhi, 1574 +rfeibls, 1574 +rfeibge, 1574 +rfeiblt, 1574 +rfeibgt, 1574 +rfeible, 1574 +rfeibal, 1574 +rfeiblo, 1574 +rfeibcc, 1574 +rfeibhs, 1574 +rfeibcs, 1574 +rfeibnv, 1574 +ror, 590 +roreq, 590 +rorne, 590 +rormi, 590 +rorpl, 590 +rorvs, 590 +rorvc, 590 +rorhi, 590 +rorls, 590 +rorge, 590 +rorlt, 590 +rorgt, 590 +rorle, 590 +roral, 590 +rorlo, 590 +rorcc, 590 +rorhs, 590 +rorcs, 590 +rornv, 590 +rors, 590 +roreqs, 590 +rornes, 590 +rormis, 590 +rorpls, 590 +rorvss, 590 +rorvcs, 590 +rorhis, 590 +rorlss, 590 +rorges, 590 +rorlts, 590 +rorgts, 590 +rorles, 590 +rorals, 590 +rorlos, 590 +rorccs, 590 +rorhss, 590 +rorcss, 590 +rornvs, 590 +rrx, 594 +rrxeq, 594 +rrxne, 594 +rrxmi, 594 +rrxpl, 594 +rrxvs, 594 +rrxvc, 594 +rrxhi, 594 +rrxls, 594 +rrxge, 594 +rrxlt, 594 +rrxgt, 594 +rrxle, 594 +rrxal, 594 +rrxlo, 594 +rrxcc, 594 +rrxhs, 594 +rrxcs, 594 +rrxnv, 594 +rrxs, 594 +rrxeqs, 594 +rrxnes, 594 +rrxmis, 594 +rrxpls, 594 +rrxvss, 594 +rrxvcs, 594 +rrxhis, 594 +rrxlss, 594 +rrxges, 594 +rrxlts, 594 +rrxgts, 594 +rrxles, 594 +rrxals, 594 +rrxlos, 594 +rrxccs, 594 +rrxhss, 594 +rrxcss, 594 +rrxnvs, 594 +rsb, 596 +rsbeq, 596 +rsbne, 596 +rsbmi, 596 +rsbpl, 596 +rsbvs, 596 +rsbvc, 596 +rsbhi, 596 +rsbls, 596 +rsbge, 596 +rsblt, 596 +rsbgt, 596 +rsble, 596 +rsbal, 596 +rsblo, 596 +rsbcc, 596 +rsbhs, 596 +rsbcs, 596 +rsbnv, 596 +rsbs, 596 +rsbeqs, 596 +rsbnes, 596 +rsbmis, 596 +rsbpls, 596 +rsbvss, 596 +rsbvcs, 596 +rsbhis, 596 +rsblss, 596 +rsbges, 596 +rsblts, 596 +rsbgts, 596 +rsbles, 596 +rsbals, 596 +rsblos, 596 +rsbccs, 596 +rsbhss, 596 +rsbcss, 596 +rsbnvs, 596 +rsbseq, 596 +rsbsne, 596 +rsbsmi, 596 +rsbspl, 596 +rsbsvs, 596 +rsbsvc, 596 +rsbshi, 596 +rsbsls, 596 +rsbsge, 596 +rsbslt, 596 +rsbsgt, 596 +rsbsle, 596 +rsbsal, 596 +rsbslo, 596 +rsbscc, 596 +rsbshs, 596 +rsbscs, 596 +rsbsnv, 596 +rsc, 602 +rsceq, 602 +rscne, 602 +rscmi, 602 +rscpl, 602 +rscvs, 602 +rscvc, 602 +rschi, 602 +rscls, 602 +rscge, 602 +rsclt, 602 +rscgt, 602 +rscle, 602 +rscal, 602 +rsclo, 602 +rsccc, 602 +rschs, 602 +rsccs, 602 +rscnv, 602 +rscs, 602 +rsceqs, 602 +rscnes, 602 +rscmis, 602 +rscpls, 602 +rscvss, 602 +rscvcs, 602 +rschis, 602 +rsclss, 602 +rscges, 602 +rsclts, 602 +rscgts, 602 +rscles, 602 +rscals, 602 +rsclos, 602 +rscccs, 602 +rschss, 602 +rsccss, 602 +rscnvs, 602 +rscseq, 602 +rscsne, 602 +rscsmi, 602 +rscspl, 602 +rscsvs, 602 +rscsvc, 602 +rscshi, 602 +rscsls, 602 +rscsge, 602 +rscslt, 602 +rscsgt, 602 +rscsle, 602 +rscsal, 602 +rscslo, 602 +rscscc, 602 +rscshs, 602 +rscscs, 602 +rscsnv, 602 +sadd16, 608 +sadd16eq, 608 +sadd16ne, 608 +sadd16mi, 608 +sadd16pl, 608 +sadd16vs, 608 +sadd16vc, 608 +sadd16hi, 608 +sadd16ls, 608 +sadd16ge, 608 +sadd16lt, 608 +sadd16gt, 608 +sadd16le, 608 +sadd16al, 608 +sadd16lo, 608 +sadd16cc, 608 +sadd16hs, 608 +sadd16cs, 608 +sadd16nv, 608 +sadd8, 610 +sadd8eq, 610 +sadd8ne, 610 +sadd8mi, 610 +sadd8pl, 610 +sadd8vs, 610 +sadd8vc, 610 +sadd8hi, 610 +sadd8ls, 610 +sadd8ge, 610 +sadd8lt, 610 +sadd8gt, 610 +sadd8le, 610 +sadd8al, 610 +sadd8lo, 610 +sadd8cc, 610 +sadd8hs, 610 +sadd8cs, 610 +sadd8nv, 610 +saddsubx,612 +saddsubxeq, 612 +saddsubxne, 612 +saddsubxmi, 612 +saddsubxpl, 612 +saddsubxvs, 612 +saddsubxvc, 612 +saddsubxhi, 612 +saddsubxls, 612 +saddsubxge, 612 +saddsubxlt, 612 +saddsubxgt, 612 +saddsubxle, 612 +saddsubxal, 612 +saddsubxlo, 612 +saddsubxcc, 612 +saddsubxhs, 612 +saddsubxcs, 612 +saddsubxnv, 612 +sasx, 612 +sasxeq, 612 +sasxne, 612 +sasxmi, 612 +sasxpl, 612 +sasxvs, 612 +sasxvc, 612 +sasxhi, 612 +sasxls, 612 +sasxge, 612 +sasxlt, 612 +sasxgt, 612 +sasxle, 612 +sasxal, 612 +sasxlo, 612 +sasxcc, 612 +sasxhs, 612 +sasxcs, 612 +sasxnv, 612 +sbc, 614 +sbceq, 614 +sbcne, 614 +sbcmi, 614 +sbcpl, 614 +sbcvs, 614 +sbcvc, 614 +sbchi, 614 +sbcls, 614 +sbcge, 614 +sbclt, 614 +sbcgt, 614 +sbcle, 614 +sbcal, 614 +sbclo, 614 +sbccc, 614 +sbchs, 614 +sbccs, 614 +sbcnv, 614 +sbcs, 614 +sbceqs, 614 +sbcnes, 614 +sbcmis, 614 +sbcpls, 614 +sbcvss, 614 +sbcvcs, 614 +sbchis, 614 +sbclss, 614 +sbcges, 614 +sbclts, 614 +sbcgts, 614 +sbcles, 614 +sbcals, 614 +sbclos, 614 +sbcccs, 614 +sbchss, 614 +sbccss, 614 +sbcnvs, 614 +sbcseq, 614 +sbcsne, 614 +sbcsmi, 614 +sbcspl, 614 +sbcsvs, 614 +sbcsvc, 614 +sbcshi, 614 +sbcsls, 614 +sbcsge, 614 +sbcslt, 614 +sbcsgt, 614 +sbcsle, 614 +sbcsal, 614 +sbcslo, 614 +sbcscc, 614 +sbcshs, 614 +sbcscs, 614 +sbcsnv, 614 +sbfx, 620 +sbfxeq, 620 +sbfxne, 620 +sbfxmi, 620 +sbfxpl, 620 +sbfxvs, 620 +sbfxvc, 620 +sbfxhi, 620 +sbfxls, 620 +sbfxge, 620 +sbfxlt, 620 +sbfxgt, 620 +sbfxle, 620 +sbfxal, 620 +sbfxlo, 620 +sbfxcc, 620 +sbfxhs, 620 +sbfxcs, 620 +sbfxnv, 620 +sdiv, 622 +sdiveq, 622 +sdivne, 622 +sdivmi, 622 +sdivpl, 622 +sdivvs, 622 +sdivvc, 622 +sdivhi, 622 +sdivls, 622 +sdivge, 622 +sdivlt, 622 +sdivgt, 622 +sdivle, 622 +sdival, 622 +sdivlo, 622 +sdivcc, 622 +sdivhs, 622 +sdivcs, 622 +sdivnv, 622 +sel, 622 +seleq, 622 +selne, 622 +selmi, 622 +selpl, 622 +selvs, 622 +selvc, 622 +selhi, 622 +sells, 622 +selge, 622 +sellt, 622 +selgt, 622 +selle, 622 +selal, 622 +sello, 622 +selcc, 622 +selhs, 622 +selcs, 622 +selnv, 622 +setend, 626 +sev, 628 +seveq, 628 +sevne, 628 +sevmi, 628 +sevpl, 628 +sevvs, 628 +sevvc, 628 +sevhi, 628 +sevls, 628 +sevge, 628 +sevlt, 628 +sevgt, 628 +sevle, 628 +seval, 628 +sevlo, 628 +sevcc, 628 +sevhs, 628 +sevcs, 628 +sevnv, 628 +shadd16,630 +shadd16eq, 630 +shadd16ne, 630 +shadd16mi, 630 +shadd16pl, 630 +shadd16vs, 630 +shadd16vc, 630 +shadd16hi, 630 +shadd16ls, 630 +shadd16ge, 630 +shadd16lt, 630 +shadd16gt, 630 +shadd16le, 630 +shadd16al, 630 +shadd16lo, 630 +shadd16cc, 630 +shadd16hs, 630 +shadd16cs, 630 +shadd16nv, 630 +shadd8, 632 +shadd8eq, 632 +shadd8ne, 632 +shadd8mi, 632 +shadd8pl, 632 +shadd8vs, 632 +shadd8vc, 632 +shadd8hi, 632 +shadd8ls, 632 +shadd8ge, 632 +shadd8lt, 632 +shadd8gt, 632 +shadd8le, 632 +shadd8al, 632 +shadd8lo, 632 +shadd8cc, 632 +shadd8hs, 632 +shadd8cs, 632 +shadd8nv, 632 +shaddsubx,634 +shaddsubxeq, 634 +shaddsubxne, 634 +shaddsubxmi, 634 +shaddsubxpl, 634 +shaddsubxvs, 634 +shaddsubxvc, 634 +shaddsubxhi, 634 +shaddsubxls, 634 +shaddsubxge, 634 +shaddsubxlt, 634 +shaddsubxgt, 634 +shaddsubxle, 634 +shaddsubxal, 634 +shaddsubxlo, 634 +shaddsubxcc, 634 +shaddsubxhs, 634 +shaddsubxcs, 634 +shaddsubxnv, 634 +shasx, 634 +shasxeq, 634 +shasxne, 634 +shasxmi, 634 +shasxpl, 634 +shasxvs, 634 +shasxvc, 634 +shasxhi, 634 +shasxls, 634 +shasxge, 634 +shasxlt, 634 +shasxgt, 634 +shasxle, 634 +shasxal, 634 +shasxlo, 634 +shasxcc, 634 +shasxhs, 634 +shasxcs, 634 +shasxnv, 634 +shsubaddx,636 +shsubaddxeq, 636 +shsubaddxne, 636 +shsubaddxmi, 636 +shsubaddxpl, 636 +shsubaddxvs, 636 +shsubaddxvc, 636 +shsubaddxhi, 636 +shsubaddxls, 636 +shsubaddxge, 636 +shsubaddxlt, 636 +shsubaddxgt, 636 +shsubaddxle, 636 +shsubaddxal, 636 +shsubaddxlo, 636 +shsubaddxcc, 636 +shsubaddxhs, 636 +shsubaddxcs, 636 +shsubaddxnv, 636 +shsax, 636 +shsaxeq, 636 +shsaxne, 636 +shsaxmi, 636 +shsaxpl, 636 +shsaxvs, 636 +shsaxvc, 636 +shsaxhi, 636 +shsaxls, 636 +shsaxge, 636 +shsaxlt, 636 +shsaxgt, 636 +shsaxle, 636 +shsaxal, 636 +shsaxlo, 636 +shsaxcc, 636 +shsaxhs, 636 +shsaxcs, 636 +shsaxnv, 636 +shsub16,638 +shsub16eq, 638 +shsub16ne, 638 +shsub16mi, 638 +shsub16pl, 638 +shsub16vs, 638 +shsub16vc, 638 +shsub16hi, 638 +shsub16ls, 638 +shsub16ge, 638 +shsub16lt, 638 +shsub16gt, 638 +shsub16le, 638 +shsub16al, 638 +shsub16lo, 638 +shsub16cc, 638 +shsub16hs, 638 +shsub16cs, 638 +shsub16nv, 638 +shsub8, 640 +shsub8eq, 640 +shsub8ne, 640 +shsub8mi, 640 +shsub8pl, 640 +shsub8vs, 640 +shsub8vc, 640 +shsub8hi, 640 +shsub8ls, 640 +shsub8ge, 640 +shsub8lt, 640 +shsub8gt, 640 +shsub8le, 640 +shsub8al, 640 +shsub8lo, 640 +shsub8cc, 640 +shsub8hs, 640 +shsub8cs, 640 +shsub8nv, 640 +smc, 1576 +smi, 1576 +smlabb, 642 +smlabbeq, 642 +smlabbne, 642 +smlabbmi, 642 +smlabbpl, 642 +smlabbvs, 642 +smlabbvc, 642 +smlabbhi, 642 +smlabbls, 642 +smlabbge, 642 +smlabblt, 642 +smlabbgt, 642 +smlabble, 642 +smlabbal, 642 +smlabblo, 642 +smlabbcc, 642 +smlabbhs, 642 +smlabbcs, 642 +smlabbnv, 642 +smlabt, 642 +smlabteq, 642 +smlabtne, 642 +smlabtmi, 642 +smlabtpl, 642 +smlabtvs, 642 +smlabtvc, 642 +smlabthi, 642 +smlabtls, 642 +smlabtge, 642 +smlabtlt, 642 +smlabtgt, 642 +smlabtle, 642 +smlabtal, 642 +smlabtlo, 642 +smlabtcc, 642 +smlabths, 642 +smlabtcs, 642 +smlabtnv, 642 +smlatb, 642 +smlatbeq, 642 +smlatbne, 642 +smlatbmi, 642 +smlatbpl, 642 +smlatbvs, 642 +smlatbvc, 642 +smlatbhi, 642 +smlatbls, 642 +smlatbge, 642 +smlatblt, 642 +smlatbgt, 642 +smlatble, 642 +smlatbal, 642 +smlatblo, 642 +smlatbcc, 642 +smlatbhs, 642 +smlatbcs, 642 +smlatbnv, 642 +smlatt, 642 +smlatteq, 642 +smlattne, 642 +smlattmi, 642 +smlattpl, 642 +smlattvs, 642 +smlattvc, 642 +smlatthi, 642 +smlattls, 642 +smlattge, 642 +smlattlt, 642 +smlattgt, 642 +smlattle, 642 +smlattal, 642 +smlattlo, 642 +smlattcc, 642 +smlatths, 642 +smlattcs, 642 +smlattnv, 642 +smlad, 644 +smladeq, 644 +smladne, 644 +smladmi, 644 +smladpl, 644 +smladvs, 644 +smladvc, 644 +smladhi, 644 +smladls, 644 +smladge, 644 +smladlt, 644 +smladgt, 644 +smladle, 644 +smladal, 644 +smladlo, 644 +smladcc, 644 +smladhs, 644 +smladcs, 644 +smladnv, 644 +smladx, 644 +smladxeq, 644 +smladxne, 644 +smladxmi, 644 +smladxpl, 644 +smladxvs, 644 +smladxvc, 644 +smladxhi, 644 +smladxls, 644 +smladxge, 644 +smladxlt, 644 +smladxgt, 644 +smladxle, 644 +smladxal, 644 +smladxlo, 644 +smladxcc, 644 +smladxhs, 644 +smladxcs, 644 +smladxnv, 644 +smlal, 646 +smlaleq, 646 +smlalne, 646 +smlalmi, 646 +smlalpl, 646 +smlalvs, 646 +smlalvc, 646 +smlalhi, 646 +smlalls, 646 +smlalge, 646 +smlallt, 646 +smlalgt, 646 +smlalle, 646 +smlalal, 646 +smlallo, 646 +smlalcc, 646 +smlalhs, 646 +smlalcs, 646 +smlalnv, 646 +smlals, 646 +smlaleqs, 646 +smlalnes, 646 +smlalmis, 646 +smlalpls, 646 +smlalvss, 646 +smlalvcs, 646 +smlalhis, 646 +smlallss, 646 +smlalges, 646 +smlallts, 646 +smlalgts, 646 +smlalles, 646 +smlalals, 646 +smlallos, 646 +smlalccs, 646 +smlalhss, 646 +smlalcss, 646 +smlalnvs, 646 +smlalseq,646 +smlalsne, 646 +smlalsmi, 646 +smlalspl, 646 +smlalsvs, 646 +smlalsvc, 646 +smlalshi, 646 +smlalsls, 646 +smlalsge, 646 +smlalslt, 646 +smlalsgt, 646 +smlalsle, 646 +smlalsal, 646 +smlalslo, 646 +smlalscc, 646 +smlalshs, 646 +smlalscs, 646 +smlalsnv, 646 +smlalbb,648 +smlalbbeq, 648 +smlalbbne, 648 +smlalbbmi, 648 +smlalbbpl, 648 +smlalbbvs, 648 +smlalbbvc, 648 +smlalbbhi, 648 +smlalbbls, 648 +smlalbbge, 648 +smlalbblt, 648 +smlalbbgt, 648 +smlalbble, 648 +smlalbbal, 648 +smlalbblo, 648 +smlalbbcc, 648 +smlalbbhs, 648 +smlalbbcs, 648 +smlalbbnv, 648 +smlalbt,648 +smlalbteq, 648 +smlalbtne, 648 +smlalbtmi, 648 +smlalbtpl, 648 +smlalbtvs, 648 +smlalbtvc, 648 +smlalbthi, 648 +smlalbtls, 648 +smlalbtge, 648 +smlalbtlt, 648 +smlalbtgt, 648 +smlalbtle, 648 +smlalbtal, 648 +smlalbtlo, 648 +smlalbtcc, 648 +smlalbths, 648 +smlalbtcs, 648 +smlalbtnv, 648 +smlaltb,648 +smlaltbeq, 648 +smlaltbne, 648 +smlaltbmi, 648 +smlaltbpl, 648 +smlaltbvs, 648 +smlaltbvc, 648 +smlaltbhi, 648 +smlaltbls, 648 +smlaltbge, 648 +smlaltblt, 648 +smlaltbgt, 648 +smlaltble, 648 +smlaltbal, 648 +smlaltblo, 648 +smlatlbcc, 648 +smlatlbhs, 648 +smlatlbcs, 648 +smlatlbnv, 648 +smlaltt,648 +smlaltteq, 648 +smlalttne, 648 +smlalttmi, 648 +smlalttpl, 648 +smlalttvs, 648 +smlalttvc, 648 +smlaltthi, 648 +smlalttls, 648 +smlalttge, 648 +smlalttlt, 648 +smlalttgt, 648 +smlalttle, 648 +smlalttal, 648 +smlalttlo, 648 +smlalttcc, 648 +smlaltths, 648 +smlalttcs, 648 +smlalttnv, 648 +smlald, 650 +smlaldeq, 650 +smlaldne, 650 +smlaldmi, 650 +smlaldpl, 650 +smlaldvs, 650 +smlaldvc, 650 +smlaldhi, 650 +smlaldls, 650 +smlaldge, 650 +smlaldlt, 650 +smlaldgt, 650 +smlaldle, 650 +smlaldal, 650 +smlaldlo, 650 +smlaldcc, 650 +smlaldhs, 650 +smlaldcs, 650 +smlaldnv, 650 +smlawb, 652 +smlawbeq, 652 +smlawbne, 652 +smlawbmi, 652 +smlawbpl, 652 +smlawbvs, 652 +smlawbvc, 652 +smlawbhi, 652 +smlawbls, 652 +smlawbge, 652 +smlawblt, 652 +smlawbgt, 652 +smlawble, 652 +smlawbal, 652 +smlawblo, 652 +smlawbcc, 652 +smlawbhs, 652 +smlawbcs, 652 +smlawbnv, 652 +smlawt, 652 +smlawteq, 652 +smlawtne, 652 +smlawtmi, 652 +smlawtpl, 652 +smlawtvs, 652 +smlawtvc, 652 +smlawthi, 652 +smlawtls, 652 +smlawtge, 652 +smlawtlt, 652 +smlawtgt, 652 +smlawtle, 652 +smlawtal, 652 +smlawtlo, 652 +smlawtcc, 652 +smlawths, 652 +smlawtcs, 652 +smlawtnv, 652 +smlsd, 654 +smlsdeq, 654 +smlsdne, 654 +smlsdmi, 654 +smlsdpl, 654 +smlsdvs, 654 +smlsdvc, 654 +smlsdhi, 654 +smlsdls, 654 +smlsdge, 654 +smlsdlt, 654 +smlsdgt, 654 +smlsdle, 654 +smlsdal, 654 +smlsdlo, 654 +smlsdcc, 654 +smlsdhs, 654 +smlsdcs, 654 +smlsdnv, 654 +smlsdx, 654 +smlsdxeq, 654 +smlsdxne, 654 +smlsdxmi, 654 +smlsdxpl, 654 +smlsdxvs, 654 +smlsdxvc, 654 +smlsdxhi, 654 +smlsdxls, 654 +smlsdxge, 654 +smlsdxlt, 654 +smlsdxgt, 654 +smlsdxle, 654 +smlsdxal, 654 +smlsdxlo, 654 +smlsdxcc, 654 +smlsdxhs, 654 +smlsdxcs, 654 +smlsdxnv, 654 +smlsld, 656 +smlsldeq, 656 +smlsldne, 656 +smlsldmi, 656 +smlsldpl, 656 +smlsldvs, 656 +smlsldvc, 656 +smlsldhi, 656 +smlsldls, 656 +smlsldge, 656 +smlsldlt, 656 +smlsldgt, 656 +smlsldle, 656 +smlsldal, 656 +smlsldlo, 656 +smlsldcc, 656 +smlsldhs, 656 +smlsldcs, 656 +smlsldnv, 656 +smlsldx 656 +smlsldxeq, 656 +smlsldxne, 656 +smlsldxmi, 656 +smlsldxpl, 656 +smlsldxvs, 656 +smlsldxvc, 656 +smlsldxhi, 656 +smlsldxls, 656 +smlsldxge, 656 +smlsldxlt, 656 +smlsldxgt, 656 +smlsldxle, 656 +smlsldxal, 656 +smlsldxlo, 656 +smlsldxcc, 656 +smlsldxhs, 656 +smlsldxcs, 656 +smlsldxnv, 656 +smmla, 658 +smmlaeq, 658 +smmlane, 658 +smmlami, 658 +smmlapl, 658 +smmlavs, 658 +smmlavc, 658 +smmlahi, 658 +smmlals, 658 +smmlage, 658 +smmlalt, 658 +smmlagt, 658 +smmlale, 658 +smmlaal, 658 +smmlalo, 658 +smmlacc, 658 +smmlahs, 658 +smmlacs, 658 +smmlanv, 658 +smmlar, 658 +smmlareq, 658 +smmlarne, 658 +smmlarmi, 658 +smmlarpl, 658 +smmlarvs, 658 +smmlarvc, 658 +smmlarhi, 658 +smmlarls, 658 +smmlarge, 658 +smmlarlt, 658 +smmlargt, 658 +smmlarle, 658 +smmlaral, 658 +smmlarlo, 658 +smmlarcc, 658 +smmlarhs, 658 +smmlarcs, 658 +smmlarnv, 658 +smmls, 660 +smmlseq, 660 +smmlsne, 660 +smmlsmi, 660 +smmlspl, 660 +smmlsvs, 660 +smmlsvc, 660 +smmlshi, 660 +smmlsls, 660 +smmlsge, 660 +smmlslt, 660 +smmlsgt, 660 +smmlsle, 660 +smmlsal, 660 +smmlslo, 660 +smmlscc, 660 +smmlshs, 660 +smmlscs, 660 +smmlsnv, 660 +smmlsr, 660 +smmlsreq, 660 +smmlsrne, 660 +smmlsrmi, 660 +smmlsrpl, 660 +smmlsrvs, 660 +smmlsrvc, 660 +smmlsrhi, 660 +smmlsrls, 660 +smmlsrge, 660 +smmlsrlt, 660 +smmlsrgt, 660 +smmlsrle, 660 +smmlsral, 660 +smmlsrlo, 660 +smmlsrcc, 660 +smmlsrhs, 660 +smmlsrcs, 660 +smmlsrnv, 660 +smmul, 662 +smmuleq, 662 +smmulne, 662 +smmulmi, 662 +smmulpl, 662 +smmulvs, 662 +smmulvc, 662 +smmulhi, 662 +smmulls, 662 +smmulge, 662 +smmullt, 662 +smmulgt, 662 +smmulle, 662 +smmulal, 662 +smmullo, 662 +smmulcc, 662 +smmulhs, 662 +smmulcs, 662 +smmulnv, 662 +smmulr, 662 +smmulreq, 662 +smmulrne, 662 +smmulrmi, 662 +smmulrpl, 662 +smmulrvs, 662 +smmulrvc, 662 +smmulrhi, 662 +smmulrls, 662 +smmulrge, 662 +smmulrlt, 662 +smmulrgt, 662 +smmulrle, 662 +smmulral, 662 +smmulrlo, 662 +smmulrcc, 662 +smmulrhs, 662 +smmulrcs, 662 +smmulrnv, 662 +smuad, 664 +smuadeq, 664 +smuadne, 664 +smuadmi, 664 +smuadpl, 664 +smuadvs, 664 +smuadvc, 664 +smuadhi, 664 +smuadls, 664 +smuadge, 664 +smuadlt, 664 +smuadgt, 664 +smuadle, 664 +smuadal, 664 +smuadlo, 664 +smuadcc, 664 +smuadhs, 664 +smuadcs, 664 +smuadnv, 664 +smuadx, 664 +smuadxeq, 664 +smuadxne, 664 +smuadxmi, 664 +smuadxpl, 664 +smuadxvs, 664 +smuadxvc, 664 +smuadxhi, 664 +smuadxls, 664 +smuadxge, 664 +smuadxlt, 664 +smuadxgt, 664 +smuadxle, 664 +smuadxal, 664 +smuadxlo, 664 +smuadxcc, 664 +smuadxhs, 664 +smuadxcs, 664 +smuadxnv, 664 +smulbb, 666 +smulbbeq, 666 +smulbbne, 666 +smulbbmi, 666 +smulbbpl, 666 +smulbbvs, 666 +smulbbvc, 666 +smulbbhi, 666 +smulbbls, 666 +smulbbge, 666 +smulbblt, 666 +smulbbgt, 666 +smulbble, 666 +smulbbal, 666 +smulbblo, 666 +smulbbcc, 666 +smulbbhs, 666 +smulbbcs, 666 +smulbbnv, 666 +smulbt, 666 +smulbteq, 666 +smulbtne, 666 +smulbtmi, 666 +smulbtpl, 666 +smulbtvs, 666 +smulbtvc, 666 +smulbthi, 666 +smulbtls, 666 +smulbtge, 666 +smulbtlt, 666 +smulbtgt, 666 +smulbtle, 666 +smulbtal, 666 +smulbtlo, 666 +smulbtcc, 666 +smulbths, 666 +smulbtcs, 666 +smulbtnv, 666 +smultb, 666 +smultbeq, 666 +smultbne, 666 +smultbmi, 666 +smultbpl, 666 +smultbvs, 666 +smultbvc, 666 +smultbhi, 666 +smultbls, 666 +smultbge, 666 +smultblt, 666 +smultbgt, 666 +smultble, 666 +smultbal, 666 +smultblo, 666 +smultbcc, 666 +smultbhs, 666 +smultbcs, 666 +smultbnv, 666 +smultt, 666 +smultteq, 666 +smulttne, 666 +smulttmi, 666 +smulttpl, 666 +smulttvs, 666 +smulttvc, 666 +smultthi, 666 +smulttls, 666 +smulttge, 666 +smulttlt, 666 +smulttgt, 666 +smulttle, 666 +smulttal, 666 +smulttlo, 666 +smulttcc, 666 +smultths, 666 +smulttcs, 666 +smulttnv, 666 +smull, 668 +smulleq, 668 +smullne, 668 +smullmi, 668 +smullpl, 668 +smullvs, 668 +smullvc, 668 +smullhi, 668 +smullls, 668 +smullge, 668 +smulllt, 668 +smullgt, 668 +smullle, 668 +smullal, 668 +smulllo, 668 +smullcc, 668 +smullhs, 668 +smullcs, 668 +smullnv, 668 +smulls, 668 +smulleqs, 668 +smullnes, 668 +smullmis, 668 +smullpls, 668 +smullvss, 668 +smullvcs, 668 +smullhis, 668 +smulllss, 668 +smullges, 668 +smulllts, 668 +smullgts, 668 +smullles, 668 +smullals, 668 +smulllos, 668 +smullccs, 668 +smullhss, 668 +smullcss, 668 +smullnvs, 668 +smullseq,668 +smullsne, 668 +smullsmi, 668 +smullspl, 668 +smullsvs, 668 +smullsvc, 668 +smullshi, 668 +smullsls, 668 +smullsge, 668 +smullslt, 668 +smullsgt, 668 +smullsle, 668 +smullsal, 668 +smullslo, 668 +smullscc, 668 +smullshs, 668 +smullscs, 668 +smullsnv, 668 +smulwb, 670 +smulwbeq, 670 +smulwbne, 670 +smulwbmi, 670 +smulwbpl, 670 +smulwbvs, 670 +smulwbvc, 670 +smulwbhi, 670 +smulwbls, 670 +smulwbge, 670 +smulwblt, 670 +smulwbgt, 670 +smulwble, 670 +smulwbal, 670 +smulwblo, 670 +smulwbcc, 670 +smulwbhs, 670 +smulwbcs, 670 +smulwbnv, 670 +smulwt, 670 +smulwteq, 670 +smulwtne, 670 +smulwtmi, 670 +smulwtpl, 670 +smulwtvs, 670 +smulwtvc, 670 +smulwthi, 670 +smulwtls, 670 +smulwtge, 670 +smulwtlt, 670 +smulwtgt, 670 +smulwtle, 670 +smulwtal, 670 +smulwtlo, 670 +smulwtcc, 670 +smulwths, 670 +smulwtcs, 670 +smulwtnv, 670 +smusd, 672 +smusdeq, 672 +smusdne, 672 +smusdmi, 672 +smusdpl, 672 +smusdvs, 672 +smusdvc, 672 +smusdhi, 672 +smusdls, 672 +smusdge, 672 +smusdlt, 672 +smusdgt, 672 +smusdle, 672 +smusdal, 672 +smusdlo, 672 +smusdcc, 672 +smusdhs, 672 +smusdcs, 672 +smusdnv, 672 +smusdx, 672 +smusdxeq, 672 +smusdxne, 672 +smusdxmi, 672 +smusdxpl, 672 +smusdxvs, 672 +smusdxvc, 672 +smusdxhi, 672 +smusdxls, 672 +smusdxge, 672 +smusdxlt, 672 +smusdxgt, 672 +smusdxle, 672 +smusdxal, 672 +smusdxlo, 672 +smusdxcc, 672 +smusdxhs, 672 +smusdxcs, 672 +smusdxnv, 672 +srsda, 1578 +srsdaeq, 1578 +srsdane, 1578 +srsdami, 1578 +srsdapl, 1578 +srsdavs, 1578 +srsdavc, 1578 +srsdahi, 1578 +srsdals, 1578 +srsdage, 1578 +srsdalt, 1578 +srsdagt, 1578 +srsdale, 1578 +srsdaal, 1578 +srsdalo, 1578 +srsdacc, 1578 +srsdahs, 1578 +srsdacs, 1578 +srsdanv, 1578 +srsdb, 1578 +srsdbeq, 1578 +srsdbne, 1578 +srsdbmi, 1578 +srsdbpl, 1578 +srsdbvs, 1578 +srsdbvc, 1578 +srsdbhi, 1578 +srsdbls, 1578 +srsdbge, 1578 +srsdblt, 1578 +srsdbgt, 1578 +srsdble, 1578 +srsdbal, 1578 +srsdblo, 1578 +srsdbcc, 1578 +srsdbhs, 1578 +srsdbcs, 1578 +srsdbnv, 1578 +srsia, 1578 +srsiaeq, 1578 +srsiane, 1578 +srsiami, 1578 +srsiapl, 1578 +srsiavs, 1578 +srsiavc, 1578 +srsiahi, 1578 +srsials, 1578 +srsiage, 1578 +srsialt, 1578 +srsiagt, 1578 +srsiale, 1578 +srsiaal, 1578 +srsialo, 1578 +srsiacc, 1578 +srsiahs, 1578 +srsiacs, 1578 +srsianv, 1578 +srsib, 1578 +srsibeq, 1578 +srsibne, 1578 +srsibmi, 1578 +srsibpl, 1578 +srsibvs, 1578 +srsibvc, 1578 +srsibhi, 1578 +srsibls, 1578 +srsibge, 1578 +srsiblt, 1578 +srsibgt, 1578 +srsible, 1578 +srsibal, 1578 +srsiblo, 1578 +srsibcc, 1578 +srsibhs, 1578 +srsibcs, 1578 +srsibnv, 1578 +ssat, 674 +ssateq, 674 +ssatne, 674 +ssatmi, 674 +ssatpl, 674 +ssatvs, 674 +ssatvc, 674 +ssathi, 674 +ssatls, 674 +ssatge, 674 +ssatlt, 674 +ssatgt, 674 +ssatle, 674 +ssatal, 674 +ssatlo, 674 +ssatcc, 674 +ssaths, 674 +ssatcs, 674 +ssatnv, 674 +ssat16, 676 +ssateq16, 676 +ssatne16, 676 +ssatmi16, 676 +ssatpl16, 676 +ssatvs16, 676 +ssatvc16, 676 +ssathi16, 676 +ssatls16, 676 +ssatge16, 676 +ssatlt16, 676 +ssatgt16, 676 +ssatle16, 676 +ssatal16, 676 +ssatlo16, 676 +ssatcc16, 676 +ssaths16, 676 +ssatcs16, 676 +ssatnv16, 676 +ssubaddx,678 +ssubaddxeq, 678 +ssubaddxne, 678 +ssubaddxmi, 678 +ssubaddxpl, 678 +ssubaddxvs, 678 +ssubaddxvc, 678 +ssubaddxhi, 678 +ssubaddxls, 678 +ssubaddxge, 678 +ssubaddxlt, 678 +ssubaddxgt, 678 +ssubaddxle, 678 +ssubaddxal, 678 +ssubaddxlo, 678 +ssubaddxcc, 678 +ssubaddxhs, 678 +ssubaddxcs, 678 +ssubaddxnv, 678 +ssax, 678 +ssaxeq, 678 +ssaxne, 678 +ssaxmi, 678 +ssaxpl, 678 +ssaxvs, 678 +ssaxvc, 678 +ssaxhi, 678 +ssaxls, 678 +ssaxge, 678 +ssaxlt, 678 +ssaxgt, 678 +ssaxle, 678 +ssaxal, 678 +ssaxlo, 678 +ssaxcc, 678 +ssaxhs, 678 +ssaxcs, 678 +ssaxnv, 678 +ssub16, 680 +ssub16eq, 680 +ssub16ne, 680 +ssub16mi, 680 +ssub16pl, 680 +ssub16vs, 680 +ssub16vc, 680 +ssub16hi, 680 +ssub16ls, 680 +ssub16ge, 680 +ssub16lt, 680 +ssub16gt, 680 +ssub16le, 680 +ssub16al, 680 +ssub16lo, 680 +ssub16cc, 680 +ssub16hs, 680 +ssub16cs, 680 +ssub16nv, 680 +ssub8, 682 +ssub8eq, 682 +ssub8ne, 682 +ssub8mi, 682 +ssub8pl, 682 +ssub8vs, 682 +ssub8vc, 682 +ssub8hi, 682 +ssub8ls, 682 +ssub8ge, 682 +ssub8lt, 682 +ssub8gt, 682 +ssub8le, 682 +ssub8al, 682 +ssub8lo, 682 +ssub8cc, 682 +ssub8hs, 682 +ssub8cs, 682 +ssub8nv, 682 +stc, 684 +stceq, 684 +stcne, 684 +stcmi, 684 +stcpl, 684 +stcvs, 684 +stcvc, 684 +stchi, 684 +stcls, 684 +stcge, 684 +stclt, 684 +stcgt, 684 +stcle, 684 +stcal, 684 +stclo, 684 +stccc, 684 +stchs, 684 +stccs, 684 +stcnv, 684 +stcl, 684 +stceql, 684 +stcnel, 684 +stcmil, 684 +stcpll, 684 +stcvsl, 684 +stcvcl, 684 +stchil, 684 +stclsl, 684 +stcgel, 684 +stcltl, 684 +stcgtl, 684 +stclel, 684 +stcall, 684 +stclol, 684 +stcccl, 684 +stchsl, 684 +stccsl, 684 +stcnvl, 684 +stcleq, 684 +stclne, 684 +stclmi, 684 +stclpl, 684 +stclvs, 684 +stclvc, 684 +stclhi, 684 +stclls, 684 +stclge, 684 +stcllt, 684 +stclgt, 684 +stclle, 684 +stclal, 684 +stcllo, 684 +stclcc, 684 +stclhs, 684 +stclcs, 684 +stclnv, 684 +stc2, 684 +stc2eq, 684 +stc2ne, 684 +stc2mi, 684 +stc2pl, 684 +stc2vs, 684 +stc2vc, 684 +stc2hi, 684 +stc2ls, 684 +stc2ge, 684 +stc2lt, 684 +stc2gt, 684 +stc2le, 684 +stc2al, 684 +stc2lo, 684 +stc2cc, 684 +stc2hs, 684 +stc2cs, 684 +stc2nv, 684 +stc2l, 684 +stc2leq, 684 +stc2lne, 684 +stc2lmi, 684 +stc2lpl, 684 +stc2lvs, 684 +stc2lvc, 684 +stc2lhi, 684 +stc2lls, 684 +stc2lge, 684 +stc2llt, 684 +stc2lgt, 684 +stc2lle, 684 +stc2lal, 684 +stc2llo, 684 +stc2lcc, 684 +stc2lhs, 684 +stc2lcs, 684 +stc2lnv, 684 +stm, 686 +stmeq, 686 +stmne, 686 +stmmi, 686 +stmpl, 686 +stmvs, 686 +stmvc, 686 +stmhi, 686 +stmls, 686 +stmge, 686 +stmlt, 686 +stmgt, 686 +stmle, 686 +stmal, 686 +stmlo, 686 +stmcc, 686 +stmhs, 686 +stmcs, 686 +stmnv, 686 +stmia, 686 +stmeqia, 686 +stmneia, 686 +stmmiia, 686 +stmplia, 686 +stmvsia, 686 +stmvcia, 686 +stmhiia, 686 +stmlsia, 686 +stmgeia, 686 +stmltia, 686 +stmgtia, 686 +stmleia, 686 +stmalia, 686 +stmloia, 686 +stmccia, 686 +stmhsia, 686 +stmcsia, 686 +stmnvia, 686 +stmea, 686 +stmeqea, 686 +stmneea, 686 +stmmiea, 686 +stmplea, 686 +stmvsea, 686 +stmvcea, 686 +stmhiea, 686 +stmlsea, 686 +stmgeea, 686 +stmltea, 686 +stmgtea, 686 +stmleea, 686 +stmalea, 686 +stmloea, 686 +stmccea, 686 +stmhsea, 686 +stmcsea, 686 +stmnvea, 686 +stmib, 692 +stmeqib, 692 +stmneib, 692 +stmmiib, 692 +stmplib, 692 +stmvsib, 692 +stmvcib, 692 +stmhiib, 692 +stmlsib, 692 +stmgeib, 692 +stmltib, 692 +stmgtib, 692 +stmleib, 692 +stmalib, 692 +stmloib, 692 +stmccib, 692 +stmhsib, 692 +stmcsib, 692 +stmnvib, 692 +stmibeq,692 +stmibne, 692 +stmibmi, 692 +stmibpl, 692 +stmibvs, 692 +stmibvc, 692 +stmibhi, 692 +stmibls, 692 +stmibge, 692 +stmiblt, 692 +stmibgt, 692 +stmible, 692 +stmibal, 692 +stmiblo, 692 +stmibcc, 692 +stmibhs, 692 +stmibcs, 692 +stmibnv, 692 +stmeqda,692 +stmnefa, 692 +stmmifa, 692 +stmplfa, 692 +stmvsfa, 692 +stmvcfa, 692 +stmhifa, 692 +stmlsfa, 692 +stmgefa, 692 +stmltfa, 692 +stmgtfa, 692 +stmlefa, 692 +stmalfa, 692 +stmlofa, 692 +stmccfa, 692 +stmhsfa, 692 +stmcsfa, 692 +stmnvfa, 692 +stmda, 688 +stmeqda, 688 +stmneda, 688 +stmmida, 688 +stmplda, 688 +stmvsda, 688 +stmvcda, 688 +stmhida, 688 +stmlsda, 688 +stmgeda, 688 +stmltda, 688 +stmgtda, 688 +stmleda, 688 +stmalda, 688 +stmloda, 688 +stmccda, 688 +stmhsda, 688 +stmcsda, 688 +stmnvda, 688 +stmdaeq,688 +stmdane, 688 +stmdami, 688 +stmdapl, 688 +stmdavs, 688 +stmdavc, 688 +stmdahi, 688 +stmdals, 688 +stmdage, 688 +stmdalt, 688 +stmdagt, 688 +stmdale, 688 +stmdaal, 688 +stmdalo, 688 +stmdacc, 688 +stmdahs, 688 +stmdacs, 688 +stmdanv, 688 +stmeqed,688 +stmneed, 688 +stmmied, 688 +stmpled, 688 +stmvsed, 688 +stmvced, 688 +stmhied, 688 +stmlsed, 688 +stmgeed, 688 +stmlted, 688 +stmgted, 688 +stmleed, 688 +stmaled, 688 +stmloed, 688 +stmcced, 688 +stmhsed, 688 +stmcsed, 688 +stmnved, 688 +stmdb, 690 +stmeqdb, 690 +stmnedb, 690 +stmmidb, 690 +stmpldb, 690 +stmvsdb, 690 +stmvcdb, 690 +stmhidb, 690 +stmlsdb, 690 +stmgedb, 690 +stmltdb, 690 +stmgtdb, 690 +stmledb, 690 +stmaldb, 690 +stmlodb, 690 +stmccdb, 690 +stmhsdb, 690 +stmcsdb, 690 +stmnvdb, 690 +stmeqfd,690 +stmnefd, 690 +stmmifd, 690 +stmplfd, 690 +stmvsfd, 690 +stmvcfd, 690 +stmhifd, 690 +stmlsfd, 690 +stmgefd, 690 +stmltfd, 690 +stmgtfd, 690 +stmlefd, 690 +stmalfd, 690 +stmlofd, 690 +stmccfd, 690 +stmhsfd, 690 +stmcsfd, 690 +stmnvfd, 690 +stmdbeq,690 +stmdbne, 690 +stmdbmi, 690 +stmdbpl, 690 +stmdbvs, 690 +stmdbvc, 690 +stmdbhi, 690 +stmdbls, 690 +stmdbge, 690 +stmdblt, 690 +stmdbgt, 690 +stmdble, 690 +stmdbal, 690 +stmdblo, 690 +stmdbcc, 690 +stmdbhs, 690 +stmdbcs, 690 +stmdbnv, 690 +str, 694 +streq, 694 +strne, 694 +strmi, 694 +strpl, 694 +strvs, 694 +strvc, 694 +strhi, 694 +strls, 694 +strge, 694 +strlt, 694 +strgt, 694 +strle, 694 +stral, 694 +strlo, 694 +strcc, 694 +strhs, 694 +strcs, 694 +strnv, 694 +strb, 700 +streqb, 700 +strneb, 700 +strmib, 700 +strplb, 700 +strvsb, 700 +strvcb, 700 +strhib, 700 +strlsb, 700 +strgeb, 700 +strltb, 700 +strgtb, 700 +strleb, 700 +stralb, 700 +strlob, 700 +strccb, 700 +strhsb, 700 +strcsb, 700 +strnvb, 700 +strbeq, 700 +strbne, 700 +strbmi, 700 +strbpl, 700 +strbvs, 700 +strbvc, 700 +strbhi, 700 +strbls, 700 +strbge, 700 +strblt, 700 +strbgt, 700 +strble, 700 +strbal, 700 +strblo, 700 +strbcc, 700 +strbhs, 700 +strbcs, 700 +strbnv, 700 +strbt, 706 +streqbt, 706 +strnebt, 706 +strmibt, 706 +strplbt, 706 +strvsbt, 706 +strvcbt, 706 +strhibt, 706 +strlsbt, 706 +strgebt, 706 +strltbt, 706 +strgtbt, 706 +strlebt, 706 +stralbt, 706 +strlobt, 706 +strccbt, 706 +strhsbt, 706 +strcsbt, 706 +strnvbt, 706 +strbteq 706 +strbtne, 706 +strbtmi, 706 +strbtpl, 706 +strbtvs, 706 +strbtvc, 706 +strbthi, 706 +strbtls, 706 +strbtge, 706 +strbtlt, 706 +strbtgt, 706 +strbtle, 706 +strbtal, 706 +strbtlo, 706 +strbtcc, 706 +strbths, 706 +strbtcs, 706 +strbtnv, 706 +strd, 708 +streqd, 708 +strned, 708 +strmid, 708 +strpld, 708 +strvsd, 708 +strvcd, 708 +strhid, 708 +strlsd, 708 +strged, 708 +strltd, 708 +strgtd, 708 +strled, 708 +strald, 708 +strlod, 708 +strccd, 708 +strhsd, 708 +strcsd, 708 +strnvd, 708 +strdeq, 708 +strdne, 708 +strdmi, 708 +strdpl, 708 +strdvs, 708 +strdvc, 708 +strdhi, 708 +strdls, 708 +strdge, 708 +strdlt, 708 +strdgt, 708 +strdle, 708 +strdal, 708 +strdlo, 708 +strdcc, 708 +strdhs, 708 +strdcs, 708 +strdnv, 708 +strex, 712 +strexeq, 712 +strexne, 712 +strexmi, 712 +strexpl, 712 +strexvs, 712 +strexvc, 712 +strexhi, 712 +strexls, 712 +strexge, 712 +strexlt, 712 +strexgt, 712 +strexle, 712 +strexal, 712 +strexlo, 712 +strexcc, 712 +strexhs, 712 +strexcs, 712 +strexnv, 712 +strexb, 714 +strexbeq, 714 +strexbne, 714 +strexbmi, 714 +strexbpl, 714 +strexbvs, 714 +strexbvc, 714 +strexbhi, 714 +strexbls, 714 +strexbge, 714 +strexblt, 714 +strexbgt, 714 +strexble, 714 +strexbal, 714 +strexblo, 714 +strexbcc, 714 +strexbhs, 714 +strexbcs, 714 +strexbnv, 714 +strexd, 716 +strexdeq, 716 +strexdne, 716 +strexdmi, 716 +strexdpl, 716 +strexdvs, 716 +strexdvc, 716 +strexdhi, 716 +strexdls, 716 +strexdge, 716 +strexdlt, 716 +strexdgt, 716 +strexdle, 716 +strexdal, 716 +strexdlo, 716 +strexdcc, 716 +strexdhs, 716 +strexdcs, 716 +strexdnv, 716 +strexh, 718 +strexheq, 718 +strexhne, 718 +strexhmi, 718 +strexhpl, 718 +strexhvs, 718 +strexhvc, 718 +strexhhi, 718 +strexhls, 718 +strexhge, 718 +strexhlt, 718 +strexhgt, 718 +strexhle, 718 +strexhal, 718 +strexhlo, 718 +strexhcc, 718 +strexhhs, 718 +strexhcs, 718 +strexhnv, 718 +strh, 720 +streqh, 720 +strneh, 720 +strmih, 720 +strplh, 720 +strvsh, 720 +strvch, 720 +strhih, 720 +strlsh, 720 +strgeh, 720 +strlth, 720 +strgth, 720 +strleh, 720 +stralh, 720 +strloh, 720 +strcch, 720 +strhsh, 720 +strcsh, 720 +strnvh, 720 +strheq, 720 +strhne, 720 +strhmi, 720 +strhpl, 720 +strhvs, 720 +strhvc, 720 +strhhi, 720 +strhls, 720 +strhge, 720 +strhlt, 720 +strhgt, 720 +strhle, 720 +strhal, 720 +strhlo, 720 +strhcc, 720 +strhhs, 720 +strhcs, 720 +strhnv, 720 +strht, 726 +strhteq, 726 +strhtne, 726 +strhtmi, 726 +strhtpl, 726 +strhtvs, 726 +strhtvc, 726 +strhthi, 726 +strhtls, 726 +strhtge, 726 +strhlt, 726 +strhtgt, 726 +strhtle, 726 +strhtal, 726 +strhtlo, 726 +strhtcc, 726 +strhths, 726 +strhtcs, 726 +strhtnv, 726 +strt, 728 +streqt, 728 +strnet, 728 +strmit, 728 +strplt, 728 +strvst, 728 +strvct, 728 +strhit, 728 +strlst, 728 +strget, 728 +strltt, 728 +strgtt, 728 +strlet, 728 +stralt, 728 +strlot, 728 +strcct, 728 +strhst, 728 +strcst, 728 +strnvt, 728 +strteq, 728 +strtne, 728 +strtmi, 728 +strtpl, 728 +strtvs, 728 +strtvc, 728 +strthi, 728 +strtls, 728 +strtge, 728 +strtlt, 728 +strtgt, 728 +strtle, 728 +strtal, 728 +strtlo, 728 +strtcc, 728 +strths, 728 +strtcs, 728 +strtnv, 728 +sub, 730 +subeq, 730 +subne, 730 +submi, 730 +subpl, 730 +subvs, 730 +subvc, 730 +subhi, 730 +subls, 730 +subge, 730 +sublt, 730 +subgt, 730 +suble, 730 +subal, 730 +sublo, 730 +subcc, 730 +subhs, 730 +subcs, 730 +subnv, 730 +subs, 730 +subeqs, 730 +subnes, 730 +submis, 730 +subpls, 730 +subvss, 730 +subvcs, 730 +subhis, 730 +sublss, 730 +subges, 730 +sublts, 730 +subgts, 730 +subles, 730 +subals, 730 +sublos, 730 +subccs, 730 +subhss, 730 +subcss, 730 +subnvs, 730 +subseq, 730 +subsne, 730 +subsmi, 730 +subspl, 730 +subsvs, 730 +subsvc, 730 +subshi, 730 +subsls, 730 +subsge, 730 +subslt, 730 +subsgt, 730 +subsle, 730 +subsal, 730 +subslo, 730 +subscc, 730 +subshs, 730 +subscs, 730 +subsnv, 730 +svc, 742 +svceq, 742 +svcne, 742 +svcmi, 742 +svcpl, 742 +svcvs, 742 +svcvc, 742 +svchi, 742 +svcls, 742 +svcge, 742 +svclt, 742 +svcgt, 742 +svcle, 742 +svcal, 742 +svclo, 742 +svccc, 742 +svchs, 742 +svccs, 742 +svcnv, 742 +swi, 742 +swieq, 742 +swine, 742 +swimi, 742 +swipl, 742 +swivs, 742 +swivc, 742 +swihi, 742 +swils, 742 +swige, 742 +swilt, 742 +swigt, 742 +swile, 742 +swial, 742 +swilo, 742 +swicc, 742 +swihs, 742 +swics, 742 +swinv, 742 +swp, 744 +swpeq, 744 +swpne, 744 +swpmi, 744 +swppl, 744 +swpvs, 744 +swpvc, 744 +swphi, 744 +swpls, 744 +swpge, 744 +swplt, 744 +swpgt, 744 +swple, 744 +swpal, 744 +swplo, 744 +swpcc, 744 +swphs, 744 +swpcs, 744 +swpnv, 744 +swpb, 744 +swpeqb, 744 +swpneb, 744 +swpmib, 744 +swpplb, 744 +swpvsb, 744 +swpvcb, 744 +swphib, 744 +swplsb, 744 +swpgeb, 744 +swpltb, 744 +swpgtb, 744 +swpleb, 744 +swpalb, 744 +swplob, 744 +swpccb, 744 +swphsb, 744 +swpcsb, 744 +swpnvb, 744 +sxtab, 746 +sxtabeq, 746 +sxtabne, 746 +sxtabmi, 746 +sxtabpl, 746 +sxtabvs, 746 +sxtabvc, 746 +sxtabhi, 746 +sxtabls, 746 +sxtabge, 746 +sxtablt, 746 +sxtabgt, 746 +sxtable, 746 +sxtabal, 746 +sxtablo, 746 +sxtabcc, 746 +sxtabhs, 746 +sxtabcs, 746 +sxtabnv, 746 +sxtab16, 748 +sxtab16eq, 748 +sxtab16ne, 748 +sxtab16mi, 748 +sxtab16pl, 748 +sxtab16vs, 748 +sxtab16vc, 748 +sxtab16hi, 748 +sxtab16ls, 748 +sxtab16ge, 748 +sxtab16lt, 748 +sxtab16gt, 748 +sxtab16le, 748 +sxtab6al, 748 +sxtab6lo, 748 +sxtab16cc, 748 +sxtab16hs, 748 +sxtab16cs, 748 +sxtab16nv, 748 +sxtah, 750 +sxtaheq, 750 +sxtahne, 750 +sxtahmi, 750 +sxtahpl, 750 +sxtahvs, 750 +sxtahvc, 750 +sxtahhi, 750 +sxtahls, 750 +sxtahge, 750 +sxtahlt, 750 +sxtahgt, 750 +sxtahle, 750 +sxtahal, 750 +sxtahlo, 750 +sxtahcc, 750 +sxtahhs, 750 +sxtahcs, 750 +sxtahnv, 750 +sxtb, 752 +sxtbeq, 752 +sxtbne, 752 +sxtbmi, 752 +sxtbpl, 752 +sxtbvs, 752 +sxtbvc, 752 +sxtbhi, 752 +sxtbls, 752 +sxtbge, 752 +sxtblt, 752 +sxtbgt, 752 +sxtble, 752 +sxtbal, 752 +sxtblo, 752 +sxtbcc, 752 +sxtbhs, 752 +sxtbcs, 752 +sxtbnv, 752 +sxtb16, 754 +sxtb16eq, 754 +sxtb16ne, 754 +sxtb16mi, 754 +sxtb16pl, 754 +sxtb16vs, 754 +sxtb16vc, 754 +sxtb16hi, 754 +sxtb16ls, 754 +sxtb16ge, 754 +sxtb16lt, 754 +sxtb16gt, 754 +sxtb16le, 754 +sxtb16al, 754 +sxtb16lo, 754 +sxtb16cc, 754 +sxtb16hs, 754 +sxtb16cs, 754 +sxtb16nv, 754 +sxth, 756 +sxtheq, 756 +sxthne, 756 +sxthmi, 756 +sxthpl, 756 +sxthvs, 756 +sxthvc, 756 +sxthhi, 756 +sxthls, 756 +sxthge, 756 +sxthlt, 756 +sxthgt, 756 +sxthle, 756 +sxthal, 756 +sxthlo, 756 +sxthcc, 756 +sxthhs, 756 +sxthcs, 756 +sxthnv, 756 +tbb, 758 +tbbeq, 758 +tbbne, 758 +tbbmi, 758 +tbbpl, 758 +tbbvs, 758 +tbbvc, 758 +tbbhi, 758 +tbbls, 758 +tbbge, 758 +tbblt, 758 +tbbgt, 758 +tbble, 758 +tbbal, 758 +tbblo, 758 +tbbcc, 758 +tbbhs, 758 +tbbcs, 758 +tbbnv, 758 +tbh, 758 +tbheq, 758 +tbhne, 758 +tbhmi, 758 +tbhpl, 758 +tbhvs, 758 +tbhvc, 758 +tbhhi, 758 +tbhls, 758 +tbhge, 758 +tbhlt, 758 +tbhgt, 758 +tbhle, 758 +tbhal, 758 +tbhlo, 758 +tbhcc, 758 +tbhhs, 758 +tbhcs, 758 +tbhnv, 758 +teq, 760 +teqeq, 760 +teqne, 760 +teqmi, 760 +teqpl, 760 +teqvs, 760 +teqvc, 760 +teqhi, 760 +teqls, 760 +teqge, 760 +teqlt, 760 +teqgt, 760 +teqle, 760 +teqal, 760 +teqlo, 760 +teqcc, 760 +teqhs, 760 +teqcs, 760 +teqnv, 760 +tst, 766 +tsteq, 766 +tstne, 766 +tstmi, 766 +tstpl, 766 +tstvs, 766 +tstvc, 766 +tsthi, 766 +tstls, 766 +tstge, 766 +tstlt, 766 +tstgt, 766 +tstle, 766 +tstal, 766 +tstlo, 766 +tstcc, 766 +tsths, 766 +tstcs, 766 +tstnv, 766 +uadd16, 772 +uadd16eq, 772 +uadd16ne, 772 +uadd16mi, 772 +uadd16pl, 772 +uadd16vs, 772 +uadd16vc, 772 +uadd16hi, 772 +uadd16ls, 772 +uadd16ge, 772 +uadd16lt, 772 +uadd16gt, 772 +uadd16le, 772 +uadd16al, 772 +uadd16lo, 772 +uadd16cc, 772 +uadd16hs, 772 +uadd16cs, 772 +uadd16nv, 772 +uadd8, 774 +uadd8eq, 774 +uadd8ne, 774 +uadd8mi, 774 +uadd8pl, 774 +uadd8vs, 774 +uadd8vc, 774 +uadd8hi, 774 +uadd8ls, 774 +uadd8ge, 774 +uadd8lt, 774 +uadd8gt, 774 +uadd8le, 774 +uadd8al, 774 +uadd8lo, 774 +uadd8cc, 774 +uadd8hs, 774 +uadd8cs, 774 +uadd8nv, 774 +uaddsubx, 776 +uaddsubxeq, 776 +uaddsubxne, 776 +uaddsubxmi, 776 +uaddsubxpl, 776 +uaddsubxvs, 776 +uaddsubxvc, 776 +uaddsubxhi, 776 +uaddsubxls, 776 +uaddsubxge, 776 +uaddsubxlt, 776 +uaddsubxgt, 776 +uaddsubxle, 776 +uaddsubxal, 776 +uaddsubxlo, 776 +uaddsubxcc, 776 +uaddsubxhs, 776 +uaddsubxcs, 776 +uaddsubxnv, 776 +uasx, 776 +uasxeq, 776 +uasxne, 776 +uasxmi, 776 +uasxpl, 776 +uasxvs, 776 +uasxvc, 776 +uasxhi, 776 +uasxls, 776 +uasxge, 776 +uasxlt, 776 +uasxgt, 776 +uasxle, 776 +uasxal, 776 +uasxlo, 776 +uasxcc, 776 +uasxhs, 776 +uasxcs, 776 +uasxnv, 776 +ubfx, 778 +ubfxeq, 778 +ubfxne, 778 +ubfxmi, 778 +ubfxpl, 778 +ubfxvs, 778 +ubfxvc, 778 +ubfxhi, 778 +ubfxls, 778 +ubfxge, 778 +ubfxlt, 778 +ubfxgt, 778 +ubfxle, 778 +ubfxal, 778 +ubfxlo, 778 +ubfxcc, 778 +ubfxhs, 778 +ubfxcs, 778 +ubfxnv, 778 +udiv, 780 +udiveq, 780 +udivne, 780 +udivmi, 780 +udivpl, 780 +udivvs, 780 +udivvc, 780 +udivhi, 780 +udivls, 780 +udivge, 780 +udivlt, 780 +udivgt, 780 +udivle, 780 +udival, 780 +udivlo, 780 +udivcc, 780 +udivhs, 780 +udivcs, 780 +udivnv, 780 +uhadd16, 782 +uhadd16eq, 782 +uhadd16ne, 782 +uhadd16mi, 782 +uhadd16pl, 782 +uhadd16vs, 782 +uhadd16vc, 782 +uhadd16hi, 782 +uhadd16ls, 782 +uhadd16ge, 782 +uhadd16lt, 782 +uhadd16gt, 782 +uhadd16le, 782 +uhadd16al, 782 +uhadd16lo, 782 +uhadd16cc, 782 +uhadd16hs, 782 +uhadd16cs, 782 +uhadd16nv, 782 +uhadd8, 784 +uhadd8eq, 784 +uhadd8ne, 784 +uhadd8mi, 784 +uhadd8pl, 784 +uhadd8vs, 784 +uhadd8vc, 784 +uhadd8hi, 784 +uhadd8ls, 784 +uhadd8ge, 784 +uhadd8lt, 784 +uhadd8gt, 784 +uhadd8le, 784 +uhadd8al, 784 +uhadd8lo, 784 +uhadd8cc, 784 +uhadd8hs, 784 +uhadd8cs, 784 +uhadd8nv, 784 +uhaddsubx, 786 +uhaddsubxeq, 786 +uhaddsubxne, 786 +uhaddsubxmi, 786 +uhaddsubxpl, 786 +uhaddsubxvs, 786 +uhaddsubxvc, 786 +uhaddsubxhi, 786 +uhaddsubxls, 786 +uhaddsubxge, 786 +uhaddsubxlt, 786 +uhaddsubxgt, 786 +uhaddsubxle, 786 +uhaddsubxal, 786 +uhaddsubxlo, 786 +uhaddsubxcc, 786 +uhaddsubxhs, 786 +uhaddsubxcs, 786 +uhaddsubxnv, 786 +uhasx, 786 +uhasxeq, 786 +uhasxne, 786 +uhasxmi, 786 +uhasxpl, 786 +uhasxvs, 786 +uhasxvc, 786 +uhasxhi, 786 +uhasxls, 786 +uhasxge, 786 +uhasxlt, 786 +uhasxgt, 786 +uhasxle, 786 +uhasxal, 786 +uhasxlo, 786 +uhasxcc, 786 +uhasxhs, 786 +uhasxcs, 786 +uhasxnv, 786 +uhsubaddx,788 +uhsubaddxeq, 788 +uhsubaddxne, 788 +uhsubaddxmi, 788 +uhsubaddxpl, 788 +uhsubaddxvs, 788 +uhsubaddxvc, 788 +uhsubaddxhi, 788 +uhsubaddxls, 788 +uhsubaddxge, 788 +uhsubaddxlt, 788 +uhsubaddxgt, 788 +uhsubaddxle, 788 +uhsubaddxal, 788 +uhsubaddxlo, 788 +uhsubaddxcc, 788 +uhsubaddxhs, 788 +uhsubaddxcs, 788 +uhsubaddxnv, 788 +uhsax, 788 +uhsaxeq, 788 +uhsaxne, 788 +uhsaxmi, 788 +uhsaxpl, 788 +uhsaxvs, 788 +uhsaxvc, 788 +uhsaxhi, 788 +uhsaxls, 788 +uhsaxge, 788 +uhsaxlt, 788 +uhsaxgt, 788 +uhsaxle, 788 +uhsaxal, 788 +uhsaxlo, 788 +uhsaxcc, 788 +uhsaxhs, 788 +uhsaxcs, 788 +uhsaxnv, 788 +uhsub16, 790 +uhsub16eq, 790 +uhsub16ne, 790 +uhsub16mi, 790 +uhsub16pl, 790 +uhsub16vs, 790 +uhsub16vc, 790 +uhsub16hi, 790 +uhsub16ls, 790 +uhsub16ge, 790 +uhsub16lt, 790 +uhsub16gt, 790 +uhsub16le, 790 +uhsub16al, 790 +uhsub16lo, 790 +uhsub16cc, 790 +uhsub16hs, 790 +uhsub16cs, 790 +uhsub16nv, 790 +uhsub8, 792 +uhsub8eq, 792 +uhsub8ne, 792 +uhsub8mi, 792 +uhsub8pl, 792 +uhsub8vs, 792 +uhsub8vc, 792 +uhsub8hi, 792 +uhsub8ls, 792 +uhsub8ge, 792 +uhsub8lt, 792 +uhsub8gt, 792 +uhsub8le, 792 +uhsub8al, 792 +uhsub8lo, 792 +uhsub8cc, 792 +uhsub8hs, 792 +uhsub8cs, 792 +uhsub8nv, 792 +umaal, 794 +umaaleq, 794 +umaalne, 794 +umaalmi, 794 +umaalpl, 794 +umaalvs, 794 +umaalvc, 794 +umaalhi, 794 +umaalls, 794 +umaalge, 794 +umaallt, 794 +umaalgt, 794 +umaalle, 794 +umaalal, 794 +umaallo, 794 +umaalcc, 794 +umaalhs, 794 +umaalcs, 794 +umaalnv, 794 +umlal, 796 +umlaleq, 796 +umlalne, 796 +umlalmi, 796 +umlalpl, 796 +umlalvs, 796 +umlalvc, 796 +umlalhi, 796 +umlalls, 796 +umlalge, 796 +umlallt, 796 +umlalgt, 796 +umlalle, 796 +umlalal, 796 +umlallo, 796 +umlalcc, 796 +umlalhs, 796 +umlalcs, 796 +umlalnv, 796 +umlals, 796 +umlaleqs, 796 +umlalnes, 796 +umlalmis, 796 +umlalpls, 796 +umlalvss, 796 +umlalvcs, 796 +umlalhis, 796 +umlallss, 796 +umlalges, 796 +umlallts, 796 +umlalgts, 796 +umlalles, 796 +umlalals, 796 +umlallos, 796 +umlalccs, 796 +umlalhss, 796 +umlalcss, 796 +umlalnvs, 796 +umlals, 796 +umlalseq, 796 +umlalsne, 796 +umlalsmi, 796 +umlalspl, 796 +umlalsvs, 796 +umlalsvc, 796 +umlalshi, 796 +umlalsls, 796 +umlalsge, 796 +umlalslt, 796 +umlalsgt, 796 +umlalsle, 796 +umlalsal, 796 +umlalslo, 796 +umlalscc, 796 +umlalshs, 796 +umlalscs, 796 +umlalsnv, 796 +umull, 798 +umulleq, 798 +umullne, 798 +umullmi, 798 +umullpl, 798 +umullvs, 798 +umullvc, 798 +umullhi, 798 +umullls, 798 +umullge, 798 +umulllt, 798 +umullgt, 798 +umullle, 798 +umullal, 798 +umulllo, 798 +umullcc, 798 +umullhs, 798 +umullcs, 798 +umullnv, 798 +umulls, 798 +umulleqs, 798 +umullnes, 798 +umullmis, 798 +umullpls, 798 +umullvss, 798 +umullvcs, 798 +umullhis, 798 +umulllss, 798 +umullges, 798 +umulllts, 798 +umullgts, 798 +umullles, 798 +umullals, 798 +umulllos, 798 +umullccs, 798 +umullhss, 798 +umullcss, 798 +umullnvs, 798 +umulls, 798 +umullseq, 798 +umullsne, 798 +umullsmi, 798 +umullspl, 798 +umullsvs, 798 +umullsvc, 798 +umullshi, 798 +umullsls, 798 +umullsge, 798 +umullslt, 798 +umullsgt, 798 +umullsle, 798 +umullsal, 798 +umullslo, 798 +umullscc, 798 +umullshs, 798 +umullscs, 798 +umullsnv, 798 +uqadd16, 800 +uqadd16eq, 800 +uqadd16ne, 800 +uqadd16mi, 800 +uqadd16pl, 800 +uqadd16vs, 800 +uqadd16vc, 800 +uqadd16hi, 800 +uqadd16ls, 800 +uqadd16ge, 800 +uqadd16lt, 800 +uqadd16gt, 800 +uqadd16le, 800 +uqadd16al, 800 +uqadd16lo, 800 +uqadd16cc, 800 +uqadd16hs, 800 +uqadd16cs, 800 +uqadd16nv, 800 +uqadd8, 802 +uqadd8eq, 802 +uqadd8ne, 802 +uqadd8mi, 802 +uqadd8pl, 802 +uqadd8vs, 802 +uqadd8vc, 802 +uqadd8hi, 802 +uqadd8ls, 802 +uqadd8ge, 802 +uqadd8lt, 802 +uqadd8gt, 802 +uqadd8le, 802 +uqadd8al, 802 +uqadd8lo, 802 +uqadd8cc, 802 +uqadd8hs, 802 +uqadd8cs, 802 +uqadd8nv, 802 +uqaddsubx, 804 +uqaddsubxeq, 804 +uqaddsubxne, 804 +uqaddsubxmi, 804 +uqaddsubxpl, 804 +uqaddsubxvs, 804 +uqaddsubxvc, 804 +uqaddsubxhi, 804 +uqaddsubxls, 804 +uqaddsubxge, 804 +uqaddsubxlt, 804 +uqaddsubxgt, 804 +uqaddsubxle, 804 +uqaddsubxal, 804 +uqaddsubxlo, 804 +uqaddsubxcc, 804 +uqaddsubxhs, 804 +uqaddsubxcs, 804 +uqaddsubxnv, 804 +uqasx, 804 +uqasxeq, 804 +uqasxne, 804 +uqasxmi, 804 +uqasxpl, 804 +uqasxvs, 804 +uqasxvc, 804 +uqasxhi, 804 +uqasxls, 804 +uqasxge, 804 +uqasxlt, 804 +uqasxgt, 804 +uqasxle, 804 +uqasxal, 804 +uqasxlo, 804 +uqasxcc, 804 +uqasxhs, 804 +uqasxcs, 804 +uqasxnv, 804 +uqsubaddx, 806 +uqsubaddxeq, 806 +uqsubaddxne, 806 +uqsubaddxmi, 806 +uqsubaddxpl, 806 +uqsubaddxvs, 806 +uqsubaddxvc, 806 +uqsubaddxhi, 806 +uqsubaddxls, 806 +uqsubaddxge, 806 +uqsubaddxlt, 806 +uqsubaddxgt, 806 +uqsubaddxle, 806 +uqsubaddxal, 806 +uqsubaddxlo, 806 +uqsubaddxcc, 806 +uqsubaddxhs, 806 +uqsubaddxcs, 806 +uqsubaddxnv, 806 +uqsax, 806 +uqsaxeq, 806 +uqsaxne, 806 +uqsaxmi, 806 +uqsaxpl, 806 +uqsaxvs, 806 +uqsaxvc, 806 +uqsaxhi, 806 +uqsaxls, 806 +uqsaxge, 806 +uqsaxlt, 806 +uqsaxgt, 806 +uqsaxle, 806 +uqsaxal, 806 +uqsaxlo, 806 +uqsaxcc, 806 +uqsaxhs, 806 +uqsaxcs, 806 +uqsaxnv, 806 +uqsub16, 808 +uqsub16eq, 808 +uqsub16ne, 808 +uqsub16mi, 808 +uqsub16pl, 808 +uqsub16vs, 808 +uqsub16vc, 808 +uqsub16hi, 808 +uqsub16ls, 808 +uqsub16ge, 808 +uqsub16lt, 808 +uqsub16gt, 808 +uqsub16le, 808 +uqsub16al, 808 +uqsub16lo, 808 +uqsub16cc, 808 +uqsub16hs, 808 +uqsub16cs, 808 +uqsub16nv, 808 +uqsub8, 810 +uqsub8eq, 810 +uqsub8ne, 810 +uqsub8mi, 810 +uqsub8pl, 810 +uqsub8vs, 810 +uqsub8vc, 810 +uqsub8hi, 810 +uqsub8ls, 810 +uqsub8ge, 810 +uqsub8lt, 810 +uqsub8gt, 810 +uqsub8le, 810 +uqsub8al, 810 +uqsub8lo, 810 +uqsub8cc, 810 +uqsub8hs, 810 +uqsub8cs, 810 +uqsub8nv, 810 +usad8, 812 +usad8eq, 812 +usad8ne, 812 +usad8mi, 812 +usad8pl, 812 +usad8vs, 812 +usad8vc, 812 +usad8hi, 812 +usad8ls, 812 +usad8ge, 812 +usad8lt, 812 +usad8gt, 812 +usad8le, 812 +usad8al, 812 +usad8lo, 812 +usad8cc, 812 +usad8hs, 812 +usad8cs, 812 +usad8nv, 812 +usada8, 814 +usada8eq, 814 +usada8ne, 814 +usada8mi, 814 +usada8pl, 814 +usada8vs, 814 +usada8vc, 814 +usada8hi, 814 +usada8ls, 814 +usada8ge, 814 +usada8lt, 814 +usada8gt, 814 +usada8le, 814 +usada8al, 814 +usada8lo, 814 +usada8cc, 814 +usada8hs, 814 +usada8cs, 814 +usada8nv, 814 +usat, 816 +usateq, 816 +usatne, 816 +usatmi, 816 +usatpl, 816 +usatvs, 816 +usatvc, 816 +usathi, 816 +usatls, 816 +usatge, 816 +usatlt, 816 +usatgt, 816 +usatle, 816 +usatal, 816 +usatlo, 816 +usatcc, 816 +usaths, 816 +usatcs, 816 +usatnv, 816 +usat16, 818 +usat16eq, 818 +usat16ne, 818 +usat16mi, 818 +usat16pl, 818 +usat16vs, 818 +usat16vc, 818 +usat16hi, 818 +usat16ls, 818 +usat16ge, 818 +usat16lt, 818 +usat16gt, 818 +usat16le, 818 +usat16al, 818 +usat16lo, 818 +usat16cc, 818 +usat16hs, 818 +usat16cs, 818 +usat16nv, 818 +usubaddx, 820 +usubaddxeq, 820 +usubaddxne, 820 +usubaddxmi, 820 +usubaddxpl, 820 +usubaddxvs, 820 +usubaddxvc, 820 +usubaddxhi, 820 +usubaddxls, 820 +usubaddxge, 820 +usubaddxlt, 820 +usubaddxgt, 820 +usubaddxle, 820 +usubaddxal, 820 +usubaddxlo, 820 +usubaddxcc, 820 +usubaddxhs, 820 +usubaddxcs, 820 +usubaddxnv, 820 +usax, 820 +usaxeq, 820 +usaxne, 820 +usaxmi, 820 +usaxpl, 820 +usaxvs, 820 +usaxvc, 820 +usaxhi, 820 +usaxls, 820 +usaxge, 820 +usaxlt, 820 +usaxgt, 820 +usaxle, 820 +usaxal, 820 +usaxlo, 820 +usaxcc, 820 +usaxhs, 820 +usaxcs, 820 +usaxnv, 820 +usub16, 822 +usub16eq, 822 +usub16ne, 822 +usub16mi, 822 +usub16pl, 822 +usub16vs, 822 +usub16vc, 822 +usub16hi, 822 +usub16ls, 822 +usub16ge, 822 +usub16lt, 822 +usub16gt, 822 +usub16le, 822 +usub16al, 822 +usub16lo, 822 +usub16cc, 822 +usub16hs, 822 +usub16cs, 822 +usub16nv, 822 +usub8, 824 +usub8eq, 824 +usub8ne, 824 +usub8mi, 824 +usub8pl, 824 +usub8vs, 824 +usub8vc, 824 +usub8hi, 824 +usub8ls, 824 +usub8ge, 824 +usub8lt, 824 +usub8gt, 824 +usub8le, 824 +usub8al, 824 +usub8lo, 824 +usub8cc, 824 +usub8hs, 824 +usub8cs, 824 +usub8nv, 824 +uxtab, 826 +uxtabeq, 826 +uxtabne, 826 +uxtabmi, 826 +uxtabpl, 826 +uxtabvs, 826 +uxtabvc, 826 +uxtabhi, 826 +uxtabls, 826 +uxtabge, 826 +uxtablt, 826 +uxtabgt, 826 +uxtable, 826 +uxtabal, 826 +uxtablo, 826 +uxtabcc, 826 +uxtabhs, 826 +uxtabcs, 826 +uxtabnv, 826 +uxtab16, 828 +uxtab16eq, 828 +uxtab16ne, 828 +uxtab16mi, 828 +uxtab16pl, 828 +uxtab16vs, 828 +uxtab16vc, 828 +uxtab16hi, 828 +uxtab16ls, 828 +uxtab16ge, 828 +uxtab16lt, 828 +uxtab16gt, 828 +uxtab16le, 828 +uxtab16al, 828 +uxtab16lo, 828 +uxtab16cc, 828 +uxtab16hs, 828 +uxtab16cs, 828 +uxtab16nv, 828 +uxtah, 830 +uxtaheq, 830 +uxtahne, 830 +uxtahmi, 830 +uxtahpl, 830 +uxtahvs, 830 +uxtahvc, 830 +uxtahhi, 830 +uxtahls, 830 +uxtahge, 830 +uxtahlt, 830 +uxtahgt, 830 +uxtahle, 830 +uxtahal, 830 +uxtahlo, 830 +uxtahcc, 830 +uxtahhs, 830 +uxtahcs, 830 +uxtahnv, 830 +uxtb, 832 +uxtbeq, 832 +uxtbne, 832 +uxtbmi, 832 +uxtbpl, 832 +uxtbvs, 832 +uxtbvc, 832 +uxtbhi, 832 +uxtbls, 832 +uxtbge, 832 +uxtblt, 832 +uxtbgt, 832 +uxtble, 832 +uxtbal, 832 +uxtblo, 832 +uxtbcc, 832 +uxtbhs, 832 +uxtbcs, 832 +uxtbnv, 832 +uxtb16, 834 +uxtb16eq, 834 +uxtb16ne, 834 +uxtb16mi, 834 +uxtb16pl, 834 +uxtb16vs, 834 +uxtb16vc, 834 +uxtb16hi, 834 +uxtb16ls, 834 +uxtb16ge, 834 +uxtb16lt, 834 +uxtb16gt, 834 +uxtb16le, 834 +uxtb16al, 834 +uxtb16lo, 834 +uxtb16cc, 834 +uxtb16hs, 834 +uxtb16cs, 834 +uxtb16nv, 834 +uxth, 836 +uxtheq, 836 +uxthne, 836 +uxthmi, 836 +uxthpl, 836 +uxthvs, 836 +uxthvc, 836 +uxthhi, 836 +uxthls, 836 +uxthge, 836 +uxthlt, 836 +uxthgt, 836 +uxthle, 836 +uxthal, 836 +uxthlo, 836 +uxthcc, 836 +uxthhs, 836 +uxthcs, 836 +uxthnv, 836 +vaba, 838 +vabal, 838 +vabd, 840 +vabdl, 840 +vabs, 844 +vacge, 846 +vacgt, 846 +vacle, 846 +vaclt, 846 +vadd, 848 +vaddhn, 852 +vaddl, 854 +vaddw, 854 +vand, 856 +vbic, 858 +vbif, 862 +vbit, 862 +vbsl, 862 +vceq, 864 +vcge, 868 +vcgt, 872 +vcle, 876 +vcls, 878 +vclt, 880 +vclz, 882 +vcmp, 884 +vcmpeq, 884 +vcmpne, 884 +vcmpmi, 884 +vcmppl, 884 +vcmpvs, 884 +vcmpvc, 884 +vcmphi, 884 +vcmpls, 884 +vcmpge, 884 +vcmplt, 884 +vcmpgt, 884 +vcmple, 884 +vcmpal, 884 +vcmplo, 884 +vcmpcc, 884 +vcmphs, 884 +vcmpcs, 884 +vcmpnv, 884 +vcmpe, 884 +vcmpeeq, 884 +vcmpene, 884 +vcmpemi, 884 +vcmpepl, 884 +vcmpevs, 884 +vcmpevc, 884 +vcmpehi, 884 +vcmpels, 884 +vcmpege, 884 +vcmpelt, 884 +vcmpegt, 884 +vcmpele, 884 +vcmpeal, 884 +vcmpelo, 884 +vcmpecc, 884 +vcmpehs, 884 +vcmpecs, 884 +vcmpenv, 884 +vcnt, 886 +vcvt, 888 +vcvteq, 888 +vcvtne, 888 +vcvtmi, 888 +vcvtpl, 888 +vcvtvs, 888 +vcvtvc, 888 +vcvthi, 888 +vcvtls, 888 +vcvtge, 888 +vcvtlt, 888 +vcvtgt, 888 +vcvtle, 888 +vcvtal, 888 +vcvtlo, 888 +vcvtcc, 888 +vcvths, 888 +vcvtcs, 888 +vcvtnv, 888 +vcvtr, 890 +vcvtreq, 890 +vcvtrne, 890 +vcvtrmi, 890 +vcvtrpl, 890 +vcvtrvs, 890 +vcvtrvc, 890 +vcvtrhi, 890 +vcvtrls, 890 +vcvtrge, 890 +vcvtrlt, 890 +vcvtrgt, 890 +vcvtrle, 890 +vcvtral, 890 +vcvtrlo, 890 +vcvtrcc, 890 +vcvtrhs, 890 +vcvtrcs, 890 +vcvtrnv, 890 +vcvtb, 900 +vcvtbeq, 900 +vcvtbne, 900 +vcvtbmi, 900 +vcvtbpl, 900 +vcvtbvs, 900 +vcvtbvc, 900 +vcvtbhi, 900 +vcvtbls, 900 +vcvtbge, 900 +vcvtblt, 900 +vcvtbgt, 900 +vcvtble, 900 +vcvtbal, 900 +vcvtblo, 900 +vcvtbcc, 900 +vcvtbhs, 900 +vcvtbcs, 900 +vcvtbnv, 900 +vcvtt, 900 +vcvtteq, 900 +vcvttne, 900 +vcvttmi, 900 +vcvttpl, 900 +vcvttvs, 900 +vcvttvc, 900 +vcvtthi, 900 +vcvttls, 900 +vcvttge, 900 +vcvttlt, 900 +vcvttgt, 900 +vcvttle, 900 +vcvttal, 900 +vcvttlo, 900 +vcvttcc, 900 +vcvtths, 900 +vcvttcs, 900 +vcvttnv, 900 +vdiv, 902 +vdiveq, 902 +vdivne, 902 +vdivmi, 902 +vdivpl, 902 +vdivvs, 902 +vdivvc, 902 +vdivhi, 902 +vdivls, 902 +vdivge, 902 +vdivlt, 902 +vdivgt, 902 +vdivle, 902 +vdival, 902 +vdivlo, 902 +vdivcc, 902 +vdivhs, 902 +vdivcs, 902 +vdivnv, 902 +vdup, 904 +veor, 908 +vext, 910 +vhadd, 912 +vhsub, 912 +vld1, 914 +vld2, 920 +vld3, 926 +vld4, 932 +vldmia, 938 +vldmiaeq, 938 +vldmiane, 938 +vldmiami, 938 +vldmiapl, 938 +vldmiavs, 938 +vldmiavc, 938 +vldmiahi, 938 +vldmials, 938 +vldmiage, 938 +vldmialt, 938 +vldmiagt, 938 +vldmiale, 938 +vldmiaal, 938 +vldmialo, 938 +vldmiacc, 938 +vldmiahs, 938 +vldmiacs, 938 +vldmianv, 938 +vldmdb, 938 +vldmdbeq, 938 +vldmdbne, 938 +vldmdbmi, 938 +vldmdbpl, 938 +vldmdbvs, 938 +vldmdbvc, 938 +vldmdbhi, 938 +vldmdbls, 938 +vldmdbge, 938 +vldmdblt, 938 +vldmdbgt, 938 +vldmdble, 938 +vldmdbal, 938 +vldmdblo, 938 +vldmdbcc, 939 +vldmdbhs, 939 +vldmdbcs, 939 +vldmdbnv, 939 +vldr, 940 +vldreq, 940 +vldrne, 940 +vldrmi, 940 +vldrpl, 940 +vldrvs, 940 +vldrvc, 940 +vldrhi, 940 +vldrls, 940 +vldrge, 940 +vldrlt, 940 +vldrgt, 940 +vldrle, 940 +vldral, 940 +vldrlo, 940 +vldrcc, 940 +vldrhs, 940 +vldrcs, 940 +vldrnv, 940 +vmax, 942 +vmin, 942 +vmla, 946 +vmlal, 946 +vmls, 946 +vmlsl, 946 +vmov, 952 +vmoveq, 956 +vmovne, 956 +vmovmi, 956 +vmovpl, 956 +vmovvs, 956 +vmovvc, 956 +vmovhi, 956 +vmovls, 956 +vmovge, 956 +vmovlt, 956 +vmovgt, 956 +vmovle, 956 +vmoval, 956 +vmovlo, 956 +vmovcc, 956 +vmovhs, 956 +vmovcs, 956 +vmovnv, 956 +vmovl, 966 +vmovn, 968 +vmrs, 970 +vmrseq, 970 +vmrsne, 970 +vmrsmi, 970 +vmrspl, 970 +vmrsvs, 970 +vmrsvc, 970 +vmrshi, 970 +vmrsls, 970 +vmrsge, 970 +vmrslt, 970 +vmrsgt, 970 +vmrsle, 970 +vmrsal, 970 +vmrslo, 970 +vmrscc, 970 +vmrshs, 970 +vmrscs, 970 +vmrsnv, 970 +vmsr, 972 +vmsreq, 972 +vmsrne, 972 +vmsrmi, 972 +vmsrpl, 972 +vmsrvs, 972 +vmsrvc, 972 +vmsrhi, 972 +vmsrls, 972 +vmsrge, 972 +vmsrlt, 972 +vmsrgt, 972 +vmsrle, 972 +vmsral, 972 +vmsrlo, 972 +vmsrcc, 972 +vmsrhs, 972 +vmsrcs, 972 +vmsrnv, 972 +vmul, 974 +vmull, 974 +vmvn, 980 +vneg, 984 +vnmla, 986 +vnmlaeq, 986 +vnmlane, 986 +vnmlami, 986 +vnmlapl, 986 +vnmlavs, 986 +vnmlavc, 986 +vnmlahi, 986 +vnmlals, 986 +vnmlage, 986 +vnmlalt, 986 +vnmlagt, 986 +vnmlale, 986 +vnmlaal, 986 +vnmlalo, 986 +vnmlacc, 986 +vnmlahs, 986 +vnmlacs, 986 +vnmlanv, 986 +vnmls, 986 +vnmlseq, 986 +vnmlsne, 986 +vnmlsmi, 986 +vnmlspl, 986 +vnmlsvs, 986 +vnmlsvc, 986 +vnmlshi, 986 +vnmlsls, 986 +vnmlsge, 986 +vnmlslt, 986 +vnmlsgt, 986 +vnmlsle, 986 +vnmlsal, 986 +vnmlslo, 986 +vnmlscc, 986 +vnmlshs, 986 +vnmlscs, 986 +vnmlsnv, 986 +vnmul, 986 +vnmuleq, 986 +vnmulne, 986 +vnmulmi, 986 +vnmulpl, 986 +vnmulvs, 986 +vnmulvc, 986 +vnmulhi, 986 +vnmulls, 986 +vnmulge, 986 +vnmullt, 986 +vnmulgt, 986 +vnmulle, 986 +vnmulal, 986 +vnmullo, 986 +vnmulcc, 986 +vnmulhs, 986 +vnmulcs, 986 +vnmulnv, 986 +vorn, 988 +vorr, 990 +vpadal, 994 +vpadd, 996 +vpaddl, 1000 +vpmax, 1002 +vpmin, 1002 +vpop, 1006 +vpopeq, 1006 +vpopne, 1006 +vpopmi, 1006 +vpoppl, 1006 +vpopvs, 1006 +vpopvc, 1006 +vpophi, 1006 +vpopls, 1006 +vpopge, 1006 +vpoplt, 1006 +vpopgt, 1006 +vpople, 1006 +vpopal, 1006 +vpoplo, 1006 +vpopcc, 1006 +vpophs, 1006 +vpopcs, 1006 +vpopnv, 1006 +vpush, 1008 +vpusheq, 1008 +vpushne, 1008 +vpushmi, 1008 +vpushpl, 1008 +vpushvs, 1008 +vpushvc, 1008 +vpushhi, 1008 +vpushls, 1008 +vpushge, 1008 +vpushlt, 1008 +vpushgt, 1008 +vpushle, 1008 +vpushal, 1008 +vpushlo, 1008 +vpushcc, 1008 +vpushhs, 1008 +vpushcs, 1008 +vpushnv, 1008 +vqabs, 1010 +vqadd, 1012 +vqdmlal, 1014 +vqdmlsl, 1014 +vqdmulh, 1016 +vqdmull, 1018 +vqmovn, 1020 +vqmovun, 1020 +vqneg, 1022 +vqrdmulh, 1024 +vqrshl, 1026 +vqrshrn, 1028 +vqrshrun, 1028 +vqshl, 1030 +vqshlu, 1032 +vqshrn, 1034 +vqshrun, 1034 +vqsub, 1036 +vraddhn, 1038 +vrecpe, 1040 +vrecps, 1042 +vrev16, 1044 +vrev32, 1044 +vrev64, 1044 +vrhadd, 1046 +vrshl, 1048 +vrshr, 1050 +vrshrn, 1052 +vrsqrte, 1054 +vrsqrts, 1056 +vrsra, 1058 +vrsubhn, 1060 +vshl, 1062 +vshll, 1066 +vshr, 1068 +vshrn, 1070 +vsli, 1072 +vsqrt, 1074 +vsqrteq, 1074 +vsqrtne, 1074 +vsqrtmi, 1074 +vsqrtpl, 1074 +vsqrtvs, 1074 +vsqrtvc, 1074 +vsqrthi, 1074 +vsqrtls, 1074 +vsqrtge, 1074 +vsqrtlt, 1074 +vsqrtgt, 1074 +vsqrtle, 1074 +vsqrtal, 1074 +vsqrtlo, 1074 +vsqrtcc, 1074 +vsqrths, 1074 +vsqrtcs, 1074 +vsqrtnv, 1074 +vsra, 1076 +vsri, 1078 +vst1, 1080 +vst2, 1084 +vst3, 1088 +vst4, 1092 +vstmia, 1096 +vstmiaeq, 1096 +vstmiane, 1096 +vstmiami, 1096 +vstmiapl, 1096 +vstmiavs, 1096 +vstmiavc, 1096 +vstmiahi, 1096 +vstmials, 1096 +vstmiage, 1096 +vstmialt, 1096 +vstmiagt, 1096 +vstmiale, 1096 +vstmiaal, 1096 +vstmialo, 1096 +vstmiacc, 1096 +vstmiahs, 1096 +vstmiacs, 1096 +vstmianv, 1096 +vstmdb, 1096 +vstmdbeq, 1096 +vstmdbne, 1096 +vstmdbmi, 1096 +vstmdbpl, 1096 +vstmdbvs, 1096 +vstmdbvc, 1096 +vstmdbhi, 1096 +vstmdbls, 1096 +vstmdbge, 1096 +vstmdblt, 1096 +vstmdbgt, 1096 +vstmdble, 1096 +vstmdbal, 1096 +vstmdblo, 1096 +vstmdbcc, 1096 +vstmdbhs, 1096 +vstmdbcs, 1096 +vstmdbnv, 1096 +vstr, 1098 +vstreq, 1098 +vstrne, 1098 +vstrmi, 1098 +vstrpl, 1098 +vstrvs, 1098 +vstrvc, 1098 +vstrhi, 1098 +vstrls, 1098 +vstrge, 1098 +vstrlt, 1098 +vstrgt, 1098 +vstrle, 1098 +vstral, 1098 +vstrlo, 1098 +vstrcc, 1098 +vstrhs, 1098 +vstrcs, 1098 +vstrnv, 1098 +vsub, 1100 +vsubeq, 1100 +vsubne, 1100 +vsubmi, 1100 +vsubpl, 1100 +vsubvs, 1100 +vsubvc, 1100 +vsubhi, 1100 +vsubls, 1100 +vsubge, 1100 +vsublt, 1100 +vsubgt, 1100 +vsuble, 1100 +vsubal, 1100 +vsublo, 1100 +vsubcc, 1100 +vsubhs, 1100 +vsubcs, 1100 +vsubnv, 1100 +vsubhn, 1104 +vsubl, 1106 +vsubw, 1106 +vswp, 1108 +vtbl, 1110 +vtbx, 1110 +vtrn, 1112 +vtst, 1114 +vuzp, 1116 +vzip, 1118 +wfe, 1120 +wfeeq, 1120 +wfene, 1120 +wfemi, 1120 +wfepl, 1120 +wfevs, 1120 +wfevc, 1120 +wfehi, 1120 +wfels, 1120 +wfege, 1120 +wfelt, 1120 +wfegt, 1120 +wfele, 1120 +wfeal, 1120 +wfelo, 1120 +wfecc, 1120 +wfehs, 1120 +wfecs, 1120 +wfenv, 1120 +wfi, 1122 +wfieq, 1122 +wfine, 1122 +wfimi, 1122 +wfipl, 1122 +wfivs, 1122 +wfivc, 1122 +wfihi, 1122 +wfils, 1122 +wfige, 1122 +wfilt, 1122 +wfigt, 1122 +wfile, 1122 +wfial, 1122 +wfilo, 1122 +wficc, 1122 +wfihs, 1122 +wfics, 1122 +wfinv, 1122 +yield, 1124 +yieldeq, 1124 +yieldne, 1124 +yieldmi, 1124 +yieldpl, 1124 +yieldvs, 1124 +yieldvc, 1124 +yieldhi, 1124 +yieldls, 1124 +yieldge, 1124 +yieldlt, 1124 +yieldgt, 1124 +yieldle, 1124 +yieldal, 1124 +yieldlo, 1124 +yieldcc, 1124 +yieldhs, 1124 +yieldcs, 1124 +yieldnv, 1124 diff --git a/src/third-party/sleigh/processors/ARM/data/patterns/ARM_BE_patterns.xml b/src/third-party/sleigh/processors/ARM/data/patterns/ARM_BE_patterns.xml new file mode 100644 index 00000000..c74608db --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/patterns/ARM_BE_patterns.xml @@ -0,0 +1,201 @@ + + + + 0xbd .......0 + 0xbd .......0 0x0000 + 0xbd .......0 0xbf00 + 0xbd .......0 0x46c0 + 0xffff + 0x46c0 + 0x4770 + 0x4770 0x0000 + 0x4770 0x46c0 + 0xb0 000..... 0xbd ....0000 + 0x00bf + 0x8000f3af + 0xe8bd 1....... ........ + 0xf746 + 0xf8 0x5d 0xfb 0....... + + + + 0xb5 ........ 0xb0 100..... + 0xb5 ........ 0x1c 00...... + 0xb5 ........ 0x46 0x.. + 0xb5 ........ 01.01... 0x.. + 0xb5 ........ 0x68 0x.. + 0xb5 ........ 01.01... 0x.. 0xb0 10...... + 0xb5 1....... 0xaf.. + 0xb0 100..... 0xb5 ....0000 + 0x1c 00...... 0xb5 ....0000 + 0x46 0x.. 0xb5 ....0000 + 01.01...0x.. 0xb5 ....0000 + 0x68 0x.. 0xb5 ....0000 + 0xe92d 010..... ........ + + + + + + + + + 0xe12fff1. + 0xe12fff1e 0x46c0 + 0xe12fff1e 0xe1a00000 + 0xea...... + 0xe8 10.11101 10.0.... 0x.. + 0xe4 0x9d 0xf0 0x08 + 0xe1 0xa0 0xf0 0x0e + 0xe320f000 0xe1a00000 + 0xe1a00000 + + + + 0xe24dd... 11101001 00101101 .1...... ....0000 + 11101001 00101101 .1...... ....0000 0xe24dd... + 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... + 11101001 00101101 .1...... ....0000 0xe1a0 010.0000 0000000. + 11101001 00101101 .1...... ....0000 + 0xe24dd... 11100101 00101101 1110.... ........ + 11101001 00101101 .0...... ........ 11100101 00101101 11100000 ......00 + 11100101 00101101 1110.... ........ 0xe24dd... + 11100101 00101101 1110.... ........ 0x........ 0xe24dd... + 0xe5 0x2d 0xe0 0x08 + 0xe1a0c00d 0xe92d.... + + + + + + + + 0xe24dd... 11101001 00101101 .1...... ....0000 + + + + + + + + 11101001 00101101 .1...... ....0000 + + + + + + + 11101001 00101101 .1...... ....0000 + + + + + + + 0xe24dd... 11100101 00101101 1110.... ........ + + + + + + + 11100101 00101101 1110.... ........ 0xe24dd... + + + + + + + 11101001 00101101 .1...... ....0000 0x........ 0xe24dd... + + + + + + + 11100101 00101101 1110.... ........ 0x........ 0xe24dd... + + + + + + + 0xe1a0c00d 0xe92d.... + + + + + + + 0xb5 ....0000 0xb0 100..... + + + + + + + 0xe92d 010..... ........ + + + + + + + 0xb5 ....0000 0x1c 00...... + + + + + + + 0xb5 ....0000 0x46 0x.. + + + + + + + 0xb5 ....0000 01.01... 0x.. + + + + + + + 0xb5 ....0000 0x68 0x.. + + + + + + + 0xb5 ....0000 01.01... 0x.. 0xb0 10...... + + + + + + + 0xb5 1...0000 0xaf.. + + + + + + + + + 0xbd .......0 + 0xbd .......0 0xbf00 + 0x4770 + 0x4770 0xbf00 + + + 0xb5 .......0 + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/patterns/ARM_LE_patterns.xml b/src/third-party/sleigh/processors/ARM/data/patterns/ARM_LE_patterns.xml new file mode 100644 index 00000000..7e18bea0 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/patterns/ARM_LE_patterns.xml @@ -0,0 +1,322 @@ + + + + .......0 0xbd + .......0 0xbd 0x0000 + .......0 0xbd 0x00bf + .......0 0xbd 0xc0 0x46 + 0xffff + 0xc046 + 0x7047 + 0x7047 0x0000 + 0x7047 0xc046 + 000..... 0xb0 ....0000 0xbd + 0x00bf + 0xaff30080 + 0xbde8 ........ 1....... + 0x46f7 + 0x5d 0xf8 0....... 0xfb + + + + ........ 0xb5 1....... 0xb0 + ........ 0xb5 00...... 0x1c + ........ 0xb5 0x.. 0x46 + ........ 0xb5 0x.. 01.01... + ........ 0xb5 0x.. 0x68 + ........ 0xb5 0x.. 01.01... 10...... 0xb0 + 1....... 0xb5 0x..af + 100..... 0xb0 ....0000 0xb5 + 00...... 0x1c ....0000 0xb5 + + 0x.. 01.01... ....0000 0xb5 + 0x.. 0x68 ....0000 0xb5 + 0x2de9 ........ 010..... + + + + + + + + + 0x1.ff2fe1 + 0x1eff2fe1 0xc046 + 0x1eff2fe1 0x0000a0e1 + 0x......ea + 0x.. 10.0.... 10.11101 0xe8 + 0x08 0xf0 0x9d 0xe4 + 0x0e 0xf0 0xa0 0xe1 + 0x00f020e3 0x0000a0e1 + 0x0000a0e1 + + + + 0x..d.4de2 ....0000 .1...... 00101101 11101001 + ....0000 .1...... 00101101 11101001 0x..d.4de2 + ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 + ....0000 .1...... 00101101 11101001 0000000. 010.0000 0xa0e1 + ....0000 .1...... 00101101 11101001 + 0x..d.4de2 ........ 1110.... 00101101 11100101 + ........ .0...... 00101101 11101001 ......00 11100000 00101101 11100101 + ........ 1110.... 00101101 11100101 0x..d.4de2 + ........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 + 0x08 0xe0 0x2d 0xe5 + 0x0dc0a0e1 0x....2de9 + ........ .1...... 00101101 11101001 + + + + + + + + 0x..d.4de2 ....0000 .1...... 00101101 11101001 + + + + + + + + + ....0000 .1...... 00101101 11101001 + + + + + + + ........ .1...... 00101101 11101001 + + + + + + + 0x..d.4de2 ........ 1110.... 00101101 11100101 + + + + + + + + ........ 1110.... 00101101 11100101 0x..d.4de2 + + + + + + + + ....0000 .1...... 00101101 11101001 0x........ 0x..d.4de2 + + + + + + + + ........ 1110.... 00101101 11100101 0x........ 0x..d.4de2 + + + + + + + 0x0dc0a0e1 0x....2de9 + + + + + + + ....0000 0xb5 1....... 0xb0 + + + + + + + 0x2de9 ........ 010..... + + + + + + + ....0000 0xb5 00...... 0x1c + + + + + + + ....0000 0xb5 0x.. 0x46 + + + + + + + ....0000 0xb5 0x.. 01.01... + + + + + + + ....0000 0xb5 0x.. 0x68 + + + + + + + ....0000 0xb5 0x.. 01.01... 10...... 0xb0 + + + + + + + 1...0000 0xb5 0x..af + + + + + + + + + .......0 0xbd + .......0 0xbd 0x00bf + 0x7047 + 0x7047 0x00bf + + + + .......0 0xb5 + + + + + + + + + + + 0x03b4 0x7146 0x0231 0x8908 0x8000 0x8900 0x0858 0x4018 0x8646 0x03bc 0xf746 + + + + + + + 0x02b4 0x7146 0x4908 0x4900 0x095c 0x4900 0x8e44 0x02bc 0x7047 + + + + + + + 0x02b4 0x7146 0x4908 0x4900 0x0956 0x4900 0x8e44 0x02bc 0x7047 + + + + + + + 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095e 0x4900 0x8e44 0x03bc 0x7047 + + + + + + + 0x03b4 0x7146 0x4908 0x4000 0x4900 0x095a 0x4900 0x8e44 0x03bc 0x7047 + + + + + + + 0x01c05ee5 0x0c0053e1 0x0330de37 0x0c30de27 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 + + + + + + + + + 0x01c05ee5 0x0c0053e1 0x0c30de27 0x0330de37 0x83 11.00000 0x8ee0 000111.0 0xff2fe1 + + + + + + + + diff --git a/src/third-party/sleigh/processors/ARM/data/patterns/patternconstraints.xml b/src/third-party/sleigh/processors/ARM/data/patterns/patternconstraints.xml new file mode 100644 index 00000000..29ca71a3 --- /dev/null +++ b/src/third-party/sleigh/processors/ARM/data/patterns/patternconstraints.xml @@ -0,0 +1,13 @@ + + + ARM_LE_patterns.xml + + + + ARM_BE_patterns.xml + + + + ARM_LE_patterns.xml + + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c13490e2..b2fb360a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(unit-tests unit-tests/test_archEVM.cpp unit-tests/test_archX64.cpp unit-tests/test_archX86.cpp + unit-tests/test_archARM32.cpp unit-tests/test_event.cpp unit-tests/test_expression.cpp unit-tests/test_ir.cpp diff --git a/tests/unit-tests/test_all.cpp b/tests/unit-tests/test_all.cpp index 4d85bea5..d043b0cc 100644 --- a/tests/unit-tests/test_all.cpp +++ b/tests/unit-tests/test_all.cpp @@ -18,6 +18,7 @@ void test_solver(); void test_loader(); void test_serialization(); void test_archEVM(); +void test_archARM32(); int main(int argc, char ** argv) @@ -52,6 +53,7 @@ int main(int argc, char ** argv) test_archX86(); test_archX64(); test_archEVM(); + test_archARM32(); test_solver(); test_loader(); test_serialization(); @@ -80,6 +82,8 @@ int main(int argc, char ** argv) test_archX86(); else if( !strcmp(argv[i], "X64")) test_archX64(); + else if( !strcmp(argv[i], "ARM32")) + test_archARM32(); else if( !strcmp(argv[i], "EVM")) test_archEVM(); else if( !strcmp(argv[i], "event")) diff --git a/tests/unit-tests/test_archARM32.cpp b/tests/unit-tests/test_archARM32.cpp new file mode 100644 index 00000000..207361a5 --- /dev/null +++ b/tests/unit-tests/test_archARM32.cpp @@ -0,0 +1,394 @@ +#include "maat/arch.hpp" +#include "maat/varcontext.hpp" +#include "maat/engine.hpp" +#include "maat/exception.hpp" +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::string; + +namespace test +{ + namespace archARM32 + { + + using namespace maat; + + unsigned int _assert(bool val, const string& msg){ + if( !val){ + cout << "\nFail: " << msg << std::endl; + throw test_exception(); + } + return 1; + } + + unsigned int test_THUMB () { + string code; + MaatEngine sym = MaatEngine(Arch::Type::ARM32); + unsigned int return_val = 0; + + sym.mem->map(0x1000, 0x2000); + code = string("\x1e\xff\x2f\xe1",4); // bx lr (branch and change to thumb mode) + sym.cpu.ctx().set(ARM32::LR, exprcst(32, 0x101d)); // set link register to 0x101c + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + code = string("\x88\x18",2); // add r0, r1, r2 + sym.cpu.ctx().set(ARM32::R1, exprcst(32, 0x1111)); // set r1 to 0x1111 + sym.cpu.ctx().set(ARM32::R2, exprcst(32, 0x1234)); // set r2 to 0x1234 + + sym.mem->write_buffer(0x101c, (uint8_t*)code.c_str(), code.size()); + + code = string("\x10\x46",2); // mov r0, r2 + sym.mem->write_buffer(0x101e, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,2); + return_val += _assert(sym.cpu.ctx().get(ARM32::R0).as_uint() == 0x2345, "1: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x1111, "2: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::R2).as_uint() == 0x1234, "3: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::TF).as_uint() == 0x1, "4: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ISAModeSwitch).as_uint() == 0x1, "5: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20, "6: ArchARM32: Failed to test Thumb mode"); + + sym.run_from(0x101e,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R0).as_uint() == 0x1234, "7: ArchARM32: Failed to test Thumb mode"); + + sym.cpu.ctx().set(ARM32::LR, exprcst(32,0x1024)); + code = string("\x70\x47", 2); // bx lr (thumb mode) + sym.mem->write_buffer(0x1020, (uint8_t*)code.c_str(), code.size()); + + code = string("\x01\x3a\xa0\xe3",4); // mov r3,0x1000 + sym.mem->write_buffer(0x1024, (uint8_t*)code.c_str(),code.size()); + + sym.run_from(0x1020,2); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0x1000, "7: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ISAModeSwitch).as_uint() == 0x0, "8: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::TF).as_uint() == 0x0, "9: ArchARM32: Failed to test Thumb mode"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x0, "10: ArchARM32: Failed to test Thumb mode"); + + sym.cpu.ctx().set(ARM32::TF,exprcst(8,0x1)); + sym.run_from(0x101c,2); + + return return_val; + } + + unsigned int disass_mov(MaatEngine &sym) { + unsigned int return_val = 0; + string code; + + code = string("\x01\x3a\xa0\xe3",4); // mov r3,0x1000 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0x1000, "1: ArchARM32: Failed to disassembly and/or execute move instruction"); + + // Test Logical Shift Left By 2 + sym.cpu.ctx().set(ARM32::R3, exprcst(32, 0xf)); // set r3 to 0xf + code = string("\x03\x31\xa0\xe1",4); // mov r3,r3, lsl #0x2 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0x3c, "2: ArchARM32: Failed to disassembly and/or execute move instruction"); + + // Test Logical Shift Right By 2 + sym.cpu.ctx().set(ARM32::R3, exprcst(32, 0xf)); // set r3 to 0xf + code = string("\x23\x31\xa0\xe1",4); // mov r3,r3, lsr #0x2 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0x3, "3: ArchARM32: Failed to disassembly and/or execute move instruction"); + // Test Arithmetic Shift Right + sym.cpu.ctx().set(ARM32::R3, exprcst(32, 0xf0000000)); // set r3 to 0xf0000000 + code = string("\x43\x31\xa0\xe1",4); // mov r3,r3, asr #0x2 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0xfc000000, "4: ArchARM32: Failed to disassembly and/or execute move instruction"); + + // test Rotate Right Shift + sym.cpu.ctx().set(ARM32::R3, exprcst(32, 0x80000007)); // set r3 to 0x80000007 + code = string("\x63\x31\xa0\xe1",4); // mov r3,r3, ror #0x2 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0xe0000001, "5: ArchARM32: Failed to disassembly and/or execute move instruction"); + + sym.cpu.ctx().set(ARM32::CF, exprcst(8,0x0)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0xf)); // set r3 to 0x1 + code = string("\x63\x30\xa0\xe1"); // mov r3,r3, rrx + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R3).as_uint() == 0x7, "6: ArchARM32: Failed to disassembly and/or execute move instruction"); + + return_val += _assert(sym.cpu.ctx().get(ARM32::SC).as_uint() == 0x1, "7: ArchARM32: Failed to disassembly and/or execute move instruction"); + + return return_val; + } + + unsigned int disass_add(MaatEngine &sym) { + unsigned int return_val = 0; + string code; + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x1000)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x1234)); + + code = string("\x03\x10\x82\xe0",4); // add r1, r2, r3 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x2234, "1: ArchARM32: Failed to disassembly and/or execute add instruction"); + + code = string("\x03\x10\x92\xe0",4); // adds r1, r2, r3 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x2234, "2: ArchARM32: Failed to disassembly and/or execute add instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "3: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "4: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x0, "5: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "6: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x0, "7: ArchARM32: Failed to disassembly and/or execute add instruction, CPSR is incorrect"); + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x7fffffff)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x1)); + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x80000000, "8: ArchARM32: Failed to disassembly and/or execute add instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x1, "9: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x1, "10: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x0, "11: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "12: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x90000000, "13: ArchARM32: Failed to disassembly and/or execute add instruction, CPSR is incorrect"); + + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0xffffabcd)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0xffffabcd)); + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0xffff579a, "7: ArchARM32: Failed to disassembly and/or execute add instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x1, "8: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "9: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "10: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "11: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0xa0000000, "12: ArchARM32: Failed to disassembly and/or execute add instruction"); + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x0)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x0)); + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x0, "13: ArchARM32: Failed to disassembly and/or execute add instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "14: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "15: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x0, "16: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x1, "17: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x40000000, "18: ArchARM32: Failed to disassembly and/or execute add instruction"); + + return return_val; + } + + unsigned int disass_sub(MaatEngine &sym) { + unsigned int return_val = 0; + string code; + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x1000)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x1234)); + + code = string("\x03\x10\x42\xe0",4); // sub r1, r2, r3 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0xfffffdcc, "1: ArchARM32: Failed to disassembly and/or execute sub instruction"); + + + code = string("\x03\x10\x52\xe0",4); // subs r1, r2, r3 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0xfffffdcc, "2: ArchARM32: Failed to disassembly and/or execute sub instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x1, "3: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "4: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x0, "5: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "6: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x80000000, "7: ArchARM32: Failed to disassembly and/or execute add instruction"); + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x1111)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x1111)); + sym.run_from(0x1000,1); + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x0, "8: ArchARM32: Failed to disassembly and/or execute sub instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "9: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "10: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "11: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x1, "12: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x60000000, "13: ArchARM32: Failed to disassembly and/or execute add instruction"); + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0xffffabcd)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x7fff6543)); + sym.run_from(0x1000,1); + + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_uint() == 0x8000468a, "14: ArchARM32: Failed to disassembly and/or execute sub instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x1, "15: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "16: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "17: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "18: ArchARM32: Failed to disassembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0xa0000000, "19: ArchARM32: Failed to disassembly and/or execute add instruction"); + + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0xc7000000)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0x56000000)); + sym.run_from(0x1000,1); + + return_val += _assert(sym.cpu.ctx().get(ARM32::R1).as_int() == 0x71000000, "20. ArchArm32: Failed to disaseembly and/or execute sub instruction"); + // Test Flag Bits + return_val += _assert(sym.cpu.ctx().get(ARM32::NF).as_int() == 0x0, "21. ArchArm32: Failed to disaseembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::VF).as_int() == 0x1, "22. ArchArm32: Failed to disaseembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CF).as_int() == 0x1, "23. ArchArm32: Failed to disaseembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::ZF).as_int() == 0x0, "24. ArchArm32: Failed to disaseembly and/or execute sub instruction"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x30000000, "25: ArchARM32: Failed to disassembly and/or execute add instruction"); + + return return_val; + } + + unsigned int disass_branch(MaatEngine& sym){ + unsigned int return_val = 0; + string code; + + code = string("\x0f\x00\xa0\xe3", 4); // mov r0, #15 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + code = string("\x0a\x00\x50\xe3", 4); // cmp r0, #10 + sym.mem->write_buffer(0x1004, (uint8_t*)code.c_str(), code.size()); + + code = string("\x00\x00\x00\xda", 4); // b.le #8 + sym.mem->write_buffer(0x1008, (uint8_t*)code.c_str(), code.size()); + + code = string("\x01\x50\xa0\xe3", 4); // mov r5, #1 + sym.mem->write_buffer(0x100c, (uint8_t*)code.c_str(), code.size()); + + code = string("\x02\x50\xa0\xe3", 4); // mov r5, #2 + sym.mem->write_buffer(0x1010, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,4); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "1: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x1, "2: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "3: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "4: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "5: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "6: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "7: ArchARM32: Failed to disassembly and/or execute add instruction"); + + code = string("\x00\x00\x00\xaa", 4); // b.ge #8 + sym.mem->write_buffer(0x1008, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,4); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "8: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x2, "9: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "10: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "10: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "11: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "12: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "25: ArchARM32: Failed to disassembly and/or execute add instruction"); + + code = string("\x0f\x00\x50\xe3", 4); // cmp r0, #15 + sym.mem->write_buffer(0x1004, (uint8_t*)code.c_str(), code.size()); + code = string("\x00\x00\x00\x0a", 4); // b.eq #8 + sym.mem->write_buffer(0x1008, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,4); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "13: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x2, "14: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "15: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "16: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "17: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x1, "18: ArchARM64: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x60000000, "25: ArchARM32: Failed to disassembly and/or execute add instruction"); + + return return_val; + } + + unsigned int disass_store_load(MaatEngine& sym){ + unsigned int return_val = 0; + string code; + + // Set Registers + sym.cpu.ctx().set(ARM32::R0, exprcst(32,0xDEADBEEF)); + sym.cpu.ctx().set(ARM32::R1, exprcst(32,0x110000)); + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R4, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R5, exprcst(32,0)); + + code = string("\x00\x00\x01\xe4", 4); // str r0 [r1] 0x0 + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert((uint32_t)sym.mem->read(0x110000, 4).as_uint() == 0xDEADBEEF, "1: ArchARM64: failed to disassemble store and load instructions."); + + code = string("\x00\x20\x11\xe4", 4); // ldr r2 [r1] + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); + + sym.run_from(0x1000,1); + return_val += _assert( sym.cpu.ctx().get(ARM32::R2).as_uint() == 0xDEADBEEF, "1: ArchARM64: failed to disassemble store and load instructions."); + + return return_val; + } + + unsigned int test_binary() + { + unsigned int return_val = 0; + MaatEngine sym = MaatEngine(Arch::Type::X64); + sym.load("tests/resources/simple_algo_2/crackmex86", + loader::Format::ELF64, + 0x100000, + {}, + {}, + {}, + {}, + {} + ); + Expr value = exprvar(64,"input"); + sym.settings.log_insts = true; + sym.cpu.ctx().set(X64::RDI, value); + sym.cpu.ctx().set(X64::RIP, exprcst(64,0x1011c9)); // transform + + sym.run(); + return return_val; + } + + } +} + +using namespace test::archARM32; + +void test_archARM32() { + unsigned int total = 0; + string green = "\033[1;32m"; + string def = "\033[0m"; + string bold = "\033[1m"; + + // Start testing + cout << bold << "[" << green << "+" << def << bold << "]" << def << std::left << std::setw(34) << " Testing arch ARM32 support... " << std::flush; + + MaatEngine engine(Arch::Type::ARM32); + engine.mem->map(0x0, 0x10000); + engine.mem->map(0x110000, 0x130000); + + total += disass_mov(engine); + total += disass_add(engine); + total += disass_sub(engine); + total += disass_branch(engine); + total += disass_store_load(engine); + + total += test_THUMB(); + // total += test_binary(); + + // total += test_float(); + cout << "\t" << total << "/" << total << green << "\tOK" << def << endl; +} \ No newline at end of file From cf868a6541e7ac1f784dc4b4056d398fcb06b247 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Wed, 23 Aug 2023 10:27:38 +0930 Subject: [PATCH 02/14] added syscall --- src/env/abi.cpp | 108 +++++++++++++++++++ src/env/emulated_libs/libc.cpp | 15 +++ src/env/emulated_syscalls/linux_syscalls.cpp | 26 +++++ src/env/env.cpp | 10 ++ src/env/env_linux.cpp | 3 + src/include/maat/env/library.hpp | 61 ++++++++++- src/include/maat/env/syscall.hpp | 2 + 7 files changed, 224 insertions(+), 1 deletion(-) diff --git a/src/env/abi.cpp b/src/env/abi.cpp index 142660d8..876f4368 100644 --- a/src/env/abi.cpp +++ b/src/env/abi.cpp @@ -402,6 +402,114 @@ void X86_LINUX_INT80::ret(MaatEngine& engine) const // Do nothing } +/*============ LINUX PowerPC ABI ============*/ +ARM32ABI::ARM32ABI(): ABI(Type::ARM32ABI) +{} + +ABI& ARM32ABI::instance() +{ + static ARM32ABI abi; + return abi; +} + +void ARM32ABI::get_args( + MaatEngine& engine, + const args_spec_t& args_spec, + std::vector& args +) const +{ + int i = 0; + for (auto arg : args_spec) + args.push_back(get_arg(engine, i++, arg)); +} + +Value ARM32ABI::get_arg(MaatEngine& engine, int n, size_t arg_size) const +{ + // Regs on the stack, pushed right to left + arg_size = ABI::real_arg_size(engine, arg_size); + Value res = engine.mem->read(engine.cpu.ctx().get(ARM32::SP).as_uint() + 4 + 4*n, 4); + return _adjust_value_to_size(res, arg_size, engine); +} + +void ARM32ABI::set_ret_value( + MaatEngine& engine, + const FunctionCallback::return_t& ret_val +) const +{ + // Return value in R0 + std::visit(maat::util::overloaded{ + [](std::monostate arg){return;}, // no return value + [&engine](auto arg){engine.cpu.ctx().set(ARM32::R0, arg);} + }, ret_val); +} + +void ARM32ABI::prepare_ret_address(MaatEngine& engine, addr_t ret_addr) const +{ + // Push the return address, simply + engine.cpu.ctx().set(ARM32::PC, engine.cpu.ctx().get(ARM32::PC).as_uint() - 4); + engine.mem->write(engine.cpu.ctx().get(ARM32::SP).as_uint(), ret_addr, 4); +} + +void ARM32ABI::ret(MaatEngine& engine) const +{ + // Pop return address, SP (pop from the stack) + engine.cpu.ctx().set(ARM32::PC, engine.mem->read((engine.cpu.ctx().get(ARM32::SP).as_uint()), 4)); + engine.cpu.ctx().set(ARM32::SP, engine.cpu.ctx().get(ARM32::SP).as_uint() + 4); +} + +/* ============== ABI PowerPC SYSCALL LINUX ==============*/ +ARM32_SYSCALL::ARM32_SYSCALL(): ABI(Type::ARM32_SYSCALL) +{} + +ABI& ARM32_SYSCALL::instance() +{ + static ARM32_SYSCALL abi; + return abi; +} + +void ARM32_SYSCALL::get_args( + MaatEngine& engine, + const args_spec_t& args_spec, + std::vector& args +) const +{ + int i = 0; + for (auto arg : args_spec) + args.push_back(get_arg(engine, i++, arg)); +} + +Value ARM32_SYSCALL::get_arg(MaatEngine& engine, int n, size_t arg_size) const +{ + std::vector arg_regs{ARM32::R0,ARM32::R1,ARM32::R2,ARM32::R3,ARM32::R4,ARM32::R5,ARM32::R6,ARM32::R7, ARM32::R8}; + Value res; + arg_size = ABI::real_arg_size(engine, arg_size); + if (n >= arg_regs.size()) + { + throw env_exception("get_arg(): Linux ARM32 CS ABI supports only up to 9 arguments"); + } + else + { + res = engine.cpu.ctx().get(arg_regs[n]); + } + return _adjust_value_to_size(res, arg_size, engine); +} + +void ARM32_SYSCALL::set_ret_value( + MaatEngine& engine, + const FunctionCallback::return_t& ret_val +) const +{ + // Return value in R3 and in R4 + std::visit(maat::util::overloaded{ + [](std::monostate arg){return;}, // no return value + [&engine](auto arg){engine.cpu.ctx().set(ARM32::R0, arg);} + }, ret_val); +} +void ARM32_SYSCALL::ret(MaatEngine& engine) const +{ + // Do nothing +} + } // namespace abi } // namespace env } // namespace maat diff --git a/src/env/emulated_libs/libc.cpp b/src/env/emulated_libs/libc.cpp index 1c38fc1b..6df70da5 100644 --- a/src/env/emulated_libs/libc.cpp +++ b/src/env/emulated_libs/libc.cpp @@ -659,6 +659,21 @@ Library linux_x64_libc() return lib; } +// For Linux ARM32 +Library linux_ARM32_libc() +{ + Library lib("libc", libc_common_functions, libc_common_data); + // Arch specific functions... + //TODO Find functions to use + lib.add_function(Function("__libc_start_main", + FunctionCallback({8,8,8,8,8,8,8}, linux_x64_libc_start_main_callback_part1) + )); + lib.add_function(Function("__libc_start_main_part2", + FunctionCallback({}, linux_x64_libc_start_main_callback_part2) + )); + return lib; +} + } // namespace emulated } // namespace env } // namespace maat diff --git a/src/env/emulated_syscalls/linux_syscalls.cpp b/src/env/emulated_syscalls/linux_syscalls.cpp index 23f912db..da9166a5 100644 --- a/src/env/emulated_syscalls/linux_syscalls.cpp +++ b/src/env/emulated_syscalls/linux_syscalls.cpp @@ -833,6 +833,32 @@ syscall_func_map_t linux_x64_syscall_map() return res; } +syscall_func_map_t linux_ARM32_syscall_map() +{ + syscall_func_map_t res + { + {1, Function("sys_exit", FunctionCallback({4}, sys_linux_exit))}, + {3, Function("sys_read", FunctionCallback({4, env::abi::auto_argsize, 4}, sys_linux_read))}, + {4, Function("sys_write", FunctionCallback({4, env::abi::auto_argsize, 4}, sys_linux_write))}, + {5, Function("sys_open", FunctionCallback({env::abi::auto_argsize, 4, 4}, sys_linux_open))}, + {6, Function("sys_close", FunctionCallback({4}, sys_linux_close))}, + {33, Function("sys_access", FunctionCallback({env::abi::auto_argsize, 4}, sys_linux_access))}, + {45, Function("sys_brk", FunctionCallback({env::abi::auto_argsize}, sys_linux_brk))}, + {85, Function("sys_readlink", FunctionCallback({env::abi::auto_argsize, env::abi::auto_argsize, env::abi::auto_argsize}, sys_linux_readlink))}, + {91, Function("sys_munmap", FunctionCallback({env::abi::auto_argsize, env::abi::auto_argsize}, sys_linux_munmap))}, + {125, Function("sys_mprotect", FunctionCallback({env::abi::auto_argsize, 4, 4}, sys_linux_mprotect))}, + {106, Function("sys_stat", FunctionCallback({env::abi::auto_argsize, env::abi::auto_argsize}, sys_linux_stat))}, + {108, Function("sys_fstat", FunctionCallback({4, env::abi::auto_argsize}, sys_linux_fstat))}, + {122, Function("sys_newuname", FunctionCallback({env::abi::auto_argsize}, sys_linux_newuname))}, + {146, Function("sys_writev", FunctionCallback({4, env::abi::auto_argsize, env::abi::auto_argsize}, sys_linux_writev))}, + {180, Function("sys_pread64", FunctionCallback({4, env::abi::auto_argsize, 4, 4}, sys_linux_pread))}, + {192, Function("sys_mmap", FunctionCallback({env::abi::auto_argsize, 4, 4, 4, 4, 4}, sys_linux_mmap))}, + {248, Function("sys_exit_group", FunctionCallback({4}, sys_linux_exit))}, + {322, Function("sys_openat", FunctionCallback({4, env::abi::auto_argsize, 4, 4}, sys_linux_openat))} + }; + return res; +} + } // namespace emulated } // namespace env } // namespace maat diff --git a/src/env/env.cpp b/src/env/env.cpp index 0e12cf7e..f00e2f4a 100644 --- a/src/env/env.cpp +++ b/src/env/env.cpp @@ -15,6 +15,11 @@ abi::ABI* _get_default_abi(Arch::Type arch, OS os) if (os == OS::LINUX) return &abi::X64_SYSTEM_V::instance(); } + else if (arch == Arch::Type::ARM32) + { + if (os == OS::LINUX) + return &abi::ARM32ABI::instance(); + } return &abi::ABI_NONE::instance(); } @@ -25,6 +30,11 @@ abi::ABI* _get_syscall_abi(Arch::Type arch, OS os) if (os == OS::LINUX) return &abi::X64_LINUX_SYSCALL::instance(); } + if (arch == Arch::Type::ARM32) + { + if (os == OS::LINUX) + return &abi::ARM32_SYSCALL::instance(); + } return &abi::ABI_NONE::instance(); } diff --git a/src/env/env_linux.cpp b/src/env/env_linux.cpp index a1f0d585..b71759e6 100644 --- a/src/env/env_linux.cpp +++ b/src/env/env_linux.cpp @@ -23,6 +23,9 @@ void LinuxEmulator::_init(Arch::Type arch) _libraries.push_back(env::emulated::linux_x64_libc()); _syscall_func_map = env::emulated::linux_x64_syscall_map(); break; + case Arch::Type::ARM32: + _libraries.push_back(env::emulated::linux_ARM32_libc()); + _syscall_func_map = env::emulated::linux_x64_syscall_map(); case Arch::Type::NONE: default: break; diff --git a/src/include/maat/env/library.hpp b/src/include/maat/env/library.hpp index 914d747b..750f5dbc 100644 --- a/src/include/maat/env/library.hpp +++ b/src/include/maat/env/library.hpp @@ -103,6 +103,9 @@ enum class Type X64_LINUX_SYSCALL, /* ARM64 */ ARM64, + /* ARM32 */ + ARM32ABI, + ARM32_SYSCALL, /* Custom */ X86_LINUX_CUSTOM_SYSCALL, ///< Used internally X64_LINUX_CUSTOM_SYSCALL, ///< Used internally @@ -308,10 +311,64 @@ class X64_LINUX_SYSCALL : public ABI virtual void ret(MaatEngine& engine) const; }; -/** \} */ // doxygen group env +/// ARM32 defualt ABI +class ARM32ABI : public ABI +{ +protected: + ARM32ABI(); +public: + /// ABI instance (singleton pattern) + static ABI& instance(); +public: + /// Get function arguments + virtual void get_args( + MaatEngine& engine, + const args_spec_t& args_spec, + std::vector& args + ) const; + /// Get function argument number 'n' (starting at 0) + virtual Value get_arg(MaatEngine& engine, int n, size_t arg_size) const; + /// Set a function's return value before it returns + virtual void set_ret_value( + MaatEngine& engine, + const FunctionCallback::return_t& ret_val + ) const; + /// Set the return address prior to call a function + virtual void prepare_ret_address(MaatEngine& engine, addr_t ret_addr) const; + /// Return from a function + virtual void ret(MaatEngine& engine) const; +}; + +/// ARM32 Linux SYSCALL ABI +class ARM32_SYSCALL : public ABI +{ +protected: + ARM32_SYSCALL(); +public: + /// ABI instance (singleton pattern) + static ABI& instance(); +public: + /// Get function arguments + virtual void get_args( + MaatEngine& engine, + const args_spec_t& args_spec, + std::vector& args + ) const; + /// Get function argument number 'n' (starting at 0) + virtual Value get_arg(MaatEngine& engine, int n, size_t arg_size) const; + /// Set a function's return value before it returns + virtual void set_ret_value( + MaatEngine& engine, + const FunctionCallback::return_t& ret_val + ) const; + /// Return from the syscall + virtual void ret(MaatEngine& engine) const; +}; +/** \} */ // doxygen group env } // namespace ABI + /// Emulated function class Function { @@ -417,6 +474,8 @@ namespace emulated Library linux_x86_libc(); /// Return the emulated libc.so for Linux on X64 Library linux_x64_libc(); +/// Return the emulated libc.so for Linux on ARM32 +Library linux_ARM32_libc(); } diff --git a/src/include/maat/env/syscall.hpp b/src/include/maat/env/syscall.hpp index b6fd7bf1..a1c367ff 100644 --- a/src/include/maat/env/syscall.hpp +++ b/src/include/maat/env/syscall.hpp @@ -21,6 +21,8 @@ namespace emulated syscall_func_map_t linux_x86_syscall_map(); /// Return the emulated syscalls for Linux on X64 syscall_func_map_t linux_x64_syscall_map(); +/// Return the emulated syscalls for Linux on ARM32 +syscall_func_map_t linux_ARM32_syscall_map(); } From 11373e9250c61747c454d2d70dda9e727649b781 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Wed, 23 Aug 2023 13:57:20 +0930 Subject: [PATCH 03/14] Jessie code review --- src/arch/arch_ARM32.cpp | 8 +---- src/engine/engine.cpp | 22 ++++++------- src/env/abi.cpp | 4 +-- src/include/maat/arch.hpp | 31 ++++++------------- src/include/maat/engine.hpp | 4 +-- src/include/maat/env/library.hpp | 2 -- src/loader/loader_lief_elf.cpp | 10 +++--- .../sleigh/native/reg_translator.cpp | 15 +++++---- .../sleigh/native/sleigh_interface.cpp | 3 +- 9 files changed, 38 insertions(+), 61 deletions(-) diff --git a/src/arch/arch_ARM32.cpp b/src/arch/arch_ARM32.cpp index f5bd5b43..5ed1e933 100644 --- a/src/arch/arch_ARM32.cpp +++ b/src/arch/arch_ARM32.cpp @@ -27,33 +27,28 @@ namespace ARM32 {"r13", R13}, {"r14", R14}, {"r15", R15}, - {"fp", FP}, {"ip", IP}, {"sp", SP}, {"lr", LR}, {"pc", PC}, - {"cpsr", CPSR}, - {"nf", NF}, {"zf", ZF}, {"cf", CF}, {"vf", VF}, {"qf", QF}, - {"jf", JF}, {"ge1", GE1}, {"ge2", GE2}, {"ge3", GE3}, {"ge4", GE4}, {"tf", TF}, - {"tmpNG", tmpNG}, {"tmpZR", tmpZR}, {"tmpCY", tmpCY}, {"tmpOV", tmpOV}, - {"sc", SC}, //shift_carry + {"sc", SC}, {"ISAModeSwitch", ISAModeSwitch} }; } @@ -102,7 +97,6 @@ namespace ARM32 case SC: case ISAModeSwitch: return 8; - default: throw runtime_exception("ArchARM32::reg_size(): got unsupported reg num"); } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index b19ff231..f2843512 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -79,13 +79,12 @@ MaatEngine::MaatEngine(Arch::Type _arch, env::OS os): env(nullptr), _uid(++_uid_ #endif } -void MaatEngine::change_modes(CPUMode _arch) +void MaatEngine::change_mode(CPUMode _arch) { - CPUMode tempMode; + // switch current_CPU_Mode switch (_arch) { case CPUMode::A32: - // switch current_CPU_Mode lifters[CPUMode::A32] = std::make_shared(CPUMode::A32); _current_cpu_mode = CPUMode::A32; break; @@ -306,24 +305,21 @@ info::Stop MaatEngine::run(int max_inst) } _previous_halt_before_exec = -1; - // If Arch == ARM then check if mode needs to change - if ( arch->type == Arch::Type::ARM32) + // If Arch == ARM32 then check if mode needs to change + if (arch->type == Arch::Type::ARM32) { - // check the TF bit and change modes + // Change CPU mode if TF bit is set switch (cpu.ctx().get(ARM32::TF).as_uint()) { case 0: - if (_current_cpu_mode != CPUMode::A32){ - change_modes(CPUMode::A32); - } + if (_current_cpu_mode != CPUMode::A32) + change_mode(CPUMode::A32); break; case 1: - if (_current_cpu_mode != CPUMode::T32){ - change_modes(CPUMode::T32); - } + if (_current_cpu_mode != CPUMode::T32) + change_mode(CPUMode::T32); break; } - } // TODO: periodically increment tsc() ? diff --git a/src/env/abi.cpp b/src/env/abi.cpp index 876f4368..c8c13ccf 100644 --- a/src/env/abi.cpp +++ b/src/env/abi.cpp @@ -402,7 +402,7 @@ void X86_LINUX_INT80::ret(MaatEngine& engine) const // Do nothing } -/*============ LINUX PowerPC ABI ============*/ +/*============ LINUX ARM32 ABI ============*/ ARM32ABI::ARM32ABI(): ABI(Type::ARM32ABI) {} @@ -457,7 +457,7 @@ void ARM32ABI::ret(MaatEngine& engine) const engine.cpu.ctx().set(ARM32::SP, engine.cpu.ctx().get(ARM32::SP).as_uint() + 4); } -/* ============== ABI PowerPC SYSCALL LINUX ==============*/ +/* ============== ABI ARM32 SYSCALL LINUX ==============*/ ARM32_SYSCALL::ARM32_SYSCALL(): ABI(Type::ARM32_SYSCALL) {} diff --git a/src/include/maat/arch.hpp b/src/include/maat/arch.hpp index 644c1faf..869fa18f 100644 --- a/src/include/maat/arch.hpp +++ b/src/include/maat/arch.hpp @@ -426,6 +426,7 @@ namespace ARM64 namespace ARM32 { + /* General Purpose Registers */ static constexpr reg_t R0 = 0; static constexpr reg_t R1 = 1; static constexpr reg_t R2 = 2; @@ -447,37 +448,25 @@ namespace ARM32 static constexpr reg_t LR = 14; // Same as R14 static constexpr reg_t R15 = 15; static constexpr reg_t PC = 15; // Same as R15 - - static constexpr reg_t CPSR = 16; // Current Program Status Register - - // CPSR bits; TODO: add other flags + /* Special Registers */ + static constexpr reg_t CPSR = 16; // Current Program Status Register CPSR bits; TODO: add other flags static constexpr reg_t NF = 17; static constexpr reg_t ZF = 18; static constexpr reg_t CF = 19; static constexpr reg_t VF = 20; static constexpr reg_t QF = 21; - static constexpr reg_t JF = 22; static constexpr reg_t GE1 = 23; static constexpr reg_t GE2 = 24; static constexpr reg_t GE3 = 25; static constexpr reg_t GE4 = 26; - static constexpr reg_t TF = 27; //thumb-bit (TB) - - static constexpr reg_t tmpNG = 28; - static constexpr reg_t tmpZR = 29; - static constexpr reg_t tmpCY = 30; - static constexpr reg_t tmpOV = 31; - static constexpr reg_t SC = 32; //shift_carry - - // nathan added register (clean up after) - static constexpr reg_t ISAModeSwitch = 33; - static constexpr reg_t mult_addr = 34; // Special internal register for dealing with multiple stores/loads 32 bits - static constexpr reg_t mult_dat8 = 35; // Special internal register for dealing with multiple stores/loads 64 bits - static constexpr reg_t mult_dat16 = 36; // Special internal register for dealing with multiple stores/loads 128 bits - - - static constexpr reg_t NB_REGS = 37; + static constexpr reg_t TF = 27; // thumb-bit (TB) + static constexpr reg_t SC = 28; //shift_carry + static constexpr reg_t ISAModeSwitch = 29; + static constexpr reg_t mult_addr = 30; // Special internal register for dealing with multiple stores/loads 32 bits + static constexpr reg_t mult_dat8 = 31; // Special internal register for dealing with multiple stores/loads 64 bits + static constexpr reg_t mult_dat16 = 32; // Special internal register for dealing with multiple stores/loads 128 bits + static constexpr reg_t NB_REGS = 33; /** \addtogroup arch * \{ */ diff --git a/src/include/maat/engine.hpp b/src/include/maat/engine.hpp index 805669d2..efecfb46 100644 --- a/src/include/maat/engine.hpp +++ b/src/include/maat/engine.hpp @@ -91,8 +91,8 @@ class MaatEngine: public serial::Serializable info::Info info; /// Engine's tweakable settings and options Settings settings; - // Change CPU modes on the fly Nathan's code - void change_modes(maat::CPUMode _arch); + // Change CPU mode between ARM32 and Thumb + void change_mode(maat::CPUMode _arch); /// Logger Logger log; public: diff --git a/src/include/maat/env/library.hpp b/src/include/maat/env/library.hpp index 750f5dbc..96ee71eb 100644 --- a/src/include/maat/env/library.hpp +++ b/src/include/maat/env/library.hpp @@ -367,8 +367,6 @@ class ARM32_SYSCALL : public ABI /** \} */ // doxygen group env } // namespace ABI - - /// Emulated function class Function { diff --git a/src/loader/loader_lief_elf.cpp b/src/loader/loader_lief_elf.cpp index c02286be..e5060a09 100644 --- a/src/loader/loader_lief_elf.cpp +++ b/src/loader/loader_lief_elf.cpp @@ -243,9 +243,9 @@ void LoaderLIEF::load_elf_using_interpreter( stack_top = engine->arch->bits() == 32 ? 0x0c000000 : 0x80000000000; stack_base = alloc_segment(engine, stack_top-stack_size, stack_size, maat::mem_flag_rw, "Stack"); engine->cpu.ctx().set(reg_sp.value(), stack_base+stack_size-0x400); // - 0x400 to leave some space in memory - if (reg_bp) { - engine->cpu.ctx().set(*reg_bp, stack_base+stack_size-0x400); - } + // For x86 special register 'reg_bp', leave some space in memory + if (reg_bp) + engine->cpu.ctx().set(*reg_bp, stack_base+stack_size-0x400); // Load interpreter load_elf_interpreter(engine, interp_path, *this); @@ -295,9 +295,9 @@ void LoaderLIEF::load_elf_binary( stack_top = engine->arch->bits() == 32 ? 0x0c000000 : 0x80000000000; stack_base = alloc_segment(engine, stack_top-stack_size, stack_size, maat::mem_flag_rw, "Stack"); engine->cpu.ctx().set(reg_sp.value(), stack_base+stack_size-0x400); // - 0x400 to leave some space in memory - if (reg_bp) { + // For x86 special register 'reg_bp', leave some space in memory + if (reg_bp) engine->cpu.ctx().set(*reg_bp, stack_base+stack_size-0x400); - } // Setup heap heap_base = end_of_segment(*engine->mem, binary_name); diff --git a/src/third-party/sleigh/native/reg_translator.cpp b/src/third-party/sleigh/native/reg_translator.cpp index 360d7b6f..80dd8ea5 100644 --- a/src/third-party/sleigh/native/reg_translator.cpp +++ b/src/third-party/sleigh/native/reg_translator.cpp @@ -1321,6 +1321,7 @@ maat::ir::Param sleigh_reg_translate_EVM(const std::string& reg_name) } maat::ir::Param sleigh_reg_translate_ARM32(const std::string& reg_name) { + /* General Purpose Registers */ if (reg_name == "r0") return maat::ir::Reg(maat::ARM32::R0, 32); if (reg_name == "r1") return maat::ir::Reg(maat::ARM32::R1, 32); if (reg_name == "r2") return maat::ir::Reg(maat::ARM32::R2, 32); @@ -1335,31 +1336,29 @@ maat::ir::Param sleigh_reg_translate_ARM32(const std::string& reg_name) { if (reg_name == "r11") return maat::ir::Reg(maat::ARM32::R11, 32); if (reg_name == "r12") return maat::ir::Reg(maat::ARM32::R12, 32); + /* Special Purpose Registers */ if (reg_name == "sp") return maat::ir::Reg(maat::ARM32::SP, 32); if (reg_name == "lr") return maat::ir::Reg(maat::ARM32::LR, 32); if (reg_name == "pc") return maat::ir::Reg(maat::ARM32::PC, 32); - if (reg_name == "cpsr") return maat::ir::Reg(maat::ARM32::CPSR, 32); - if (reg_name == "mult_addr") return maat::ir::Reg(maat::ARM32::mult_addr, 32); if (reg_name == "mult_dat8") return maat::ir::Reg(maat::ARM32::mult_addr, 64); if (reg_name == "mult_dat16") return maat::ir::Reg(maat::ARM32::mult_addr, 128); - if (reg_name == "NG") return maat::ir::Reg(maat::ARM32::NF, 8); if (reg_name == "ZR") return maat::ir::Reg(maat::ARM32::ZF, 8); if (reg_name == "CY") return maat::ir::Reg(maat::ARM32::CF, 8); if (reg_name == "OV") return maat::ir::Reg(maat::ARM32::VF, 8); if (reg_name == "Q") return maat::ir::Reg(maat::ARM32::QF, 8); - // if (reg_name == "JF") return maat::ir::Reg(maat::ARM32::JF, 8); + if (reg_name == "JF") return maat::ir::Reg(maat::ARM32::JF, 8); // Not Tested if (reg_name == "GE1") return maat::ir::Reg(maat::ARM32::GE1, 8); if (reg_name == "GE2") return maat::ir::Reg(maat::ARM32::GE2, 8); if (reg_name == "GE3") return maat::ir::Reg(maat::ARM32::GE3, 8); if (reg_name == "GE4") return maat::ir::Reg(maat::ARM32::GE4, 8); if (reg_name == "TB") return maat::ir::Reg(maat::ARM32::TF, 8); - if (reg_name == "tmpNG") return maat::ir::Reg(maat::ARM32::tmpNG, 8); - if (reg_name == "tmpZR") return maat::ir::Reg(maat::ARM32::tmpZR, 8); - if (reg_name == "tmpCY") return maat::ir::Reg(maat::ARM32::tmpCY, 8); - if (reg_name == "tmpOV") return maat::ir::Reg(maat::ARM32::tmpOV, 8); + if (reg_name == "tmpNG") return maat::ir::Reg(maat::ARM32::NF, 8); + if (reg_name == "tmpZR") return maat::ir::Reg(maat::ARM32::ZF, 8); + if (reg_name == "tmpCY") return maat::ir::Reg(maat::ARM32::CF, 8); + if (reg_name == "tmpOV") return maat::ir::Reg(maat::ARM32::VF, 8); if (reg_name == "shift_carry") return maat::ir::Reg(maat::ARM32::SC, 8); if (reg_name == "ISAModeSwitch") return maat::ir::Reg(maat::ARM32::ISAModeSwitch, 8); diff --git a/src/third-party/sleigh/native/sleigh_interface.cpp b/src/third-party/sleigh/native/sleigh_interface.cpp index 44a0fa79..7f60adad 100644 --- a/src/third-party/sleigh/native/sleigh_interface.cpp +++ b/src/third-party/sleigh/native/sleigh_interface.cpp @@ -399,10 +399,11 @@ class TranslationContext // TODO - is this useful ? will this hinder performance ? // Needs to be here apparently but maybe we could tweak setData so we don't need to reset... m_sleigh->reset(&m_loader, &m_context_internal); + // If arch is arm32 bit then don't allow contextSet() (fixes low level error in ghidra) if (arch == Arch::Type::ARM32) { - // disable context setting for ARMv7 32-bit architecture + // Disable context setting for ARMv7 32-bit architecture m_sleigh->allowContextSet(false); } From 73fea2c2fb810d02095145b734ac5354be821e75 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Thu, 7 Sep 2023 13:22:35 +0930 Subject: [PATCH 04/14] slight fixes --- src/arch/arch_ARM32.cpp | 8 -------- src/loader/loader_lief.cpp | 1 + 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/arch/arch_ARM32.cpp b/src/arch/arch_ARM32.cpp index 5ed1e933..b2943ca6 100644 --- a/src/arch/arch_ARM32.cpp +++ b/src/arch/arch_ARM32.cpp @@ -44,10 +44,6 @@ namespace ARM32 {"ge3", GE3}, {"ge4", GE4}, {"tf", TF}, - {"tmpNG", tmpNG}, - {"tmpZR", tmpZR}, - {"tmpCY", tmpCY}, - {"tmpOV", tmpOV}, {"sc", SC}, {"ISAModeSwitch", ISAModeSwitch} }; @@ -90,10 +86,6 @@ namespace ARM32 case GE3: case GE4: case TF: - case tmpNG: - case tmpZR: - case tmpCY: - case tmpOV: case SC: case ISAModeSwitch: return 8; diff --git a/src/loader/loader_lief.cpp b/src/loader/loader_lief.cpp index 9f692c03..7663155a 100644 --- a/src/loader/loader_lief.cpp +++ b/src/loader/loader_lief.cpp @@ -103,6 +103,7 @@ void LoaderLIEF::get_arch_special_registers( fs = X64::FS; break; case Arch::Type::ARM32: + bp = ARM32::R12; break; default: throw loader_exception( From c5141baa525b61f9f3ff9e8d8c09dcedf6eb9b3b Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Thu, 7 Sep 2023 14:32:45 +0930 Subject: [PATCH 05/14] bp for arm32 is in r11 --- src/loader/loader_lief.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader/loader_lief.cpp b/src/loader/loader_lief.cpp index 7663155a..a8027556 100644 --- a/src/loader/loader_lief.cpp +++ b/src/loader/loader_lief.cpp @@ -103,7 +103,7 @@ void LoaderLIEF::get_arch_special_registers( fs = X64::FS; break; case Arch::Type::ARM32: - bp = ARM32::R12; + bp = ARM32::R11; break; default: throw loader_exception( From 39a367e9d811e00b70e3be203181fc5daa45172b Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Thu, 12 Oct 2023 11:31:01 +1030 Subject: [PATCH 06/14] made syscalls more obvious, detailed comment for sleigh interface --- src/engine/callother.cpp | 42 ++++++++ src/env/abi.cpp | 26 ++--- src/env/env.cpp | 2 +- src/env/env_linux.cpp | 2 +- src/include/maat/callother.hpp | 2 + src/include/maat/env/library.hpp | 6 +- .../sleigh/native/sleigh_interface.cpp | 3 +- tests/unit-tests/test_archARM32.cpp | 96 ++++++++++--------- 8 files changed, 117 insertions(+), 62 deletions(-) diff --git a/src/engine/callother.cpp b/src/engine/callother.cpp index f12b7b49..87dcf91c 100644 --- a/src/engine/callother.cpp +++ b/src/engine/callother.cpp @@ -25,6 +25,8 @@ Id mnemonic_to_id(const std::string& mnemonic, Arch::Type arch) if (mnemonic == "STACK_PUSH") return Id::EVM_STACK_PUSH; if (mnemonic == "STACK_POP") return Id::EVM_STACK_POP; break; + case Arch::Type::ARM32: + if (mnemonic == "swi") return Id::ARM32_SC; default: break; } @@ -1041,6 +1043,44 @@ void EVM_LOG_handler(MaatEngine& engine, const ir::Inst& inst, ir::ProcessedInst } } +/* +System call for ARM32. +The syscalls are untested and don't work +*/ +void ARM32_SC_handler(MaatEngine& engine, const ir::Inst& inst, ir::ProcessedInst& pinst) +{ + // Get syscall number + const Value& sys_num = engine.cpu.ctx().get(ARM32::R7); + if (sys_num.is_symbolic(*engine.vars)) + { + throw callother_exception("SWI 0x0: syscall number is symbolic!"); + } + // Get function to emulate syscall` + try + { + const env::Function& func = engine.env->get_syscall_func_by_num( + sys_num.as_uint(*engine.vars) + ); + + // Execute function callback + switch (func.callback().execute(engine, env::abi::ARM32_SYSCALL::instance())) + { + case env::Action::CONTINUE: + break; + case env::Action::ERROR: + throw callother_exception( + "SWI 0x0: Emulation callback signaled an error, SWI is untested and might not work!!" + ); + } + } + catch(const env_exception& e) + { + throw callother_exception( + Fmt() << "SWI 0x0: " << e.what() >> Fmt::to_str + ); + } +} + /// Return the default handler map for CALLOTHER occurences HandlerMap default_handler_map() { @@ -1083,6 +1123,8 @@ HandlerMap default_handler_map() h.set_handler(Id::EVM_SELFDESTRUCT, EVM_SELFDESTRUCT_handler); h.set_handler(Id::EVM_LOG, EVM_LOG_handler); + h.set_handler(Id::ARM32_SC, ARM32_SC_handler); + return h; } diff --git a/src/env/abi.cpp b/src/env/abi.cpp index c8c13ccf..02dea29c 100644 --- a/src/env/abi.cpp +++ b/src/env/abi.cpp @@ -402,17 +402,17 @@ void X86_LINUX_INT80::ret(MaatEngine& engine) const // Do nothing } -/*============ LINUX ARM32 ABI ============*/ -ARM32ABI::ARM32ABI(): ABI(Type::ARM32ABI) +/*============ LINUX ARM32 EABI ============*/ +ARM32EABI::ARM32EABI(): ABI(Type::ARM32EABI) {} -ABI& ARM32ABI::instance() +ABI& ARM32EABI::instance() { - static ARM32ABI abi; + static ARM32EABI abi; return abi; } -void ARM32ABI::get_args( +void ARM32EABI::get_args( MaatEngine& engine, const args_spec_t& args_spec, std::vector& args @@ -423,7 +423,7 @@ void ARM32ABI::get_args( args.push_back(get_arg(engine, i++, arg)); } -Value ARM32ABI::get_arg(MaatEngine& engine, int n, size_t arg_size) const +Value ARM32EABI::get_arg(MaatEngine& engine, int n, size_t arg_size) const { // Regs on the stack, pushed right to left arg_size = ABI::real_arg_size(engine, arg_size); @@ -431,7 +431,7 @@ Value ARM32ABI::get_arg(MaatEngine& engine, int n, size_t arg_size) const return _adjust_value_to_size(res, arg_size, engine); } -void ARM32ABI::set_ret_value( +void ARM32EABI::set_ret_value( MaatEngine& engine, const FunctionCallback::return_t& ret_val ) const @@ -443,21 +443,21 @@ void ARM32ABI::set_ret_value( }, ret_val); } -void ARM32ABI::prepare_ret_address(MaatEngine& engine, addr_t ret_addr) const +void ARM32EABI::prepare_ret_address(MaatEngine& engine, addr_t ret_addr) const { // Push the return address, simply engine.cpu.ctx().set(ARM32::PC, engine.cpu.ctx().get(ARM32::PC).as_uint() - 4); engine.mem->write(engine.cpu.ctx().get(ARM32::SP).as_uint(), ret_addr, 4); } -void ARM32ABI::ret(MaatEngine& engine) const +void ARM32EABI::ret(MaatEngine& engine) const { // Pop return address, SP (pop from the stack) engine.cpu.ctx().set(ARM32::PC, engine.mem->read((engine.cpu.ctx().get(ARM32::SP).as_uint()), 4)); engine.cpu.ctx().set(ARM32::SP, engine.cpu.ctx().get(ARM32::SP).as_uint() + 4); } -/* ============== ABI ARM32 SYSCALL LINUX ==============*/ +/* ============== EABI ARM32 SYSCALL LINUX ==============*/ ARM32_SYSCALL::ARM32_SYSCALL(): ABI(Type::ARM32_SYSCALL) {} @@ -480,12 +480,12 @@ void ARM32_SYSCALL::get_args( Value ARM32_SYSCALL::get_arg(MaatEngine& engine, int n, size_t arg_size) const { - std::vector arg_regs{ARM32::R0,ARM32::R1,ARM32::R2,ARM32::R3,ARM32::R4,ARM32::R5,ARM32::R6,ARM32::R7, ARM32::R8}; + std::vector arg_regs{ARM32::R0,ARM32::R1,ARM32::R2,ARM32::R3,ARM32::R4,ARM32::R5,ARM32::R6}; Value res; arg_size = ABI::real_arg_size(engine, arg_size); if (n >= arg_regs.size()) { - throw env_exception("get_arg(): Linux ARM32 CS ABI supports only up to 9 arguments"); + throw env_exception("get_arg(): Linux ARM32 CS ABI supports only up to 7 arguments"); } else { @@ -499,7 +499,7 @@ void ARM32_SYSCALL::set_ret_value( const FunctionCallback::return_t& ret_val ) const { - // Return value in R3 and in R4 + // Return value in R0 std::visit(maat::util::overloaded{ [](std::monostate arg){return;}, // no return value [&engine](auto arg){engine.cpu.ctx().set(ARM32::R0, arg);} diff --git a/src/env/env.cpp b/src/env/env.cpp index f00e2f4a..253c94b8 100644 --- a/src/env/env.cpp +++ b/src/env/env.cpp @@ -18,7 +18,7 @@ abi::ABI* _get_default_abi(Arch::Type arch, OS os) else if (arch == Arch::Type::ARM32) { if (os == OS::LINUX) - return &abi::ARM32ABI::instance(); + return &abi::ARM32EABI::instance(); } return &abi::ABI_NONE::instance(); } diff --git a/src/env/env_linux.cpp b/src/env/env_linux.cpp index b71759e6..1ba78601 100644 --- a/src/env/env_linux.cpp +++ b/src/env/env_linux.cpp @@ -25,7 +25,7 @@ void LinuxEmulator::_init(Arch::Type arch) break; case Arch::Type::ARM32: _libraries.push_back(env::emulated::linux_ARM32_libc()); - _syscall_func_map = env::emulated::linux_x64_syscall_map(); + _syscall_func_map = env::emulated::linux_ARM32_syscall_map(); case Arch::Type::NONE: default: break; diff --git a/src/include/maat/callother.hpp b/src/include/maat/callother.hpp index 0e3e34e3..fe5477f1 100644 --- a/src/include/maat/callother.hpp +++ b/src/include/maat/callother.hpp @@ -65,6 +65,8 @@ enum class Id EVM_CREATE, EVM_SELFDESTRUCT, EVM_LOG, + // ARM32 + ARM32_SC, UNSUPPORTED }; diff --git a/src/include/maat/env/library.hpp b/src/include/maat/env/library.hpp index 96ee71eb..4c12e1f9 100644 --- a/src/include/maat/env/library.hpp +++ b/src/include/maat/env/library.hpp @@ -104,7 +104,7 @@ enum class Type /* ARM64 */ ARM64, /* ARM32 */ - ARM32ABI, + ARM32EABI, ARM32_SYSCALL, /* Custom */ X86_LINUX_CUSTOM_SYSCALL, ///< Used internally @@ -312,10 +312,10 @@ class X64_LINUX_SYSCALL : public ABI }; /// ARM32 defualt ABI -class ARM32ABI : public ABI +class ARM32EABI : public ABI { protected: - ARM32ABI(); + ARM32EABI(); public: /// ABI instance (singleton pattern) static ABI& instance(); diff --git a/src/third-party/sleigh/native/sleigh_interface.cpp b/src/third-party/sleigh/native/sleigh_interface.cpp index 7f60adad..3965351c 100644 --- a/src/third-party/sleigh/native/sleigh_interface.cpp +++ b/src/third-party/sleigh/native/sleigh_interface.cpp @@ -400,7 +400,8 @@ class TranslationContext // Needs to be here apparently but maybe we could tweak setData so we don't need to reset... m_sleigh->reset(&m_loader, &m_context_internal); - // If arch is arm32 bit then don't allow contextSet() (fixes low level error in ghidra) + // If arch is arm32 bit then don't allow contextSet() + // this fixes instructions such as mov lr, pc and other instructions that use context switching if (arch == Arch::Type::ARM32) { // Disable context setting for ARMv7 32-bit architecture diff --git a/tests/unit-tests/test_archARM32.cpp b/tests/unit-tests/test_archARM32.cpp index 207361a5..dc291edb 100644 --- a/tests/unit-tests/test_archARM32.cpp +++ b/tests/unit-tests/test_archARM32.cpp @@ -276,39 +276,44 @@ namespace test sym.mem->write_buffer(0x1010, (uint8_t*)code.c_str(), code.size()); sym.run_from(0x1000,4); - return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "1: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x1, "2: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "3: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "4: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "5: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "6: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "7: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "1: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x1, "2: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "3: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "4: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "5: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "6: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "98: ArchARM32: Failed to disassembly and/or execute add instruction"); code = string("\x00\x00\x00\xaa", 4); // b.ge #8 sym.mem->write_buffer(0x1008, (uint8_t*)code.c_str(), code.size()); sym.run_from(0x1000,4); - return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "8: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x2, "9: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "10: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "10: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "11: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "12: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "25: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "8: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x2, "9: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "10: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "10: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "11: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x0, "12: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x20000000, "99: ArchARM32: Failed to disassembly and/or execute add instruction"); code = string("\x0f\x00\x50\xe3", 4); // cmp r0, #15 sym.mem->write_buffer(0x1004, (uint8_t*)code.c_str(), code.size()); code = string("\x00\x00\x00\x0a", 4); // b.eq #8 sym.mem->write_buffer(0x1008, (uint8_t*)code.c_str(), code.size()); + code = string("\x04\x50\xa0\xe3", 4); // mov r5, #4 + sym.mem->write_buffer(0x1010, (uint8_t*)code.c_str(), code.size()); sym.run_from(0x1000,4); - return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "13: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x2, "14: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "15: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "16: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "17: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x1, "18: ArchARM64: failed to disassembly and/or execute Branch Conditional"); - return_val += _assert(sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x60000000, "25: ArchARM32: Failed to disassembly and/or execute add instruction"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R0).as_uint() == 0xf, "13: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::R5).as_uint() == 0x4, "14: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + + // test flags + sym.run_from(0x1000,2); + return_val += _assert( sym.cpu.ctx().get(ARM32::NF).as_uint() == 0x0, "15: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::VF).as_uint() == 0x0, "16: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CF).as_uint() == 0x1, "17: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::ZF).as_uint() == 0x1, "18: ArchARM32: failed to disassembly and/or execute Branch Conditional"); + return_val += _assert( sym.cpu.ctx().get(ARM32::CPSR).as_uint() == 0x60000000, "99: ArchARM32: Failed to disassembly and/or execute add instruction"); return return_val; } @@ -329,39 +334,43 @@ namespace test sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); sym.run_from(0x1000,1); - return_val += _assert((uint32_t)sym.mem->read(0x110000, 4).as_uint() == 0xDEADBEEF, "1: ArchARM64: failed to disassemble store and load instructions."); + return_val += _assert((uint32_t)sym.mem->read(0x110000, 4).as_uint() == 0xDEADBEEF, "1: ArchARM32: failed to disassemble store and load instructions."); code = string("\x00\x20\x11\xe4", 4); // ldr r2 [r1] sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); sym.run_from(0x1000,1); - return_val += _assert( sym.cpu.ctx().get(ARM32::R2).as_uint() == 0xDEADBEEF, "1: ArchARM64: failed to disassemble store and load instructions."); + return_val += _assert( sym.cpu.ctx().get(ARM32::R2).as_uint() == 0xDEADBEEF, "1: ArchARM32: failed to disassemble store and load instructions."); return return_val; } - unsigned int test_binary() - { + unsigned int test_systemcall(){ unsigned int return_val = 0; - MaatEngine sym = MaatEngine(Arch::Type::X64); - sym.load("tests/resources/simple_algo_2/crackmex86", - loader::Format::ELF64, - 0x100000, - {}, - {}, - {}, - {}, - {} - ); - Expr value = exprvar(64,"input"); + string code; + MaatEngine sym = MaatEngine(Arch::Type::ARM32, env::OS::LINUX); + sym.mem->map(0x1000,0x2000); + + // set registers + sym.cpu.ctx().set(ARM32::R0, exprcst(32,0x1500)); + sym.cpu.ctx().set(ARM32::R1, exprcst(32,0x40)); + sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x1500)); + sym.cpu.ctx().set(ARM32::R3, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R4, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R5, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R6, exprcst(32,0)); + sym.cpu.ctx().set(ARM32::R7, exprcst(32,5)); + + // /home/nathan/test_syscalls/example.txt + code = string("\x2f\x68\x6f\x6d\x65\x2f\x6e\x61\x74\x68\x61\x6e\x2f\x74\x65\x73\x74\x5f\x73\x79\x73\x63\x61\x6c\x6c\x73\x2f\x65\x78\x61\x6d\x70\x6c\x65\x2e\x74\x78\x74",38); + sym.mem->write_buffer(0x1500, (uint8_t*)code.c_str(), code.size()); + + code = string("\x00\x00\x00\xef",4); + sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); sym.settings.log_insts = true; - sym.cpu.ctx().set(X64::RDI, value); - sym.cpu.ctx().set(X64::RIP, exprcst(64,0x1011c9)); // transform - - sym.run(); + sym.run_from(0x1000,1); return return_val; } - } } @@ -385,9 +394,10 @@ void test_archARM32() { total += disass_sub(engine); total += disass_branch(engine); total += disass_store_load(engine); - total += test_THUMB(); - // total += test_binary(); + + // System calls aren't working + // total += test_systemcall(); // total += test_float(); cout << "\t" << total << "/" << total << green << "\tOK" << def << endl; From 9bc0ac69682a15f302312c1e7c51a2de32e018d8 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Thu, 12 Oct 2023 12:56:12 +1030 Subject: [PATCH 07/14] adding more obvious syscall warning --- src/engine/callother.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/callother.cpp b/src/engine/callother.cpp index 87dcf91c..728a75e2 100644 --- a/src/engine/callother.cpp +++ b/src/engine/callother.cpp @@ -1049,6 +1049,7 @@ The syscalls are untested and don't work */ void ARM32_SC_handler(MaatEngine& engine, const ir::Inst& inst, ir::ProcessedInst& pinst) { + engine.log.warning("SC is untested and might not work!!"); // Get syscall number const Value& sys_num = engine.cpu.ctx().get(ARM32::R7); if (sys_num.is_symbolic(*engine.vars)) From 81deb356a883f5e8ebfbfbf49853f117c23b2833 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Thu, 12 Oct 2023 12:57:16 +1030 Subject: [PATCH 08/14] adding more obvious syscall warning --- src/engine/callother.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/callother.cpp b/src/engine/callother.cpp index 728a75e2..514fe0d4 100644 --- a/src/engine/callother.cpp +++ b/src/engine/callother.cpp @@ -1049,7 +1049,7 @@ The syscalls are untested and don't work */ void ARM32_SC_handler(MaatEngine& engine, const ir::Inst& inst, ir::ProcessedInst& pinst) { - engine.log.warning("SC is untested and might not work!!"); + engine.log.warning("System Call is untested and might not work!!"); // Get syscall number const Value& sys_num = engine.cpu.ctx().get(ARM32::R7); if (sys_num.is_symbolic(*engine.vars)) From 0b6b4fb54b37aec6757c91dcc9ed66df3333f3fa Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Fri, 20 Oct 2023 13:52:44 +1030 Subject: [PATCH 09/14] got rid of syscall test & p information in tests --- tests/unit-tests/test_archARM32.cpp | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/tests/unit-tests/test_archARM32.cpp b/tests/unit-tests/test_archARM32.cpp index dc291edb..5274e271 100644 --- a/tests/unit-tests/test_archARM32.cpp +++ b/tests/unit-tests/test_archARM32.cpp @@ -345,32 +345,6 @@ namespace test return return_val; } - unsigned int test_systemcall(){ - unsigned int return_val = 0; - string code; - MaatEngine sym = MaatEngine(Arch::Type::ARM32, env::OS::LINUX); - sym.mem->map(0x1000,0x2000); - - // set registers - sym.cpu.ctx().set(ARM32::R0, exprcst(32,0x1500)); - sym.cpu.ctx().set(ARM32::R1, exprcst(32,0x40)); - sym.cpu.ctx().set(ARM32::R2, exprcst(32,0x1500)); - sym.cpu.ctx().set(ARM32::R3, exprcst(32,0)); - sym.cpu.ctx().set(ARM32::R4, exprcst(32,0)); - sym.cpu.ctx().set(ARM32::R5, exprcst(32,0)); - sym.cpu.ctx().set(ARM32::R6, exprcst(32,0)); - sym.cpu.ctx().set(ARM32::R7, exprcst(32,5)); - - // /home/nathan/test_syscalls/example.txt - code = string("\x2f\x68\x6f\x6d\x65\x2f\x6e\x61\x74\x68\x61\x6e\x2f\x74\x65\x73\x74\x5f\x73\x79\x73\x63\x61\x6c\x6c\x73\x2f\x65\x78\x61\x6d\x70\x6c\x65\x2e\x74\x78\x74",38); - sym.mem->write_buffer(0x1500, (uint8_t*)code.c_str(), code.size()); - - code = string("\x00\x00\x00\xef",4); - sym.mem->write_buffer(0x1000, (uint8_t*)code.c_str(), code.size()); - sym.settings.log_insts = true; - sym.run_from(0x1000,1); - return return_val; - } } } @@ -396,9 +370,5 @@ void test_archARM32() { total += disass_store_load(engine); total += test_THUMB(); - // System calls aren't working - // total += test_systemcall(); - - // total += test_float(); cout << "\t" << total << "/" << total << green << "\tOK" << def << endl; } \ No newline at end of file From 66bc9d77690c7f1d52dddc09d80c2af49302bc5f Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Fri, 20 Oct 2023 14:08:00 +1030 Subject: [PATCH 10/14] remove bashbuild script --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 85116d72..50d2c52a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,4 @@ cmake-build-*/ prefix/ CMakeLists.txt.user CMakeUserPresets.json -maat_state_* -bashbuild +maat_state_* \ No newline at end of file From cff8880224a2a751611acb47c8819490134bc0e7 Mon Sep 17 00:00:00 2001 From: Katastropic2431 Date: Wed, 1 Nov 2023 13:26:41 +1030 Subject: [PATCH 11/14] adding attribution to files I added --- src/arch/arch_ARM32.cpp | 6 ++++++ tests/unit-tests/test_archARM32.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/arch/arch_ARM32.cpp b/src/arch/arch_ARM32.cpp index b2943ca6..d43d55d2 100644 --- a/src/arch/arch_ARM32.cpp +++ b/src/arch/arch_ARM32.cpp @@ -1,3 +1,9 @@ +/* +Commonwealth of Australia represented by the Department of Defence + +Produced by Nathan Do, Student Intern at DSTG (Defence Science and Technology Group) +*/ + #include "maat/arch.hpp" #include "maat/exception.hpp" #include "maat/cpu.hpp" diff --git a/tests/unit-tests/test_archARM32.cpp b/tests/unit-tests/test_archARM32.cpp index 5274e271..b9ac66b3 100644 --- a/tests/unit-tests/test_archARM32.cpp +++ b/tests/unit-tests/test_archARM32.cpp @@ -1,3 +1,9 @@ +/* +Commonwealth of Australia represented by the Department of Defence + +Produced by Nathan Do, Student Intern at DSTG (Defence Science and Technology Group) +*/ + #include "maat/arch.hpp" #include "maat/varcontext.hpp" #include "maat/engine.hpp" From d372ca1fce9b3a93ec8050f8adee2623f84157d6 Mon Sep 17 00:00:00 2001 From: G0ne-Phishing Date: Wed, 13 Dec 2023 07:18:21 +1030 Subject: [PATCH 12/14] Merge with trailofbits/maat master From 2a901729bc03abf03b43b6f6f81ecf3b16cc98e8 Mon Sep 17 00:00:00 2001 From: G0ne-Phishing Date: Wed, 13 Dec 2023 07:37:33 +1030 Subject: [PATCH 13/14] Merge with Nathan Do's ARMv7 support repo. From d3239326994285e9a94be618d051c33d5c1ba72b Mon Sep 17 00:00:00 2001 From: G0ne-Phishing Date: Wed, 13 Dec 2023 07:38:12 +1030 Subject: [PATCH 14/14] Merge with Nathan Do's ARMv7 support repo.