From 2238e6c3ef12e69827538ef77cff015c3d3fb6ee Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 19 Nov 2022 21:44:06 +0000 Subject: [PATCH 1/6] externals: Update dynarmic to 7a926d689bcc1cc39dd26d5bba379dffcc6815a3 --- externals/dynarmic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/externals/dynarmic b/externals/dynarmic index 45bc7a82d..7a926d689 160000 --- a/externals/dynarmic +++ b/externals/dynarmic @@ -1 +1 @@ -Subproject commit 45bc7a82de5fab362ad01268a08e7eaa689ae2c2 +Subproject commit 7a926d689bcc1cc39dd26d5bba379dffcc6815a3 From f298278f372292f614889bfecd7eda343ea2920d Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 19 Nov 2022 21:54:21 +0000 Subject: [PATCH 2/6] arm/dynarmic: Initial implementation for instruction tick counts --- src/core/CMakeLists.txt | 2 ++ src/core/arm/dynarmic/arm_dynarmic.cpp | 4 ++++ src/core/arm/dynarmic/arm_tick_counts.cpp | 16 ++++++++++++++++ src/core/arm/dynarmic/arm_tick_counts.h | 13 +++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 src/core/arm/dynarmic/arm_tick_counts.cpp create mode 100644 src/core/arm/dynarmic/arm_tick_counts.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e1738e9f6..d57aef53e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -492,6 +492,8 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) arm/dynarmic/arm_dynarmic_cp15.h arm/dynarmic/arm_exclusive_monitor.cpp arm/dynarmic/arm_exclusive_monitor.h + arm/dynarmic/arm_tick_counts.cpp + arm/dynarmic/arm_tick_counts.h ) target_link_libraries(core PRIVATE dynarmic) endif() diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 09fdb99b5..eea63f07f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -11,6 +11,7 @@ #include "core/arm/dynarmic/arm_dynarmic.h" #include "core/arm/dynarmic/arm_dynarmic_cp15.h" #include "core/arm/dynarmic/arm_exclusive_monitor.h" +#include "core/arm/dynarmic/arm_tick_counts.h" #include "core/core.h" #include "core/core_timing.h" #include "core/gdbstub/gdbstub.h" @@ -161,6 +162,9 @@ public: s64 ticks = parent.GetTimer().GetDowncount(); return static_cast(ticks <= 0 ? 0 : ticks); } + std::uint64_t GetTicksForCode(bool is_thumb, VAddr, std::uint32_t instruction) override { + return Core::TicksForInstruction(is_thumb, instruction); + } ARM_Dynarmic& parent; Kernel::SVCContext svc_context; diff --git a/src/core/arm/dynarmic/arm_tick_counts.cpp b/src/core/arm/dynarmic/arm_tick_counts.cpp new file mode 100644 index 000000000..3a3af41f8 --- /dev/null +++ b/src/core/arm/dynarmic/arm_tick_counts.cpp @@ -0,0 +1,16 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" +#include "core/arm/dynarmic/arm_tick_counts.h" + +namespace Core { + +u64 TicksForInstruction(bool is_thumb, u32 instruction) { + (void)is_thumb; + (void)instruction; + return 1; +} + +} // namespace Core diff --git a/src/core/arm/dynarmic/arm_tick_counts.h b/src/core/arm/dynarmic/arm_tick_counts.h new file mode 100644 index 000000000..b6051522b --- /dev/null +++ b/src/core/arm/dynarmic/arm_tick_counts.h @@ -0,0 +1,13 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +namespace Core { + +u64 TicksForInstruction(bool is_thumb, u32 instruction); + +} // namespace Core From 7cae35024f0d3a74e424eae12596f6398f60a948 Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 19 Nov 2022 22:44:16 +0000 Subject: [PATCH 3/6] common: Add StringLiteral --- src/common/CMakeLists.txt | 1 + src/common/string_literal.h | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/common/string_literal.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 48914c960..e4f8b25e8 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -104,6 +104,7 @@ add_library(common STATIC serialization/boost_flat_set.h serialization/boost_small_vector.hpp serialization/boost_vector.hpp + string_literal.h string_util.cpp string_util.h swap.h diff --git a/src/common/string_literal.h b/src/common/string_literal.h new file mode 100644 index 000000000..cc148edda --- /dev/null +++ b/src/common/string_literal.h @@ -0,0 +1,24 @@ +// Copyright 2022 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +namespace Common { + +template +struct StringLiteral { + constexpr StringLiteral(const char (&str)[N]) { + std::copy_n(str, N, value); + } + + static constexpr std::size_t strlen = N - 1; + static constexpr std::size_t size = N; + + char value[N]; +}; + +} // namespace Common From 0f250bed89cd654cbfd4b1806eaf5ea6541edc1b Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 19 Nov 2022 23:04:25 +0000 Subject: [PATCH 4/6] arm_tick_counts: Skeleton implementation --- src/core/arm/dynarmic/arm_tick_counts.cpp | 345 +++++++++++++++++++++- 1 file changed, 343 insertions(+), 2 deletions(-) diff --git a/src/core/arm/dynarmic/arm_tick_counts.cpp b/src/core/arm/dynarmic/arm_tick_counts.cpp index 3a3af41f8..a497fdfad 100644 --- a/src/core/arm/dynarmic/arm_tick_counts.cpp +++ b/src/core/arm/dynarmic/arm_tick_counts.cpp @@ -2,14 +2,355 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_types.h" +#include "common/string_literal.h" #include "core/arm/dynarmic/arm_tick_counts.h" +namespace { + +template +constexpr u32 GetMatchingBitsFromStringLiteral() { + u32 result = 0; + for (size_t i = 0; i < haystack.strlen; i++) { + for (size_t a = 0; a < needle.strlen; a++) { + if (haystack.value[i] == needle.value[a]) { + result |= 1 << (haystack.strlen - 1 - i); + } + } + } + return result; +} + +template +constexpr u32 DepositBits(u32 val) { + u32 mask = mask_; + u32 res = 0; + for (u32 bb = 1; mask; bb += bb) { + if (val & bb) + res |= mask & -mask; + mask &= mask - 1; + } + return res; +} + +template +struct MatcherArg { + template + u32 Get() { + return DepositBits()>(instruction); + } + + u32 instruction; +}; + +struct Matcher { + u32 mask; + u32 expect; + std::function fn; +}; + +#define INST(NAME, BS, CYCLES) \ + Matcher{GetMatchingBitsFromStringLiteral(), \ + GetMatchingBitsFromStringLiteral(), \ + std::function{[](u32 instruction) -> u64 { \ + [[maybe_unused]] MatcherArg i{instruction}; \ + return (CYCLES); \ + }}}, + +const std::array arm_matchers{ + // clang-format off + + // Branch instructions + INST("BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v5 + INST("BLX (reg)", "cccc000100101111111111110011mmmm", (1)) // v5 + INST("B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 + INST("BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 + INST("BX", "cccc000100101111111111110001mmmm", (1)) // v4T + INST("BXJ", "cccc000100101111111111110010mmmm", (1)) // v5J + + // Coprocessor instructions + INST("CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM", (1)) // v2 (CDP2: v5) + INST("LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv", (1)) // v2 (LDC2: v5) + INST("MCR", "cccc1110ooo0NNNNttttppppooo1MMMM", (1)) // v2 (MCR2: v5) + INST("MCRR", "cccc11000100uuuuttttppppooooMMMM", (1)) // v5E (MCRR2: v6) + INST("MRC", "cccc1110ooo1NNNNttttppppooo1MMMM", (1)) // v2 (MRC2: v5) + INST("MRRC", "cccc11000101uuuuttttppppooooMMMM", (1)) // v5E (MRRC2: v6) + INST("STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv", (1)) // v2 (STC2: v5) + + // Data Processing instructions + INST("ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv", (1)) // v1 + INST("CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm", (1)) // v1 + INST("CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm", (1)) // v1 + INST("CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv", (1)) // v1 + INST("CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm", (1)) // v1 + INST("CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm", (1)) // v1 + INST("EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv", (1)) // v1 + INST("MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm", (1)) // v1 + INST("MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm", (1)) // v1 + INST("MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv", (1)) // v1 + INST("MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm", (1)) // v1 + INST("MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm", (1)) // v1 + INST("ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv", (1)) // v1 + INST("SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm", (1)) // v1 + INST("SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm", (1)) // v1 + INST("TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv", (1)) // v1 + INST("TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm", (1)) // v1 + INST("TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm", (1)) // v1 + INST("TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv", (1)) // v1 + INST("TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm", (1)) // v1 + INST("TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm", (1)) // v1 + + // Exception Generating instructions + INST("BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv", (1)) // v5 + INST("SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 + INST("UDF", "111001111111------------1111----", (1)) + + // Extension instructions + INST("SXTB", "cccc011010101111ddddrr000111mmmm", (1)) // v6 + INST("SXTB16", "cccc011010001111ddddrr000111mmmm", (1)) // v6 + INST("SXTH", "cccc011010111111ddddrr000111mmmm", (1)) // v6 + INST("SXTAB", "cccc01101010nnnnddddrr000111mmmm", (1)) // v6 + INST("SXTAB16", "cccc01101000nnnnddddrr000111mmmm", (1)) // v6 + INST("SXTAH", "cccc01101011nnnnddddrr000111mmmm", (1)) // v6 + INST("UXTB", "cccc011011101111ddddrr000111mmmm", (1)) // v6 + INST("UXTB16", "cccc011011001111ddddrr000111mmmm", (1)) // v6 + INST("UXTH", "cccc011011111111ddddrr000111mmmm", (1)) // v6 + INST("UXTAB", "cccc01101110nnnnddddrr000111mmmm", (1)) // v6 + INST("UXTAB16", "cccc01101100nnnnddddrr000111mmmm", (1)) // v6 + INST("UXTAH", "cccc01101111nnnnddddrr000111mmmm", (1)) // v6 + + // Hint instructions + INST("PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii", (1)) // v5E for PLD; v7 for PLDW + INST("PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm", (1)) // v5E for PLD; v7 for PLDW + INST("SEV", "----0011001000001111000000000100", (1)) // v6K + INST("WFE", "----0011001000001111000000000010", (1)) // v6K + INST("WFI", "----0011001000001111000000000011", (1)) // v6K + INST("YIELD", "----0011001000001111000000000001", (1)) // v6K + + // Synchronization Primitive instructions + INST("CLREX", "11110101011111111111000000011111", (1)) // v6K + INST("SWP", "cccc00010000nnnntttt00001001uuuu", (1)) // v2S (v6: Deprecated) + INST("SWPB", "cccc00010100nnnntttt00001001uuuu", (1)) // v2S (v6: Deprecated) + INST("STREX", "cccc00011000nnnndddd11111001mmmm", (1)) // v6 + INST("LDREX", "cccc00011001nnnndddd111110011111", (1)) // v6 + INST("STREXD", "cccc00011010nnnndddd11111001mmmm", (1)) // v6K + INST("LDREXD", "cccc00011011nnnndddd111110011111", (1)) // v6K + INST("STREXB", "cccc00011100nnnndddd11111001mmmm", (1)) // v6K + INST("LDREXB", "cccc00011101nnnndddd111110011111", (1)) // v6K + INST("STREXH", "cccc00011110nnnndddd11111001mmmm", (1)) // v6K + INST("LDREXH", "cccc00011111nnnndddd111110011111", (1)) // v6K + + // Load/Store instructions + INST("LDRBT (A1)", "----0100-111--------------------", (1)) // v1 + INST("LDRBT (A2)", "----0110-111---------------0----", (1)) // v1 + INST("LDRT (A1)", "----0100-011--------------------", (1)) // v1 + INST("LDRT (A2)", "----0110-011---------------0----", (1)) // v1 + INST("STRBT (A1)", "----0100-110--------------------", (1)) // v1 + INST("STRBT (A2)", "----0110-110---------------0----", (1)) // v1 + INST("STRT (A1)", "----0100-010--------------------", (1)) // v1 + INST("STRT (A2)", "----0110-010---------------0----", (1)) // v1 + INST("LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv", (1)) // v1 + INST("LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv", (1)) // v1 + INST("LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm", (1)) // v1 + INST("LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv", (1)) // v1 + INST("LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv", (1)) // v1 + INST("LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm", (1)) // v1 + INST("LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv", (1)) // v5E + INST("LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv", (1)) // v5E + INST("LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm", (1)) // v5E + INST("LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv", (1)) // v4 + INST("LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv", (1)) // v4 + INST("LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm", (1)) // v4 + INST("LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv", (1)) // v4 + INST("LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv", (1)) // v4 + INST("LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm", (1)) // v4 + INST("LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv", (1)) // v4 + INST("LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv", (1)) // v4 + INST("LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm", (1)) // v4 + INST("STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv", (1)) // v1 + INST("STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm", (1)) // v1 + INST("STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv", (1)) // v1 + INST("STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm", (1)) // v1 + INST("STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv", (1)) // v5E + INST("STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm", (1)) // v5E + INST("STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv", (1)) // v4 + INST("STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm", (1)) // v4 + + // Load/Store Multiple instructions + INST("LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("LDM (usr reg)", "----100--101--------------------", (1)) // v1 + INST("LDM (exce ret)", "----100--1-1----1---------------", (1)) // v1 + INST("STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 + INST("STM (usr reg)", "----100--100--------------------", (1)) // v1 + + // Miscellaneous instructions + INST("CLZ", "cccc000101101111dddd11110001mmmm", (1)) // v5 + INST("NOP", "----0011001000001111000000000000", (1)) // v6K + INST("SEL", "cccc01101000nnnndddd11111011mmmm", (1)) // v6 + + // Unsigned Sum of Absolute Differences instructions + INST("USAD8", "cccc01111000dddd1111mmmm0001nnnn", (1)) // v6 + INST("USADA8", "cccc01111000ddddaaaammmm0001nnnn", (1)) // v6 + + // Packing instructions + INST("PKHBT", "cccc01101000nnnnddddvvvvv001mmmm", (1)) // v6K + INST("PKHTB", "cccc01101000nnnnddddvvvvv101mmmm", (1)) // v6K + + // Reversal instructions + INST("REV", "cccc011010111111dddd11110011mmmm", (1)) // v6 + INST("REV16", "cccc011010111111dddd11111011mmmm", (1)) // v6 + INST("REVSH", "cccc011011111111dddd11111011mmmm", (1)) // v6 + + // Saturation instructions + INST("SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn", (1)) // v6 + INST("SSAT16", "cccc01101010vvvvdddd11110011nnnn", (1)) // v6 + INST("USAT", "cccc0110111vvvvvddddvvvvvr01nnnn", (1)) // v6 + INST("USAT16", "cccc01101110vvvvdddd11110011nnnn", (1)) // v6 + + // Multiply (Normal) instructions + INST("MLA", "cccc0000001Sddddaaaammmm1001nnnn", (1)) // v2 + INST("MUL", "cccc0000000Sdddd0000mmmm1001nnnn", (1)) // v2 + + // Multiply (Long) instructions + INST("SMLAL", "cccc0000111Sddddaaaammmm1001nnnn", (1)) // v3M + INST("SMULL", "cccc0000110Sddddaaaammmm1001nnnn", (1)) // v3M + INST("UMAAL", "cccc00000100ddddaaaammmm1001nnnn", (1)) // v6 + INST("UMLAL", "cccc0000101Sddddaaaammmm1001nnnn", (1)) // v3M + INST("UMULL", "cccc0000100Sddddaaaammmm1001nnnn", (1)) // v3M + + // Multiply (Halfword) instructions + INST("SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn", (1)) // v5xP + INST("SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn", (1)) // v5xP + INST("SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn", (1)) // v5xP + + // Multiply (Word by Halfword) instructions + INST("SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn", (1)) // v5xP + INST("SMULWY", "cccc00010010dddd0000mmmm1y10nnnn", (1)) // v5xP + + // Multiply (Most Significant Word) instructions + INST("SMMUL", "cccc01110101dddd1111mmmm00R1nnnn", (1)) // v6 + INST("SMMLA", "cccc01110101ddddaaaammmm00R1nnnn", (1)) // v6 + INST("SMMLS", "cccc01110101ddddaaaammmm11R1nnnn", (1)) // v6 + + // Multiply (Dual) instructions + INST("SMLAD", "cccc01110000ddddaaaammmm00M1nnnn", (1)) // v6 + INST("SMLALD", "cccc01110100ddddaaaammmm00M1nnnn", (1)) // v6 + INST("SMLSD", "cccc01110000ddddaaaammmm01M1nnnn", (1)) // v6 + INST("SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn", (1)) // v6 + INST("SMUAD", "cccc01110000dddd1111mmmm00M1nnnn", (1)) // v6 + INST("SMUSD", "cccc01110000dddd1111mmmm01M1nnnn", (1)) // v6 + + // Parallel Add/Subtract (Modulo) instructions + INST("SADD8", "cccc01100001nnnndddd11111001mmmm", (1)) // v6 + INST("SADD16", "cccc01100001nnnndddd11110001mmmm", (1)) // v6 + INST("SASX", "cccc01100001nnnndddd11110011mmmm", (1)) // v6 + INST("SSAX", "cccc01100001nnnndddd11110101mmmm", (1)) // v6 + INST("SSUB8", "cccc01100001nnnndddd11111111mmmm", (1)) // v6 + INST("SSUB16", "cccc01100001nnnndddd11110111mmmm", (1)) // v6 + INST("UADD8", "cccc01100101nnnndddd11111001mmmm", (1)) // v6 + INST("UADD16", "cccc01100101nnnndddd11110001mmmm", (1)) // v6 + INST("UASX", "cccc01100101nnnndddd11110011mmmm", (1)) // v6 + INST("USAX", "cccc01100101nnnndddd11110101mmmm", (1)) // v6 + INST("USUB8", "cccc01100101nnnndddd11111111mmmm", (1)) // v6 + INST("USUB16", "cccc01100101nnnndddd11110111mmmm", (1)) // v6 + + // Parallel Add/Subtract (Saturating) instructions + INST("QADD8", "cccc01100010nnnndddd11111001mmmm", (1)) // v6 + INST("QADD16", "cccc01100010nnnndddd11110001mmmm", (1)) // v6 + INST("QASX", "cccc01100010nnnndddd11110011mmmm", (1)) // v6 + INST("QSAX", "cccc01100010nnnndddd11110101mmmm", (1)) // v6 + INST("QSUB8", "cccc01100010nnnndddd11111111mmmm", (1)) // v6 + INST("QSUB16", "cccc01100010nnnndddd11110111mmmm", (1)) // v6 + INST("UQADD8", "cccc01100110nnnndddd11111001mmmm", (1)) // v6 + INST("UQADD16", "cccc01100110nnnndddd11110001mmmm", (1)) // v6 + INST("UQASX", "cccc01100110nnnndddd11110011mmmm", (1)) // v6 + INST("UQSAX", "cccc01100110nnnndddd11110101mmmm", (1)) // v6 + INST("UQSUB8", "cccc01100110nnnndddd11111111mmmm", (1)) // v6 + INST("UQSUB16", "cccc01100110nnnndddd11110111mmmm", (1)) // v6 + + // Parallel Add/Subtract (Halving) instructions + INST("SHADD8", "cccc01100011nnnndddd11111001mmmm", (1)) // v6 + INST("SHADD16", "cccc01100011nnnndddd11110001mmmm", (1)) // v6 + INST("SHASX", "cccc01100011nnnndddd11110011mmmm", (1)) // v6 + INST("SHSAX", "cccc01100011nnnndddd11110101mmmm", (1)) // v6 + INST("SHSUB8", "cccc01100011nnnndddd11111111mmmm", (1)) // v6 + INST("SHSUB16", "cccc01100011nnnndddd11110111mmmm", (1)) // v6 + INST("UHADD8", "cccc01100111nnnndddd11111001mmmm", (1)) // v6 + INST("UHADD16", "cccc01100111nnnndddd11110001mmmm", (1)) // v6 + INST("UHASX", "cccc01100111nnnndddd11110011mmmm", (1)) // v6 + INST("UHSAX", "cccc01100111nnnndddd11110101mmmm", (1)) // v6 + INST("UHSUB8", "cccc01100111nnnndddd11111111mmmm", (1)) // v6 + INST("UHSUB16", "cccc01100111nnnndddd11110111mmmm", (1)) // v6 + + // Saturated Add/Subtract instructions + INST("QADD", "cccc00010000nnnndddd00000101mmmm", (1)) // v5xP + INST("QSUB", "cccc00010010nnnndddd00000101mmmm", (1)) // v5xP + INST("QDADD", "cccc00010100nnnndddd00000101mmmm", (1)) // v5xP + INST("QDSUB", "cccc00010110nnnndddd00000101mmmm", (1)) // v5xP + + // Status Register Access instructions + INST("CPS", "111100010000---00000000---0-----", (1)) // v6 + INST("SETEND", "1111000100000001000000e000000000", (1)) // v6 + INST("MRS", "cccc000100001111dddd000000000000", (1)) // v3 + INST("MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv", (1)) // v3 + INST("MSR (reg)", "cccc00010010mmmm111100000000nnnn", (1)) // v3 + INST("RFE", "1111100--0-1----0000101000000000", (1)) // v6 + INST("SRS", "1111100--1-0110100000101000-----", (1)) // v6 + + // clang-format on +}; + +} // namespace + namespace Core { u64 TicksForInstruction(bool is_thumb, u32 instruction) { - (void)is_thumb; - (void)instruction; + if (is_thumb) { + return 1; + } + + const auto matches_instruction = [instruction](const auto& matcher) { + return (instruction & matcher.mask) == matcher.expect; + }; + + auto iter = std::find_if(arm_matchers.begin(), arm_matchers.end(), matches_instruction); + if (iter != arm_matchers.end()) { + return iter->fn(instruction); + } return 1; } From 9c0fad21dbb0704be0c4a19442271250d527f57a Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 19 Nov 2022 23:54:18 +0000 Subject: [PATCH 5/6] arm_tick_counts: Implement ARM cycle counting --- src/core/arm/dynarmic/arm_tick_counts.cpp | 475 ++++++++++++---------- 1 file changed, 255 insertions(+), 220 deletions(-) diff --git a/src/core/arm/dynarmic/arm_tick_counts.cpp b/src/core/arm/dynarmic/arm_tick_counts.cpp index a497fdfad..6c8c33f82 100644 --- a/src/core/arm/dynarmic/arm_tick_counts.cpp +++ b/src/core/arm/dynarmic/arm_tick_counts.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include "common/common_types.h" #include "common/string_literal.h" @@ -50,6 +51,40 @@ struct Matcher { std::function fn; }; +u64 DataProcessing_imm(auto i) { + if (i.template Get<"d">() == 15) { + return 7; + } + return 1; +} +u64 DataProcessing_reg(auto i) { + if (i.template Get<"d">() == 15) { + return 7; + } + return 1; +} +u64 DataProcessing_rsr(auto i) { + if (i.template Get<"d">() == 15) { + return 8; + } + return 2; +} +u64 LoadStoreSingle_imm(auto) { + return 2; +} +u64 LoadStoreSingle_reg(auto i) { + // TODO: Load PC + if (i.template Get<"u">() == 1 && i.template Get<"r">() == 0 && + (i.template Get<"v">() == 0 || i.template Get<"v">() == 2)) { + return 2; + } + return 4; +} +u64 LoadStoreMultiple(auto i) { + // TODO: Load PC + return 1 + std::popcount(i.template Get<"x">()) / 2; +} + #define INST(NAME, BS, CYCLES) \ Matcher{GetMatchingBitsFromStringLiteral(), \ GetMatchingBitsFromStringLiteral(), \ @@ -62,274 +97,274 @@ const std::array arm_matchers{ // clang-format off // Branch instructions - INST("BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v5 - INST("BLX (reg)", "cccc000100101111111111110011mmmm", (1)) // v5 - INST("B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 - INST("BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 - INST("BX", "cccc000100101111111111110001mmmm", (1)) // v4T - INST("BXJ", "cccc000100101111111111110010mmmm", (1)) // v5J + INST("BLX (imm)", "1111101hvvvvvvvvvvvvvvvvvvvvvvvv", 5) // v5 + INST("BLX (reg)", "cccc000100101111111111110011mmmm", 6) // v5 + INST("B", "cccc1010vvvvvvvvvvvvvvvvvvvvvvvv", 4) // v1 + INST("BL", "cccc1011vvvvvvvvvvvvvvvvvvvvvvvv", 4) // v1 + INST("BX", "cccc000100101111111111110001mmmm", 5) // v4T + INST("BXJ", "cccc000100101111111111110010mmmm", 1) // v5J // Coprocessor instructions - INST("CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM", (1)) // v2 (CDP2: v5) - INST("LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv", (1)) // v2 (LDC2: v5) - INST("MCR", "cccc1110ooo0NNNNttttppppooo1MMMM", (1)) // v2 (MCR2: v5) - INST("MCRR", "cccc11000100uuuuttttppppooooMMMM", (1)) // v5E (MCRR2: v6) - INST("MRC", "cccc1110ooo1NNNNttttppppooo1MMMM", (1)) // v2 (MRC2: v5) - INST("MRRC", "cccc11000101uuuuttttppppooooMMMM", (1)) // v5E (MRRC2: v6) - INST("STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv", (1)) // v2 (STC2: v5) + INST("CDP", "cccc1110ooooNNNNDDDDppppooo0MMMM", 1) // v2 (CDP2: v5) + INST("LDC", "cccc110pudw1nnnnDDDDppppvvvvvvvv", 1) // v2 (LDC2: v5) + INST("MCR", "cccc1110ooo0NNNNttttppppooo1MMMM", 2) // v2 (MCR2: v5) + INST("MCRR", "cccc11000100uuuuttttppppooooMMMM", 2) // v5E (MCRR2: v6) + INST("MRC", "cccc1110ooo1NNNNttttppppooo1MMMM", 2) // v2 (MRC2: v5) + INST("MRRC", "cccc11000101uuuuttttppppooooMMMM", 2) // v5E (MRRC2: v6) + INST("STC", "cccc110pudw0nnnnDDDDppppvvvvvvvv", 1) // v2 (STC2: v5) // Data Processing instructions - INST("ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv", (1)) // v1 - INST("CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm", (1)) // v1 - INST("CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm", (1)) // v1 - INST("CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv", (1)) // v1 - INST("CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm", (1)) // v1 - INST("CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm", (1)) // v1 - INST("EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv", (1)) // v1 - INST("MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm", (1)) // v1 - INST("MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm", (1)) // v1 - INST("MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv", (1)) // v1 - INST("MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm", (1)) // v1 - INST("MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm", (1)) // v1 - INST("ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv", (1)) // v1 - INST("SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm", (1)) // v1 - INST("SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm", (1)) // v1 - INST("TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv", (1)) // v1 - INST("TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm", (1)) // v1 - INST("TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm", (1)) // v1 - INST("TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv", (1)) // v1 - INST("TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm", (1)) // v1 - INST("TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm", (1)) // v1 + INST("ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm", DataProcessing_rsr(i)) // v1 + INST("TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv", DataProcessing_imm(i)) // v1 + INST("TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm", DataProcessing_reg(i)) // v1 + INST("TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm", DataProcessing_rsr(i)) // v1 // Exception Generating instructions - INST("BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv", (1)) // v5 - INST("SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv", (1)) // v1 - INST("UDF", "111001111111------------1111----", (1)) + INST("BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv", 8) // v5 + INST("SVC", "cccc1111vvvvvvvvvvvvvvvvvvvvvvvv", 8) // v1 + INST("UDF", "111001111111------------1111----", 8) // Extension instructions - INST("SXTB", "cccc011010101111ddddrr000111mmmm", (1)) // v6 - INST("SXTB16", "cccc011010001111ddddrr000111mmmm", (1)) // v6 - INST("SXTH", "cccc011010111111ddddrr000111mmmm", (1)) // v6 - INST("SXTAB", "cccc01101010nnnnddddrr000111mmmm", (1)) // v6 - INST("SXTAB16", "cccc01101000nnnnddddrr000111mmmm", (1)) // v6 - INST("SXTAH", "cccc01101011nnnnddddrr000111mmmm", (1)) // v6 - INST("UXTB", "cccc011011101111ddddrr000111mmmm", (1)) // v6 - INST("UXTB16", "cccc011011001111ddddrr000111mmmm", (1)) // v6 - INST("UXTH", "cccc011011111111ddddrr000111mmmm", (1)) // v6 - INST("UXTAB", "cccc01101110nnnnddddrr000111mmmm", (1)) // v6 - INST("UXTAB16", "cccc01101100nnnnddddrr000111mmmm", (1)) // v6 - INST("UXTAH", "cccc01101111nnnnddddrr000111mmmm", (1)) // v6 + INST("SXTB", "cccc011010101111ddddrr000111mmmm", 1) // v6 + INST("SXTB16", "cccc011010001111ddddrr000111mmmm", 1) // v6 + INST("SXTH", "cccc011010111111ddddrr000111mmmm", 1) // v6 + INST("SXTAB", "cccc01101010nnnnddddrr000111mmmm", 1) // v6 + INST("SXTAB16", "cccc01101000nnnnddddrr000111mmmm", 1) // v6 + INST("SXTAH", "cccc01101011nnnnddddrr000111mmmm", 1) // v6 + INST("UXTB", "cccc011011101111ddddrr000111mmmm", 1) // v6 + INST("UXTB16", "cccc011011001111ddddrr000111mmmm", 1) // v6 + INST("UXTH", "cccc011011111111ddddrr000111mmmm", 1) // v6 + INST("UXTAB", "cccc01101110nnnnddddrr000111mmmm", 1) // v6 + INST("UXTAB16", "cccc01101100nnnnddddrr000111mmmm", 1) // v6 + INST("UXTAH", "cccc01101111nnnnddddrr000111mmmm", 1) // v6 // Hint instructions - INST("PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii", (1)) // v5E for PLD; v7 for PLDW - INST("PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm", (1)) // v5E for PLD; v7 for PLDW - INST("SEV", "----0011001000001111000000000100", (1)) // v6K - INST("WFE", "----0011001000001111000000000010", (1)) // v6K - INST("WFI", "----0011001000001111000000000011", (1)) // v6K - INST("YIELD", "----0011001000001111000000000001", (1)) // v6K + INST("PLD (imm)", "11110101uz01nnnn1111iiiiiiiiiiii", 1) // v5E for PLD; v7 for PLDW + INST("PLD (reg)", "11110111uz01nnnn1111iiiiitt0mmmm", 1) // v5E for PLD; v7 for PLDW + INST("SEV", "----0011001000001111000000000100", 1) // v6K + INST("WFE", "----0011001000001111000000000010", 1) // v6K + INST("WFI", "----0011001000001111000000000011", 1) // v6K + INST("YIELD", "----0011001000001111000000000001", 1) // v6K // Synchronization Primitive instructions - INST("CLREX", "11110101011111111111000000011111", (1)) // v6K - INST("SWP", "cccc00010000nnnntttt00001001uuuu", (1)) // v2S (v6: Deprecated) - INST("SWPB", "cccc00010100nnnntttt00001001uuuu", (1)) // v2S (v6: Deprecated) - INST("STREX", "cccc00011000nnnndddd11111001mmmm", (1)) // v6 - INST("LDREX", "cccc00011001nnnndddd111110011111", (1)) // v6 - INST("STREXD", "cccc00011010nnnndddd11111001mmmm", (1)) // v6K - INST("LDREXD", "cccc00011011nnnndddd111110011111", (1)) // v6K - INST("STREXB", "cccc00011100nnnndddd11111001mmmm", (1)) // v6K - INST("LDREXB", "cccc00011101nnnndddd111110011111", (1)) // v6K - INST("STREXH", "cccc00011110nnnndddd11111001mmmm", (1)) // v6K - INST("LDREXH", "cccc00011111nnnndddd111110011111", (1)) // v6K + INST("CLREX", "11110101011111111111000000011111", 1) // v6K + INST("SWP", "cccc00010000nnnntttt00001001uuuu", 4) // v2S (v6: Deprecated) + INST("SWPB", "cccc00010100nnnntttt00001001uuuu", 4) // v2S (v6: Deprecated) + INST("STREX", "cccc00011000nnnndddd11111001mmmm", 2) // v6 + INST("LDREX", "cccc00011001nnnndddd111110011111", 2) // v6 + INST("STREXD", "cccc00011010nnnndddd11111001mmmm", 2) // v6K + INST("LDREXD", "cccc00011011nnnndddd111110011111", 2) // v6K + INST("STREXB", "cccc00011100nnnndddd11111001mmmm", 2) // v6K + INST("LDREXB", "cccc00011101nnnndddd111110011111", 2) // v6K + INST("STREXH", "cccc00011110nnnndddd11111001mmmm", 2) // v6K + INST("LDREXH", "cccc00011111nnnndddd111110011111", 2) // v6K // Load/Store instructions - INST("LDRBT (A1)", "----0100-111--------------------", (1)) // v1 - INST("LDRBT (A2)", "----0110-111---------------0----", (1)) // v1 - INST("LDRT (A1)", "----0100-011--------------------", (1)) // v1 - INST("LDRT (A2)", "----0110-011---------------0----", (1)) // v1 - INST("STRBT (A1)", "----0100-110--------------------", (1)) // v1 - INST("STRBT (A2)", "----0110-110---------------0----", (1)) // v1 - INST("STRT (A1)", "----0100-010--------------------", (1)) // v1 - INST("STRT (A2)", "----0110-010---------------0----", (1)) // v1 - INST("LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv", (1)) // v1 - INST("LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv", (1)) // v1 - INST("LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm", (1)) // v1 - INST("LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv", (1)) // v1 - INST("LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv", (1)) // v1 - INST("LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm", (1)) // v1 - INST("LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv", (1)) // v5E - INST("LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv", (1)) // v5E - INST("LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm", (1)) // v5E - INST("LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv", (1)) // v4 - INST("LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv", (1)) // v4 - INST("LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm", (1)) // v4 - INST("LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv", (1)) // v4 - INST("LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv", (1)) // v4 - INST("LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm", (1)) // v4 - INST("LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv", (1)) // v4 - INST("LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv", (1)) // v4 - INST("LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm", (1)) // v4 - INST("STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv", (1)) // v1 - INST("STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm", (1)) // v1 - INST("STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv", (1)) // v1 - INST("STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm", (1)) // v1 - INST("STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv", (1)) // v5E - INST("STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm", (1)) // v5E - INST("STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv", (1)) // v4 - INST("STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm", (1)) // v4 + INST("LDRBT (A1)", "----0100-111--------------------", 1) // v1 + INST("LDRBT (A2)", "----0110-111---------------0----", 1) // v1 + INST("LDRT (A1)", "----0100-011--------------------", 1) // v1 + INST("LDRT (A2)", "----0110-011---------------0----", 1) // v1 + INST("STRBT (A1)", "----0100-110--------------------", 1) // v1 + INST("STRBT (A2)", "----0110-110---------------0----", 1) // v1 + INST("STRT (A1)", "----0100-010--------------------", 1) // v1 + INST("STRT (A2)", "----0110-010---------------0----", 1) // v1 + INST("LDR (lit)", "cccc0101u0011111ttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("LDR (imm)", "cccc010pu0w1nnnnttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("LDR (reg)", "cccc011pu0w1nnnnttttvvvvvrr0mmmm", LoadStoreSingle_reg(i)) // v1 + INST("LDRB (lit)", "cccc0101u1011111ttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("LDRB (imm)", "cccc010pu1w1nnnnttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("LDRB (reg)", "cccc011pu1w1nnnnttttvvvvvrr0mmmm", LoadStoreSingle_reg(i)) // v1 + INST("LDRD (lit)", "cccc0001u1001111ttttvvvv1101vvvv", LoadStoreSingle_imm(i)) // v5E + INST("LDRD (imm)", "cccc000pu1w0nnnnttttvvvv1101vvvv", LoadStoreSingle_imm(i)) // v5E + INST("LDRD (reg)", "cccc000pu0w0nnnntttt00001101mmmm", LoadStoreSingle_reg(i)) // v5E + INST("LDRH (lit)", "cccc000pu1w11111ttttvvvv1011vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRH (imm)", "cccc000pu1w1nnnnttttvvvv1011vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRH (reg)", "cccc000pu0w1nnnntttt00001011mmmm", LoadStoreSingle_reg(i)) // v4 + INST("LDRSB (lit)", "cccc0001u1011111ttttvvvv1101vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRSB (imm)", "cccc000pu1w1nnnnttttvvvv1101vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRSB (reg)", "cccc000pu0w1nnnntttt00001101mmmm", LoadStoreSingle_reg(i)) // v4 + INST("LDRSH (lit)", "cccc0001u1011111ttttvvvv1111vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRSH (imm)", "cccc000pu1w1nnnnttttvvvv1111vvvv", LoadStoreSingle_imm(i)) // v4 + INST("LDRSH (reg)", "cccc000pu0w1nnnntttt00001111mmmm", LoadStoreSingle_reg(i)) // v4 + INST("STR (imm)", "cccc010pu0w0nnnnttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("STR (reg)", "cccc011pu0w0nnnnttttvvvvvrr0mmmm", LoadStoreSingle_reg(i)) // v1 + INST("STRB (imm)", "cccc010pu1w0nnnnttttvvvvvvvvvvvv", LoadStoreSingle_imm(i)) // v1 + INST("STRB (reg)", "cccc011pu1w0nnnnttttvvvvvrr0mmmm", LoadStoreSingle_reg(i)) // v1 + INST("STRD (imm)", "cccc000pu1w0nnnnttttvvvv1111vvvv", LoadStoreSingle_imm(i)) // v5E + INST("STRD (reg)", "cccc000pu0w0nnnntttt00001111mmmm", LoadStoreSingle_reg(i)) // v5E + INST("STRH (imm)", "cccc000pu1w0nnnnttttvvvv1011vvvv", LoadStoreSingle_imm(i)) // v4 + INST("STRH (reg)", "cccc000pu0w0nnnntttt00001011mmmm", LoadStoreSingle_reg(i)) // v4 // Load/Store Multiple instructions - INST("LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("LDM (usr reg)", "----100--101--------------------", (1)) // v1 - INST("LDM (exce ret)", "----100--1-1----1---------------", (1)) // v1 - INST("STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx", (1)) // v1 - INST("STM (usr reg)", "----100--100--------------------", (1)) // v1 + INST("LDM", "cccc100010w1nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("LDMDA", "cccc100000w1nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("LDMDB", "cccc100100w1nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("LDMIB", "cccc100110w1nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("LDM (usr reg)", "----100--101--------------------", 1) // v1 + INST("LDM (exce ret)", "----100--1-1----1---------------", 1) // v1 + INST("STM", "cccc100010w0nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("STMDA", "cccc100000w0nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("STMDB", "cccc100100w0nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("STMIB", "cccc100110w0nnnnxxxxxxxxxxxxxxxx", LoadStoreMultiple(i)) // v1 + INST("STM (usr reg)", "----100--100--------------------", 1) // v1 // Miscellaneous instructions - INST("CLZ", "cccc000101101111dddd11110001mmmm", (1)) // v5 - INST("NOP", "----0011001000001111000000000000", (1)) // v6K - INST("SEL", "cccc01101000nnnndddd11111011mmmm", (1)) // v6 + INST("CLZ", "cccc000101101111dddd11110001mmmm", 1) // v5 + INST("NOP", "----0011001000001111000000000000", 1) // v6K + INST("SEL", "cccc01101000nnnndddd11111011mmmm", 1) // v6 // Unsigned Sum of Absolute Differences instructions - INST("USAD8", "cccc01111000dddd1111mmmm0001nnnn", (1)) // v6 - INST("USADA8", "cccc01111000ddddaaaammmm0001nnnn", (1)) // v6 + INST("USAD8", "cccc01111000dddd1111mmmm0001nnnn", 1) // v6 + INST("USADA8", "cccc01111000ddddaaaammmm0001nnnn", 1) // v6 // Packing instructions - INST("PKHBT", "cccc01101000nnnnddddvvvvv001mmmm", (1)) // v6K - INST("PKHTB", "cccc01101000nnnnddddvvvvv101mmmm", (1)) // v6K + INST("PKHBT", "cccc01101000nnnnddddvvvvv001mmmm", 1) // v6K + INST("PKHTB", "cccc01101000nnnnddddvvvvv101mmmm", 1) // v6K // Reversal instructions - INST("REV", "cccc011010111111dddd11110011mmmm", (1)) // v6 - INST("REV16", "cccc011010111111dddd11111011mmmm", (1)) // v6 - INST("REVSH", "cccc011011111111dddd11111011mmmm", (1)) // v6 + INST("REV", "cccc011010111111dddd11110011mmmm", 1) // v6 + INST("REV16", "cccc011010111111dddd11111011mmmm", 1) // v6 + INST("REVSH", "cccc011011111111dddd11111011mmmm", 1) // v6 // Saturation instructions - INST("SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn", (1)) // v6 - INST("SSAT16", "cccc01101010vvvvdddd11110011nnnn", (1)) // v6 - INST("USAT", "cccc0110111vvvvvddddvvvvvr01nnnn", (1)) // v6 - INST("USAT16", "cccc01101110vvvvdddd11110011nnnn", (1)) // v6 + INST("SSAT", "cccc0110101vvvvvddddvvvvvr01nnnn", 1) // v6 + INST("SSAT16", "cccc01101010vvvvdddd11110011nnnn", 1) // v6 + INST("USAT", "cccc0110111vvvvvddddvvvvvr01nnnn", 1) // v6 + INST("USAT16", "cccc01101110vvvvdddd11110011nnnn", 1) // v6 // Multiply (Normal) instructions - INST("MLA", "cccc0000001Sddddaaaammmm1001nnnn", (1)) // v2 - INST("MUL", "cccc0000000Sdddd0000mmmm1001nnnn", (1)) // v2 + INST("MLA", "cccc0000001Sddddaaaammmm1001nnnn", (i.template Get<"S">() ? 5 : 2)) // v2 + INST("MUL", "cccc0000000Sdddd0000mmmm1001nnnn", (i.template Get<"S">() ? 5 : 2)) // v2 // Multiply (Long) instructions - INST("SMLAL", "cccc0000111Sddddaaaammmm1001nnnn", (1)) // v3M - INST("SMULL", "cccc0000110Sddddaaaammmm1001nnnn", (1)) // v3M - INST("UMAAL", "cccc00000100ddddaaaammmm1001nnnn", (1)) // v6 - INST("UMLAL", "cccc0000101Sddddaaaammmm1001nnnn", (1)) // v3M - INST("UMULL", "cccc0000100Sddddaaaammmm1001nnnn", (1)) // v3M + INST("SMLAL", "cccc0000111Sddddaaaammmm1001nnnn", (i.template Get<"S">() ? 6 : 3)) // v3M + INST("SMULL", "cccc0000110Sddddaaaammmm1001nnnn", (i.template Get<"S">() ? 6 : 3)) // v3M + INST("UMAAL", "cccc00000100ddddaaaammmm1001nnnn", 3) // v6 + INST("UMLAL", "cccc0000101Sddddaaaammmm1001nnnn", (i.template Get<"S">() ? 6 : 3)) // v3M + INST("UMULL", "cccc0000100Sddddaaaammmm1001nnnn", (i.template Get<"S">() ? 6 : 3)) // v3M // Multiply (Halfword) instructions - INST("SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn", (1)) // v5xP - INST("SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn", (1)) // v5xP - INST("SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn", (1)) // v5xP + INST("SMLALXY", "cccc00010100ddddaaaammmm1xy0nnnn", 2) // v5xP + INST("SMLAXY", "cccc00010000ddddaaaammmm1xy0nnnn", 1) // v5xP + INST("SMULXY", "cccc00010110dddd0000mmmm1xy0nnnn", 1) // v5xP // Multiply (Word by Halfword) instructions - INST("SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn", (1)) // v5xP - INST("SMULWY", "cccc00010010dddd0000mmmm1y10nnnn", (1)) // v5xP + INST("SMLAWY", "cccc00010010ddddaaaammmm1y00nnnn", 1) // v5xP + INST("SMULWY", "cccc00010010dddd0000mmmm1y10nnnn", 1) // v5xP // Multiply (Most Significant Word) instructions - INST("SMMUL", "cccc01110101dddd1111mmmm00R1nnnn", (1)) // v6 - INST("SMMLA", "cccc01110101ddddaaaammmm00R1nnnn", (1)) // v6 - INST("SMMLS", "cccc01110101ddddaaaammmm11R1nnnn", (1)) // v6 + INST("SMMUL", "cccc01110101dddd1111mmmm00R1nnnn", 2) // v6 + INST("SMMLA", "cccc01110101ddddaaaammmm00R1nnnn", 2) // v6 + INST("SMMLS", "cccc01110101ddddaaaammmm11R1nnnn", 2) // v6 // Multiply (Dual) instructions - INST("SMLAD", "cccc01110000ddddaaaammmm00M1nnnn", (1)) // v6 - INST("SMLALD", "cccc01110100ddddaaaammmm00M1nnnn", (1)) // v6 - INST("SMLSD", "cccc01110000ddddaaaammmm01M1nnnn", (1)) // v6 - INST("SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn", (1)) // v6 - INST("SMUAD", "cccc01110000dddd1111mmmm00M1nnnn", (1)) // v6 - INST("SMUSD", "cccc01110000dddd1111mmmm01M1nnnn", (1)) // v6 + INST("SMLAD", "cccc01110000ddddaaaammmm00M1nnnn", 2) // v6 + INST("SMLALD", "cccc01110100ddddaaaammmm00M1nnnn", 2) // v6 + INST("SMLSD", "cccc01110000ddddaaaammmm01M1nnnn", 2) // v6 + INST("SMLSLD", "cccc01110100ddddaaaammmm01M1nnnn", 2) // v6 + INST("SMUAD", "cccc01110000dddd1111mmmm00M1nnnn", 2) // v6 + INST("SMUSD", "cccc01110000dddd1111mmmm01M1nnnn", 2) // v6 // Parallel Add/Subtract (Modulo) instructions - INST("SADD8", "cccc01100001nnnndddd11111001mmmm", (1)) // v6 - INST("SADD16", "cccc01100001nnnndddd11110001mmmm", (1)) // v6 - INST("SASX", "cccc01100001nnnndddd11110011mmmm", (1)) // v6 - INST("SSAX", "cccc01100001nnnndddd11110101mmmm", (1)) // v6 - INST("SSUB8", "cccc01100001nnnndddd11111111mmmm", (1)) // v6 - INST("SSUB16", "cccc01100001nnnndddd11110111mmmm", (1)) // v6 - INST("UADD8", "cccc01100101nnnndddd11111001mmmm", (1)) // v6 - INST("UADD16", "cccc01100101nnnndddd11110001mmmm", (1)) // v6 - INST("UASX", "cccc01100101nnnndddd11110011mmmm", (1)) // v6 - INST("USAX", "cccc01100101nnnndddd11110101mmmm", (1)) // v6 - INST("USUB8", "cccc01100101nnnndddd11111111mmmm", (1)) // v6 - INST("USUB16", "cccc01100101nnnndddd11110111mmmm", (1)) // v6 + INST("SADD8", "cccc01100001nnnndddd11111001mmmm", 1) // v6 + INST("SADD16", "cccc01100001nnnndddd11110001mmmm", 1) // v6 + INST("SASX", "cccc01100001nnnndddd11110011mmmm", 1) // v6 + INST("SSAX", "cccc01100001nnnndddd11110101mmmm", 1) // v6 + INST("SSUB8", "cccc01100001nnnndddd11111111mmmm", 1) // v6 + INST("SSUB16", "cccc01100001nnnndddd11110111mmmm", 1) // v6 + INST("UADD8", "cccc01100101nnnndddd11111001mmmm", 1) // v6 + INST("UADD16", "cccc01100101nnnndddd11110001mmmm", 1) // v6 + INST("UASX", "cccc01100101nnnndddd11110011mmmm", 1) // v6 + INST("USAX", "cccc01100101nnnndddd11110101mmmm", 1) // v6 + INST("USUB8", "cccc01100101nnnndddd11111111mmmm", 1) // v6 + INST("USUB16", "cccc01100101nnnndddd11110111mmmm", 1) // v6 // Parallel Add/Subtract (Saturating) instructions - INST("QADD8", "cccc01100010nnnndddd11111001mmmm", (1)) // v6 - INST("QADD16", "cccc01100010nnnndddd11110001mmmm", (1)) // v6 - INST("QASX", "cccc01100010nnnndddd11110011mmmm", (1)) // v6 - INST("QSAX", "cccc01100010nnnndddd11110101mmmm", (1)) // v6 - INST("QSUB8", "cccc01100010nnnndddd11111111mmmm", (1)) // v6 - INST("QSUB16", "cccc01100010nnnndddd11110111mmmm", (1)) // v6 - INST("UQADD8", "cccc01100110nnnndddd11111001mmmm", (1)) // v6 - INST("UQADD16", "cccc01100110nnnndddd11110001mmmm", (1)) // v6 - INST("UQASX", "cccc01100110nnnndddd11110011mmmm", (1)) // v6 - INST("UQSAX", "cccc01100110nnnndddd11110101mmmm", (1)) // v6 - INST("UQSUB8", "cccc01100110nnnndddd11111111mmmm", (1)) // v6 - INST("UQSUB16", "cccc01100110nnnndddd11110111mmmm", (1)) // v6 + INST("QADD8", "cccc01100010nnnndddd11111001mmmm", 1) // v6 + INST("QADD16", "cccc01100010nnnndddd11110001mmmm", 1) // v6 + INST("QASX", "cccc01100010nnnndddd11110011mmmm", 1) // v6 + INST("QSAX", "cccc01100010nnnndddd11110101mmmm", 1) // v6 + INST("QSUB8", "cccc01100010nnnndddd11111111mmmm", 1) // v6 + INST("QSUB16", "cccc01100010nnnndddd11110111mmmm", 1) // v6 + INST("UQADD8", "cccc01100110nnnndddd11111001mmmm", 1) // v6 + INST("UQADD16", "cccc01100110nnnndddd11110001mmmm", 1) // v6 + INST("UQASX", "cccc01100110nnnndddd11110011mmmm", 1) // v6 + INST("UQSAX", "cccc01100110nnnndddd11110101mmmm", 1) // v6 + INST("UQSUB8", "cccc01100110nnnndddd11111111mmmm", 1) // v6 + INST("UQSUB16", "cccc01100110nnnndddd11110111mmmm", 1) // v6 // Parallel Add/Subtract (Halving) instructions - INST("SHADD8", "cccc01100011nnnndddd11111001mmmm", (1)) // v6 - INST("SHADD16", "cccc01100011nnnndddd11110001mmmm", (1)) // v6 - INST("SHASX", "cccc01100011nnnndddd11110011mmmm", (1)) // v6 - INST("SHSAX", "cccc01100011nnnndddd11110101mmmm", (1)) // v6 - INST("SHSUB8", "cccc01100011nnnndddd11111111mmmm", (1)) // v6 - INST("SHSUB16", "cccc01100011nnnndddd11110111mmmm", (1)) // v6 - INST("UHADD8", "cccc01100111nnnndddd11111001mmmm", (1)) // v6 - INST("UHADD16", "cccc01100111nnnndddd11110001mmmm", (1)) // v6 - INST("UHASX", "cccc01100111nnnndddd11110011mmmm", (1)) // v6 - INST("UHSAX", "cccc01100111nnnndddd11110101mmmm", (1)) // v6 - INST("UHSUB8", "cccc01100111nnnndddd11111111mmmm", (1)) // v6 - INST("UHSUB16", "cccc01100111nnnndddd11110111mmmm", (1)) // v6 + INST("SHADD8", "cccc01100011nnnndddd11111001mmmm", 1) // v6 + INST("SHADD16", "cccc01100011nnnndddd11110001mmmm", 1) // v6 + INST("SHASX", "cccc01100011nnnndddd11110011mmmm", 1) // v6 + INST("SHSAX", "cccc01100011nnnndddd11110101mmmm", 1) // v6 + INST("SHSUB8", "cccc01100011nnnndddd11111111mmmm", 1) // v6 + INST("SHSUB16", "cccc01100011nnnndddd11110111mmmm", 1) // v6 + INST("UHADD8", "cccc01100111nnnndddd11111001mmmm", 1) // v6 + INST("UHADD16", "cccc01100111nnnndddd11110001mmmm", 1) // v6 + INST("UHASX", "cccc01100111nnnndddd11110011mmmm", 1) // v6 + INST("UHSAX", "cccc01100111nnnndddd11110101mmmm", 1) // v6 + INST("UHSUB8", "cccc01100111nnnndddd11111111mmmm", 1) // v6 + INST("UHSUB16", "cccc01100111nnnndddd11110111mmmm", 1) // v6 // Saturated Add/Subtract instructions - INST("QADD", "cccc00010000nnnndddd00000101mmmm", (1)) // v5xP - INST("QSUB", "cccc00010010nnnndddd00000101mmmm", (1)) // v5xP - INST("QDADD", "cccc00010100nnnndddd00000101mmmm", (1)) // v5xP - INST("QDSUB", "cccc00010110nnnndddd00000101mmmm", (1)) // v5xP + INST("QADD", "cccc00010000nnnndddd00000101mmmm", 1) // v5xP + INST("QSUB", "cccc00010010nnnndddd00000101mmmm", 1) // v5xP + INST("QDADD", "cccc00010100nnnndddd00000101mmmm", 1) // v5xP + INST("QDSUB", "cccc00010110nnnndddd00000101mmmm", 1) // v5xP // Status Register Access instructions - INST("CPS", "111100010000---00000000---0-----", (1)) // v6 - INST("SETEND", "1111000100000001000000e000000000", (1)) // v6 - INST("MRS", "cccc000100001111dddd000000000000", (1)) // v3 - INST("MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv", (1)) // v3 - INST("MSR (reg)", "cccc00010010mmmm111100000000nnnn", (1)) // v3 - INST("RFE", "1111100--0-1----0000101000000000", (1)) // v6 - INST("SRS", "1111100--1-0110100000101000-----", (1)) // v6 + INST("CPS", "111100010000---00000000---0-----", 1) // v6 + INST("SETEND", "1111000100000001000000e000000000", 1) // v6 + INST("MRS", "cccc000100001111dddd000000000000", 1) // v3 + INST("MSR (imm)", "cccc00110010mmmm1111rrrrvvvvvvvv", (i.template Get<"m">() == 0b1000 ? 1 : 4)) // v3 + INST("MSR (reg)", "cccc00010010mmmm111100000000nnnn", (i.template Get<"m">() == 0b1000 ? 1 : 4)) // v3 + INST("RFE", "1111100--0-1----0000101000000000", 9) // v6 + INST("SRS", "1111100--1-0110100000101000-----", 1) // v6 // clang-format on }; From 6da59d581e124733ac47953f51c8b802ed18ef97 Mon Sep 17 00:00:00 2001 From: Merry Date: Mon, 21 Nov 2022 21:19:20 +0000 Subject: [PATCH 6/6] arm_tick_counts: Thumb implementation --- src/core/arm/dynarmic/arm_tick_counts.cpp | 98 +++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/core/arm/dynarmic/arm_tick_counts.cpp b/src/core/arm/dynarmic/arm_tick_counts.cpp index 6c8c33f82..59f91e9f7 100644 --- a/src/core/arm/dynarmic/arm_tick_counts.cpp +++ b/src/core/arm/dynarmic/arm_tick_counts.cpp @@ -369,6 +369,104 @@ const std::array arm_matchers{ // clang-format on }; +const std::array thumb_matchers{ + // clang-format off + + // Shift (immediate) add, subtract, move and compare instructions + INST("LSL (imm)", "00000vvvvvmmmddd", 1) + INST("LSR (imm)", "00001vvvvvmmmddd", 1) + INST("ASR (imm)", "00010vvvvvmmmddd", 1) + INST("ADD (reg, T1)", "0001100mmmnnnddd", 1) + INST("SUB (reg)", "0001101mmmnnnddd", 1) + INST("ADD (imm, T1)", "0001110vvvnnnddd", 1) + INST("SUB (imm, T1)", "0001111vvvnnnddd", 1) + INST("MOV (imm)", "00100dddvvvvvvvv", 1) + INST("CMP (imm)", "00101nnnvvvvvvvv", 1) + INST("ADD (imm, T2)", "00110dddvvvvvvvv", 1) + INST("SUB (imm, T2)", "00111dddvvvvvvvv", 1) + + // Data-processing instructions + INST("AND (reg)", "0100000000mmmddd", 1) + INST("EOR (reg)", "0100000001mmmddd", 1) + INST("LSL (reg)", "0100000010mmmddd", 1) + INST("LSR (reg)", "0100000011mmmddd", 1) + INST("ASR (reg)", "0100000100mmmddd", 1) + INST("ADC (reg)", "0100000101mmmddd", 1) + INST("SBC (reg)", "0100000110mmmddd", 1) + INST("ROR (reg)", "0100000111sssddd", 1) + INST("TST (reg)", "0100001000mmmnnn", 1) + INST("RSB (imm)", "0100001001nnnddd", 1) + INST("CMP (reg, T1)", "0100001010mmmnnn", 1) + INST("CMN (reg)", "0100001011mmmnnn", 1) + INST("ORR (reg)", "0100001100mmmddd", 1) + INST("MUL (reg)", "0100001101nnnddd", 1) + INST("BIC (reg)", "0100001110mmmddd", 1) + INST("MVN (reg)", "0100001111mmmddd", 1) + + // Special data instructions + INST("ADD (reg, T2)", "01000100Dmmmmddd", 1) // v4T, Low regs: v6T2 + INST("CMP (reg, T2)", "01000101Nmmmmnnn", 1) // v4T + INST("MOV (reg)", "01000110Dmmmmddd", 1) // v4T, Low regs: v6 + + // Store/Load single data item instructions + INST("LDR (literal)", "01001tttvvvvvvvv", 2) + INST("STR (reg)", "0101000mmmnnnttt", 2) + INST("STRH (reg)", "0101001mmmnnnttt", 2) + INST("STRB (reg)", "0101010mmmnnnttt", 2) + INST("LDRSB (reg)", "0101011mmmnnnttt", 2) + INST("LDR (reg)", "0101100mmmnnnttt", 2) + INST("LDRH (reg)", "0101101mmmnnnttt", 2) + INST("LDRB (reg)", "0101110mmmnnnttt", 2) + INST("LDRSH (reg)", "0101111mmmnnnttt", 2) + INST("STR (imm, T1)", "01100vvvvvnnnttt", 2) + INST("LDR (imm, T1)", "01101vvvvvnnnttt", 2) + INST("STRB (imm)", "01110vvvvvnnnttt", 2) + INST("LDRB (imm)", "01111vvvvvnnnttt", 2) + INST("STRH (imm)", "10000vvvvvnnnttt", 2) + INST("LDRH (imm)", "10001vvvvvnnnttt", 2) + INST("STR (imm, T2)", "10010tttvvvvvvvv", 2) + INST("LDR (imm, T2)", "10011tttvvvvvvvv", 2) + + // Generate relative address instructions + INST("ADR", "10100dddvvvvvvvv", 1) + INST("ADD (SP plus imm, T1)", "10101dddvvvvvvvv", 1) + INST("ADD (SP plus imm, T2)", "101100000vvvvvvv", 1) // v4T + INST("SUB (SP minus imm)", "101100001vvvvvvv", 1) // v4T + + // Hint instructions + INST("NOP", "10111111--------", (1)) // IT on v7 + + // Miscellaneous 16-bit instructions + INST("SXTH", "1011001000mmmddd", 1) // v6 + INST("SXTB", "1011001001mmmddd", 1) // v6 + INST("UXTH", "1011001010mmmddd", 1) // v6 + INST("UXTB", "1011001011mmmddd", 1) // v6 + INST("PUSH", "1011010xxxxxxxxx", LoadStoreMultiple(i)) // v4T + INST("POP", "1011110xxxxxxxxx", LoadStoreMultiple(i)) // v4T + INST("SETEND", "101101100101x000", 1) // v6 + INST("CPS", "10110110011m0aif", 1) // v6 + INST("REV", "1011101000mmmddd", 1) // v6 + INST("REV16", "1011101001mmmddd", 1) // v6 + INST("REVSH", "1011101011mmmddd", 1) // v6 + INST("BKPT", "10111110xxxxxxxx", 8) // v5 + + // Store/Load multiple registers + INST("STMIA", "11000nnnxxxxxxxx", LoadStoreMultiple(i)) + INST("LDMIA", "11001nnnxxxxxxxx", LoadStoreMultiple(i)) + + // Branch instructions + INST("BX", "010001110mmmm000", 5) // v4T + INST("BLX (reg)", "010001111mmmm000", 6) // v5T + INST("UDF", "11011110--------", 8) + INST("SVC", "11011111xxxxxxxx", 8) + INST("B (T1)", "1101ccccvvvvvvvv", 4) + INST("B (T2)", "11100vvvvvvvvvvv", 4) + INST("BL (imm)", "11110Svvvvvvvvvv11j1jvvvvvvvvvvv", 4) // v4T + INST("BLX (imm)", "11110Svvvvvvvvvv11j0jvvvvvvvvvvv", 5) // v5T + + // clang-format on +}; + } // namespace namespace Core {