shader: Implement SEL
This commit is contained in:
		| @@ -79,6 +79,7 @@ add_library(shader_recompiler STATIC | |||||||
|     frontend/maxwell/translate/impl/move_register.cpp |     frontend/maxwell/translate/impl/move_register.cpp | ||||||
|     frontend/maxwell/translate/impl/move_special_register.cpp |     frontend/maxwell/translate/impl/move_special_register.cpp | ||||||
|     frontend/maxwell/translate/impl/not_implemented.cpp |     frontend/maxwell/translate/impl/not_implemented.cpp | ||||||
|  |     frontend/maxwell/translate/impl/select_source_with_predicate.cpp | ||||||
|     frontend/maxwell/translate/translate.cpp |     frontend/maxwell/translate/translate.cpp | ||||||
|     frontend/maxwell/translate/translate.h |     frontend/maxwell/translate/translate.h | ||||||
|     ir_opt/collect_shader_info_pass.cpp |     ir_opt/collect_shader_info_pass.cpp | ||||||
|   | |||||||
| @@ -729,18 +729,6 @@ void TranslatorVisitor::SAM(u64) { | |||||||
|     ThrowNotImplemented(Opcode::SAM); |     ThrowNotImplemented(Opcode::SAM); | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslatorVisitor::SEL_reg(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::SEL_reg); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::SEL_cbuf(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::SEL_cbuf); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::SEL_imm(u64) { |  | ||||||
|     ThrowNotImplemented(Opcode::SEL_imm); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void TranslatorVisitor::SETCRSPTR(u64) { | void TranslatorVisitor::SETCRSPTR(u64) { | ||||||
|     ThrowNotImplemented(Opcode::SETCRSPTR); |     ThrowNotImplemented(Opcode::SETCRSPTR); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,44 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #include "common/bit_field.h" | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
|  | namespace Shader::Maxwell { | ||||||
|  | namespace { | ||||||
|  |  | ||||||
|  | void SEL(TranslatorVisitor& v, u64 insn, const IR::U32& src) { | ||||||
|  |     union { | ||||||
|  |         u64 raw; | ||||||
|  |         BitField<0, 8, IR::Reg> dest_reg; | ||||||
|  |         BitField<8, 8, IR::Reg> op_a; | ||||||
|  |         BitField<39, 3, IR::Pred> pred; | ||||||
|  |         BitField<42, 1, u64> neg_pred; | ||||||
|  |     } const sel{insn}; | ||||||
|  |  | ||||||
|  |     const IR::U1 pred = v.ir.GetPred(sel.pred); | ||||||
|  |     IR::U32 op_a{v.X(sel.op_a)}; | ||||||
|  |     IR::U32 op_b{src}; | ||||||
|  |     if (sel.neg_pred != 0) { | ||||||
|  |         std::swap(op_a, op_b); | ||||||
|  |     } | ||||||
|  |     const IR::U32 result{v.ir.Select(pred, op_a, op_b)}; | ||||||
|  |  | ||||||
|  |     v.X(sel.dest_reg, result); | ||||||
|  | } | ||||||
|  | } // Anonymous namespace | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::SEL_reg(u64 insn) { | ||||||
|  |     SEL(*this, insn, GetReg20(insn)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::SEL_cbuf(u64 insn) { | ||||||
|  |     SEL(*this, insn, GetCbuf(insn)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void TranslatorVisitor::SEL_imm(u64 insn) { | ||||||
|  |     SEL(*this, insn, GetImm20(insn)); | ||||||
|  | } | ||||||
|  | } // namespace Shader::Maxwell | ||||||
| @@ -109,11 +109,13 @@ IR::Opcode UndefOpcode(const FlagTag&) noexcept { | |||||||
|  |  | ||||||
| class Pass { | class Pass { | ||||||
| public: | public: | ||||||
|     void WriteVariable(auto variable, IR::Block* block, const IR::Value& value) { |     template <typename Type> | ||||||
|  |     void WriteVariable(Type variable, IR::Block* block, const IR::Value& value) { | ||||||
|         current_def[variable].insert_or_assign(block, value); |         current_def[variable].insert_or_assign(block, value); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     IR::Value ReadVariable(auto variable, IR::Block* block) { |     template <typename Type> | ||||||
|  |     IR::Value ReadVariable(Type variable, IR::Block* block) { | ||||||
|         const ValueMap& def{current_def[variable]}; |         const ValueMap& def{current_def[variable]}; | ||||||
|         if (const auto it{def.find(block)}; it != def.end()) { |         if (const auto it{def.find(block)}; it != def.end()) { | ||||||
|             return it->second; |             return it->second; | ||||||
| @@ -132,7 +134,8 @@ public: | |||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     IR::Value ReadVariableRecursive(auto variable, IR::Block* block) { |     template <typename Type> | ||||||
|  |     IR::Value ReadVariableRecursive(Type variable, IR::Block* block) { | ||||||
|         IR::Value val; |         IR::Value val; | ||||||
|         if (!sealed_blocks.contains(block)) { |         if (!sealed_blocks.contains(block)) { | ||||||
|             // Incomplete CFG |             // Incomplete CFG | ||||||
| @@ -154,7 +157,8 @@ private: | |||||||
|         return val; |         return val; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     IR::Value AddPhiOperands(auto variable, IR::Inst& phi, IR::Block* block) { |     template <typename Type> | ||||||
|  |     IR::Value AddPhiOperands(Type variable, IR::Inst& phi, IR::Block* block) { | ||||||
|         for (IR::Block* const imm_pred : block->ImmediatePredecessors()) { |         for (IR::Block* const imm_pred : block->ImmediatePredecessors()) { | ||||||
|             phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred)); |             phi.AddPhiOperand(imm_pred, ReadVariable(variable, imm_pred)); | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user