/* This file is part of the dynarmic project. * Copyright (c) 2020 MerryMage * SPDX-License-Identifier: 0BSD */ #pragma once #include #include #include #include #include #include "common/bit_util.h" #include "common/common_types.h" #include "frontend/decoder/decoder_detail.h" #include "frontend/decoder/matcher.h" namespace Dynarmic::A32 { template using ASIMDMatcher = Decoder::Matcher; template std::vector> GetASIMDDecodeTable() { std::vector> table = { #define INST(fn, name, bitstring) Decoder::detail::detail>::GetMatcher(&V::fn, name, bitstring), #include "asimd.inc" #undef INST }; // Exceptions to the rule of thumb. const std::set comes_first{ "VBIC, VMOV, VMVN, VORR (immediate)", "VEXT", "VTBL", "VTBX", "VDUP (scalar)", }; const std::set comes_last{ "VMLA (scalar)", "VMLAL (scalar)", "VQDMLAL/VQDMLSL (scalar)", "VMUL (scalar)", "VMULL (scalar)", "VQDMULL (scalar)", "VQDMULH (scalar)", "VQRDMULH (scalar)", }; const auto sort_begin = std::stable_partition(table.begin(), table.end(), [&](const auto& matcher) { return comes_first.count(matcher.GetName()) > 0; }); const auto sort_end = std::stable_partition(table.begin(), table.end(), [&](const auto& matcher) { return comes_last.count(matcher.GetName()) == 0; }); // If a matcher has more bits in its mask it is more specific, so it should come first. std::stable_sort(sort_begin, sort_end, [](const auto& matcher1, const auto& matcher2) { return Common::BitCount(matcher1.GetMask()) > Common::BitCount(matcher2.GetMask()); }); return table; } template std::optional>> DecodeASIMD(u32 instruction) { static const auto table = GetASIMDDecodeTable(); 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; } } // namespace Dynarmic::A32