decoder_detail: Simplify DYNARMIC_DECODER_GET_MATCHER

This commit is contained in:
Merry 2022-08-21 17:50:10 +01:00
parent a62dc19605
commit bf422a190a

View file

@ -17,7 +17,7 @@ namespace Dynarmic::Decoder {
namespace detail { namespace detail {
template<size_t N> template<size_t N>
inline constexpr std::array<char, N> StringToArray(const char (&str)[N + 1]) { inline consteval std::array<char, N> StringToArray(const char (&str)[N + 1]) {
std::array<char, N> result{}; std::array<char, N> result{};
for (size_t i = 0; i < N; i++) { for (size_t i = 0; i < N; i++) {
result[i] = str[i]; result[i] = str[i];
@ -42,7 +42,11 @@ struct detail {
* A '0' in a bitstring indicates that a zero must be present at that bit position. * A '0' in a bitstring indicates that a zero must be present at that bit position.
* A '1' in a bitstring indicates that a one must be present at that bit position. * A '1' in a bitstring indicates that a one must be present at that bit position.
*/ */
#ifdef __APPLE__ // AppleClang workaround
static constexpr auto GetMaskAndExpect(std::array<char, opcode_bitsize> bitstring) { static constexpr auto GetMaskAndExpect(std::array<char, opcode_bitsize> bitstring) {
#else
static consteval auto GetMaskAndExpect(std::array<char, opcode_bitsize> bitstring) {
#endif
const auto one = static_cast<opcode_type>(1); const auto one = static_cast<opcode_type>(1);
opcode_type mask = 0, expect = 0; opcode_type mask = 0, expect = 0;
for (size_t i = 0; i < opcode_bitsize; i++) { for (size_t i = 0; i < opcode_bitsize; i++) {
@ -69,7 +73,7 @@ struct detail {
* An argument is specified by a continuous string of the same character. * An argument is specified by a continuous string of the same character.
*/ */
template<size_t N> template<size_t N>
static constexpr auto GetArgInfo(std::array<char, opcode_bitsize> bitstring) { static consteval auto GetArgInfo(std::array<char, opcode_bitsize> bitstring) {
std::array<opcode_type, N> masks = {}; std::array<opcode_type, N> masks = {};
std::array<size_t, N> shifts = {}; std::array<size_t, N> shifts = {};
size_t arg_index = 0; size_t arg_index = 0;
@ -164,19 +168,23 @@ struct detail {
* Creates a matcher that can match and parse instructions based on bitstring. * Creates a matcher that can match and parse instructions based on bitstring.
* See also: GetMaskAndExpect and GetArgInfo for format of bitstring. * See also: GetMaskAndExpect and GetArgInfo for format of bitstring.
*/ */
template<typename FnT, size_t args_count = mcl::parameter_count_v<FnT>> template<auto bitstring, typename FnT>
static auto GetMatcher(FnT fn, const char* const name, std::tuple<opcode_type, opcode_type> mask_and_expect, std::tuple<std::array<opcode_type, args_count>, std::array<size_t, args_count>> masks_and_shifts) { static auto GetMatcher(FnT fn, const char* const name) {
constexpr size_t args_count = mcl::parameter_count_v<FnT>;
constexpr auto mask = std::get<0>(GetMaskAndExpect(bitstring));
constexpr auto expect = std::get<1>(GetMaskAndExpect(bitstring));
constexpr auto arg_masks = std::get<0>(GetArgInfo<args_count>(bitstring));
constexpr auto arg_shifts = std::get<1>(GetArgInfo<args_count>(bitstring));
using Iota = std::make_index_sequence<args_count>; using Iota = std::make_index_sequence<args_count>;
const auto [mask, expect] = mask_and_expect;
const auto [arg_masks, arg_shifts] = masks_and_shifts;
const auto proxy_fn = VisitorCaller<FnT>::Make(Iota(), fn, arg_masks, arg_shifts); const auto proxy_fn = VisitorCaller<FnT>::Make(Iota(), fn, arg_masks, arg_shifts);
return MatcherT(name, mask, expect, proxy_fn); return MatcherT(name, mask, expect, proxy_fn);
} }
}; };
#define DYNARMIC_DECODER_GET_MATCHER(MatcherT, fn, name, bitstring) Decoder::detail::detail<MatcherT<V>>::GetMatcher(&V::fn, name, Decoder::detail::detail<MatcherT<V>>::GetMaskAndExpect(bitstring), Decoder::detail::detail<MatcherT<V>>::template GetArgInfo<mcl::parameter_count_v<decltype(&V::fn)>>(bitstring)) #define DYNARMIC_DECODER_GET_MATCHER(MatcherT, fn, name, bitstring) Decoder::detail::detail<MatcherT<V>>::template GetMatcher<bitstring>(&V::fn, name)
} // namespace detail } // namespace detail
} // namespace Dynarmic::Decoder } // namespace Dynarmic::Decoder