From 8db4d65587a02c1714cd5d0ba5a8f4000ebd1cbb Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 19 Apr 2020 11:35:13 +0100 Subject: [PATCH] A64/decoder: Use a lookup table instead of doing a linear scan --- src/frontend/A64/decoder/a64.h | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/frontend/A64/decoder/a64.h b/src/frontend/A64/decoder/a64.h index 4ed0c98f..128141ff 100644 --- a/src/frontend/A64/decoder/a64.h +++ b/src/frontend/A64/decoder/a64.h @@ -24,14 +24,23 @@ template using Matcher = Decoder::Matcher; template -std::vector> GetDecodeTable() { - std::vector> table = { +using DecodeTable = std::array>, 0x1000>; + +namespace detail { +inline size_t ToFastLookupIndex(u32 instruction) { + return ((instruction >> 10) & 0x00F) | ((instruction >> 18) & 0xFF0); +} +} // namespace detail + +template +DecodeTable GetDecodeTable() { + std::vector> list = { #define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(&Visitor::fn, name, bitstring), #include "a64.inc" #undef INST }; - std::stable_sort(table.begin(), table.end(), [](const auto& matcher1, const auto& matcher2) { + std::stable_sort(list.begin(), list.end(), [](const auto& matcher1, const auto& matcher2) { // If a matcher has more bits in its mask it is more specific, so it should come first. return Common::BitCount(matcher1.GetMask()) > Common::BitCount(matcher2.GetMask()); }); @@ -43,10 +52,20 @@ std::vector> GetDecodeTable() { "Unallocated SIMD modified immediate", }; - std::stable_partition(table.begin(), table.end(), [&](const auto& matcher) { + std::stable_partition(list.begin(), list.end(), [&](const auto& matcher) { return comes_first.count(matcher.GetName()) > 0; }); + DecodeTable table{}; + for (size_t i = 0; i < table.size(); ++i) { + for (auto matcher : list) { + const auto expect = detail::ToFastLookupIndex(matcher.GetExpected()); + const auto mask = detail::ToFastLookupIndex(matcher.GetMask()); + if ((i & mask) == expect) { + table[i].push_back(matcher); + } + } + } return table; } @@ -56,8 +75,9 @@ std::optional>> Decode(u32 instruc const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); }; - auto iter = std::find_if(table.begin(), table.end(), matches_instruction); - return iter != table.end() ? std::optional>>(*iter) : std::nullopt; + const auto& subtable = table[detail::ToFastLookupIndex(instruction)]; + auto iter = std::find_if(subtable.begin(), subtable.end(), matches_instruction); + return iter != subtable.end() ? std::optional>>(*iter) : std::nullopt; } } // namespace Dynarmic::A64