From 0f1abe3a2e17eb40f23b74bf28e8ac2e7c368fc0 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 31 Oct 2025 23:11:29 +0000 Subject: [PATCH] [shader_recompiler] simplify decoder table logic and let compiler do tables for us Signed-off-by: lizzie --- .../frontend/maxwell/decode.cpp | 129 +++--------------- .../frontend/maxwell/maxwell.inc | 4 +- .../frontend/maxwell/translate/impl/impl.h | 1 + .../translate/impl/not_implemented.cpp | 4 + 4 files changed, 22 insertions(+), 116 deletions(-) diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp index 601dcfdfa8..b92863e4c7 100644 --- a/src/shader_recompiler/frontend/maxwell/decode.cpp +++ b/src/shader_recompiler/frontend/maxwell/decode.cpp @@ -7,142 +7,45 @@ #include #include #include +#include +#include #include "common/common_types.h" -#include #include "shader_recompiler/exception.h" #include "shader_recompiler/frontend/maxwell/decode.h" #include "shader_recompiler/frontend/maxwell/opcodes.h" namespace Shader::Maxwell { -namespace { -struct MaskValue { - u64 mask; - u64 value; -}; -constexpr MaskValue MaskValueFromEncoding(const char* encoding) { - u64 mask{}; - u64 value{}; - u64 bit{u64(1) << 63}; - while (*encoding) { - switch (*encoding) { +consteval std::pair MaskValueFromEncoding(const char data[20]) noexcept { + u64 mask = 0, value = 0, bit = u64(1) << 63; + for (int i = 0; i < 20; ++i) + switch (data[i]) { case '0': mask |= bit; + bit >>= 1; break; case '1': mask |= bit; value |= bit; + bit >>= 1; break; case '-': - break; - case ' ': + bit >>= 1; break; default: - throw LogicError("Invalid encoding character '{}'", *encoding); - } - ++encoding; - if (*encoding != ' ') { - bit >>= 1; + break; } - } - return MaskValue{.mask = mask, .value = value}; + return { mask, value }; } -struct InstEncoding { - MaskValue mask_value; - Opcode opcode; -}; -constexpr auto SortedEncodings() { - std::array encodings{ -#define INST(name, cute, encode) \ - InstEncoding{ \ - .mask_value{MaskValueFromEncoding(encode)}, \ - .opcode = Opcode::name, \ - }, +Opcode Decode(u64 insn) { +#define INST(name, cute, encode) \ + if (auto const p = MaskValueFromEncoding(encode); (insn & p.first) == p.second) \ + return Opcode::name; #include "maxwell.inc" #undef INST - }; - std::ranges::sort(encodings, [](const InstEncoding& lhs, const InstEncoding& rhs) { - return std::popcount(lhs.mask_value.mask) > std::popcount(rhs.mask_value.mask); - }); - return encodings; -} -constexpr auto ENCODINGS{SortedEncodings()}; - -constexpr int WidestLeftBits() { - int bits{64}; - for (const InstEncoding& encoding : ENCODINGS) { - bits = (std::min)(bits, std::countr_zero(encoding.mask_value.mask)); - } - return 64 - bits; -} -constexpr int WIDEST_LEFT_BITS{WidestLeftBits()}; -constexpr int MASK_SHIFT{64 - WIDEST_LEFT_BITS}; - -constexpr size_t ToFastLookupIndex(u64 value) { - return static_cast(value >> MASK_SHIFT); -} - -constexpr size_t FastLookupSize() { - size_t max_width{}; - for (const InstEncoding& encoding : ENCODINGS) { - max_width = (std::max)(max_width, ToFastLookupIndex(encoding.mask_value.mask)); - } - return max_width + 1; -} -constexpr size_t FAST_LOOKUP_SIZE{FastLookupSize()}; - -struct InstInfo { - [[nodiscard]] u64 Mask() const noexcept { - return static_cast(high_mask) << MASK_SHIFT; - } - - [[nodiscard]] u64 Value() const noexcept { - return static_cast(high_value) << MASK_SHIFT; - } - - u16 high_mask; - u16 high_value; - Opcode opcode; -}; - -constexpr auto MakeFastLookupTableIndex(size_t index) { - std::array encodings{}; - size_t element{}; - for (const auto& encoding : ENCODINGS) { - const size_t mask{ToFastLookupIndex(encoding.mask_value.mask)}; - const size_t value{ToFastLookupIndex(encoding.mask_value.value)}; - if ((index & mask) == value) { - encodings.at(element) = InstInfo{ - .high_mask = static_cast(encoding.mask_value.mask >> MASK_SHIFT), - .high_value = static_cast(encoding.mask_value.value >> MASK_SHIFT), - .opcode = encoding.opcode, - }; - ++element; - } - } - return encodings; -} - -/*constexpr*/ auto MakeFastLookupTable() { - auto encodings{std::make_unique, FAST_LOOKUP_SIZE>>()}; - for (size_t index = 0; index < FAST_LOOKUP_SIZE; ++index) { - (*encodings)[index] = MakeFastLookupTableIndex(index); - } - return encodings; -} -const auto FAST_LOOKUP_TABLE{MakeFastLookupTable()}; -} // Anonymous namespace - -Opcode Decode(u64 insn) { - const auto& table{(*FAST_LOOKUP_TABLE)[ToFastLookupIndex(insn)]}; - const auto it{std::ranges::find_if( - table, [insn](const InstInfo& info) { return (insn & info.Mask()) == info.Value(); })}; - if (it == table.end()) { - throw NotImplementedException("Instruction 0x{:016x} is unknown / unimplemented", insn); - } - return it->opcode; + throw NotImplementedException("Invalid insn 0x{:016x}", insn); } } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/maxwell.inc b/src/shader_recompiler/frontend/maxwell/maxwell.inc index 495b3e9f1c..7fe4b23a64 100644 --- a/src/shader_recompiler/frontend/maxwell/maxwell.inc +++ b/src/shader_recompiler/frontend/maxwell/maxwell.inc @@ -24,6 +24,7 @@ INST(BRX, "BRX", "1110 0010 0101 ----") INST(CAL, "CAL", "1110 0010 0110 ----") INST(CCTL, "CCTL", "1110 1111 011- ----") INST(CCTLL, "CCTLL", "1110 1111 100- ----") +INST(CCTLT, "CCTLT", "1110 1011 1111 0--0") INST(CONT, "CONT", "1110 0011 0101 ----") INST(CS2R, "CS2R", "0101 0000 1100 1---") INST(CSET, "CSET", "0101 0000 1001 1---") @@ -280,6 +281,3 @@ INST(XMAD_reg, "XMAD (reg)", "0101 1011 00-- ----") INST(XMAD_rc, "XMAD (rc)", "0101 0001 0--- ----") INST(XMAD_cr, "XMAD (cr)", "0100 111- ---- ----") INST(XMAD_imm, "XMAD (imm)", "0011 011- 00-- ----") - -// Removed due to its weird formatting making fast tables larger -// INST(CCTLT, "CCTLT", "1110 1011 1111 0--0") diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index 37963dc777..33365f4814 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h @@ -86,6 +86,7 @@ public: void CAL(); void CCTL(u64 insn); void CCTLL(u64 insn); + void CCTLT(u64 insn); void CONT(u64 insn); void CS2R(u64 insn); void CSET(u64 insn); diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 6203003b35..dcad3a9635 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp @@ -48,6 +48,10 @@ void TranslatorVisitor::CCTLL(u64) { ThrowNotImplemented(Opcode::CCTLL); } +void TranslatorVisitor::CCTLT(u64) { + ThrowNotImplemented(Opcode::CCTLT); +} + void TranslatorVisitor::CONT(u64) { ThrowNotImplemented(Opcode::CONT); }