1 /* This file is part of the dynarmic project.
2  * Copyright (c) 2016 MerryMage
3  * SPDX-License-Identifier: 0BSD
4  *
5  * Original version of table by Lioncash.
6  */
7 
8 #pragma once
9 
10 #include <algorithm>
11 #include <functional>
12 #include <optional>
13 #include <vector>
14 
15 #include "common/bit_util.h"
16 #include "common/common_types.h"
17 #include "frontend/decoder/decoder_detail.h"
18 #include "frontend/decoder/matcher.h"
19 
20 namespace Dynarmic::A32 {
21 
22 template <typename Visitor>
23 using ArmMatcher = Decoder::Matcher<Visitor, u32>;
24 
25 template <typename V>
GetArmDecodeTable()26 std::vector<ArmMatcher<V>> GetArmDecodeTable() {
27     std::vector<ArmMatcher<V>> table = {
28 
29 #define INST(fn, name, bitstring) Decoder::detail::detail<ArmMatcher<V>>::GetMatcher(&V::fn, name, bitstring),
30 #ifdef ARCHITECTURE_Aarch64
31 #include "arm_a64.inc"
32 #else
33 #include "arm.inc"
34 #endif
35 #undef INST
36 
37     };
38 
39     // If a matcher has more bits in its mask it is more specific, so it should come first.
40     std::stable_sort(table.begin(), table.end(), [](const auto& matcher1, const auto& matcher2) {
41         return Common::BitCount(matcher1.GetMask()) > Common::BitCount(matcher2.GetMask());
42     });
43 
44     return table;
45 }
46 
47 template<typename V>
DecodeArm(u32 instruction)48 std::optional<std::reference_wrapper<const ArmMatcher<V>>> DecodeArm(u32 instruction) {
49     static const auto table = GetArmDecodeTable<V>();
50 
51     const auto matches_instruction = [instruction](const auto& matcher) { return matcher.Matches(instruction); };
52 
53     auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
54     return iter != table.end() ? std::optional<std::reference_wrapper<const ArmMatcher<V>>>(*iter) : std::nullopt;
55 }
56 
57 } // namespace Dynarmic::A32
58