forked from eden-emu/eden
		
	shader: Implement CSET and CSETP
This commit is contained in:
		
							parent
							
								
									32b6c63485
								
							
						
					
					
						commit
						3b7fd3ad0f
					
				
					 6 changed files with 114 additions and 15 deletions
				
			
		|  | @ -63,6 +63,7 @@ add_library(shader_recompiler STATIC | |||
|     frontend/maxwell/translate/impl/common_encoding.h | ||||
|     frontend/maxwell/translate/impl/common_funcs.cpp | ||||
|     frontend/maxwell/translate/impl/common_funcs.h | ||||
|     frontend/maxwell/translate/impl/condition_code_set.cpp | ||||
|     frontend/maxwell/translate/impl/find_leading_one.cpp | ||||
|     frontend/maxwell/translate/impl/floating_point_add.cpp | ||||
|     frontend/maxwell/translate/impl/floating_point_compare.cpp | ||||
|  |  | |||
|  | @ -5,12 +5,13 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include <fmt/format.h> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Shader::IR { | ||||
| 
 | ||||
| enum class FlowTest { | ||||
| enum class FlowTest : u64 { | ||||
|     F, | ||||
|     LT, | ||||
|     EQ, | ||||
|  |  | |||
|  | @ -169,16 +169,62 @@ void IREmitter::SetOFlag(const U1& value) { | |||
| 
 | ||||
| static U1 GetFlowTest(IREmitter& ir, FlowTest flow_test) { | ||||
|     switch (flow_test) { | ||||
|     case FlowTest::T: | ||||
|         return ir.Imm1(true); | ||||
|     case FlowTest::F: | ||||
|         return ir.Imm1(false); | ||||
|     case FlowTest::LT: | ||||
|         return ir.LogicalXor(ir.LogicalAnd(ir.GetSFlag(), ir.LogicalNot(ir.GetZFlag())), | ||||
|                              ir.GetOFlag()); | ||||
|     case FlowTest::EQ: | ||||
|         // TODO: Test this
 | ||||
|         return ir.GetZFlag(); | ||||
|         return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.GetZFlag()); | ||||
|     case FlowTest::LE: | ||||
|         return ir.LogicalXor(ir.GetSFlag(), ir.LogicalOr(ir.GetZFlag(), ir.GetOFlag())); | ||||
|     case FlowTest::GT: | ||||
|         return ir.LogicalAnd(ir.LogicalXor(ir.LogicalNot(ir.GetSFlag()), ir.GetOFlag()), | ||||
|                              ir.LogicalNot(ir.GetZFlag())); | ||||
|     case FlowTest::NE: | ||||
|         // TODO: Test this
 | ||||
|         return ir.LogicalNot(ir.GetZFlag()); | ||||
|     case FlowTest::GE: | ||||
|         return ir.LogicalNot(ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag())); | ||||
|     case FlowTest::NUM: | ||||
|         return ir.LogicalOr(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag())); | ||||
|     case FlowTest::NaN: | ||||
|         return ir.LogicalAnd(ir.GetSFlag(), ir.GetZFlag()); | ||||
|     case FlowTest::LTU: | ||||
|         return ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag()); | ||||
|     case FlowTest::EQU: | ||||
|         return ir.GetZFlag(); | ||||
|     case FlowTest::LEU: | ||||
|         return ir.LogicalOr(ir.LogicalXor(ir.GetSFlag(), ir.GetOFlag()), ir.GetZFlag()); | ||||
|     case FlowTest::GTU: | ||||
|         return ir.LogicalXor(ir.LogicalNot(ir.GetSFlag()), | ||||
|                              ir.LogicalOr(ir.GetZFlag(), ir.GetOFlag())); | ||||
|     case FlowTest::NEU: | ||||
|         return ir.LogicalOr(ir.GetSFlag(), ir.LogicalNot(ir.GetZFlag())); | ||||
|     case FlowTest::GEU: | ||||
|         return ir.LogicalXor(ir.LogicalOr(ir.LogicalNot(ir.GetSFlag()), ir.GetZFlag()), | ||||
|                              ir.GetOFlag()); | ||||
|     case FlowTest::T: | ||||
|         return ir.Imm1(true); | ||||
|     case FlowTest::OFF: | ||||
|         return ir.LogicalNot(ir.GetOFlag()); | ||||
|     case FlowTest::LO: | ||||
|         return ir.LogicalNot(ir.GetCFlag()); | ||||
|     case FlowTest::SFF: | ||||
|         return ir.LogicalNot(ir.GetSFlag()); | ||||
|     case FlowTest::LS: | ||||
|         return ir.LogicalOr(ir.GetZFlag(), ir.LogicalNot(ir.GetCFlag())); | ||||
|     case FlowTest::HI: | ||||
|         return ir.LogicalAnd(ir.GetCFlag(), ir.LogicalNot(ir.GetZFlag())); | ||||
|     case FlowTest::SFT: | ||||
|         return ir.GetSFlag(); | ||||
|     case FlowTest::HS: | ||||
|         return ir.GetCFlag(); | ||||
|     case FlowTest::OFT: | ||||
|         return ir.GetOFlag(); | ||||
|     case FlowTest::RLE: | ||||
|         return ir.LogicalOr(ir.GetSFlag(), ir.GetZFlag()); | ||||
|     case FlowTest::RGT: | ||||
|         return ir.LogicalAnd(ir.LogicalNot(ir.GetSFlag()), ir.LogicalNot(ir.GetZFlag())); | ||||
|     default: | ||||
|         throw NotImplementedException("Flow test {}", flow_test); | ||||
|     } | ||||
|  | @ -190,6 +236,10 @@ U1 IREmitter::Condition(IR::Condition cond) { | |||
|     return LogicalAnd(GetPred(pred, is_negated), GetFlowTest(*this, flow_test)); | ||||
| } | ||||
| 
 | ||||
| U1 IREmitter::GetFlowTestResult(FlowTest test) { | ||||
|     return GetFlowTest(*this, test); | ||||
| } | ||||
| 
 | ||||
| F32 IREmitter::GetAttribute(IR::Attribute attribute) { | ||||
|     return Inst<F32>(Opcode::GetAttribute, attribute); | ||||
| } | ||||
|  |  | |||
|  | @ -62,6 +62,7 @@ public: | |||
|     void SetOFlag(const U1& value); | ||||
| 
 | ||||
|     [[nodiscard]] U1 Condition(IR::Condition cond); | ||||
|     [[nodiscard]] U1 GetFlowTestResult(FlowTest test); | ||||
| 
 | ||||
|     [[nodiscard]] F32 GetAttribute(IR::Attribute attribute); | ||||
|     void SetAttribute(IR::Attribute attribute, const F32& value); | ||||
|  |  | |||
|  | @ -0,0 +1,54 @@ | |||
| // 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/common_funcs.h" | ||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||
| 
 | ||||
| namespace Shader::Maxwell { | ||||
| 
 | ||||
| void TranslatorVisitor::CSET(u64 insn) { | ||||
|     union { | ||||
|         u64 raw; | ||||
|         BitField<0, 8, IR::Reg> dest_reg; | ||||
|         BitField<8, 5, IR::FlowTest> cc_test; | ||||
|         BitField<39, 3, IR::Pred> bop_pred; | ||||
|         BitField<42, 1, u64> neg_bop_pred; | ||||
|         BitField<44, 1, u64> bf; | ||||
|         BitField<45, 2, BooleanOp> bop; | ||||
|     } const cset{insn}; | ||||
| 
 | ||||
|     const IR::U32 one_mask{ir.Imm32(-1)}; | ||||
|     const IR::U32 fp_one{ir.Imm32(0x3f800000)}; | ||||
|     const IR::U32 fail_result{ir.Imm32(0)}; | ||||
|     const IR::U32 pass_result{cset.bf == 0 ? one_mask : fp_one}; | ||||
|     const IR::U1 cc_test_result{ir.GetFlowTestResult(cset.cc_test)}; | ||||
|     const IR::U1 bop_pred{ir.GetPred(cset.bop_pred, cset.neg_bop_pred != 0)}; | ||||
|     const IR::U1 pred_result{PredicateCombine(ir, cc_test_result, bop_pred, cset.bop)}; | ||||
|     const IR::U32 result{ir.Select(pred_result, pass_result, fail_result)}; | ||||
|     X(cset.dest_reg, result); | ||||
| } | ||||
| 
 | ||||
| void TranslatorVisitor::CSETP(u64 insn) { | ||||
|     union { | ||||
|         u64 raw; | ||||
|         BitField<0, 3, IR::Pred> dest_pred_b; | ||||
|         BitField<3, 3, IR::Pred> dest_pred_a; | ||||
|         BitField<8, 5, IR::FlowTest> cc_test; | ||||
|         BitField<39, 3, IR::Pred> bop_pred; | ||||
|         BitField<42, 1, u64> neg_bop_pred; | ||||
|         BitField<45, 2, BooleanOp> bop; | ||||
|     } const csetp{insn}; | ||||
| 
 | ||||
|     const BooleanOp bop{csetp.bop}; | ||||
|     const IR::U1 bop_pred{ir.GetPred(csetp.bop_pred, csetp.neg_bop_pred != 0)}; | ||||
|     const IR::U1 cc_test_result{ir.GetFlowTestResult(csetp.cc_test)}; | ||||
|     const IR::U1 result_a{PredicateCombine(ir, cc_test_result, bop_pred, bop)}; | ||||
|     const IR::U1 result_b{PredicateCombine(ir, ir.LogicalNot(cc_test_result), bop_pred, bop)}; | ||||
|     ir.SetPred(csetp.dest_pred_a, result_a); | ||||
|     ir.SetPred(csetp.dest_pred_b, result_b); | ||||
| } | ||||
| 
 | ||||
| } // namespace Shader::Maxwell
 | ||||
|  | @ -85,14 +85,6 @@ void TranslatorVisitor::CS2R(u64) { | |||
|     ThrowNotImplemented(Opcode::CS2R); | ||||
| } | ||||
| 
 | ||||
| void TranslatorVisitor::CSET(u64) { | ||||
|     ThrowNotImplemented(Opcode::CSET); | ||||
| } | ||||
| 
 | ||||
| void TranslatorVisitor::CSETP(u64) { | ||||
|     ThrowNotImplemented(Opcode::CSETP); | ||||
| } | ||||
| 
 | ||||
| void TranslatorVisitor::DADD_reg(u64) { | ||||
|     ThrowNotImplemented(Opcode::DADD_reg); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 ameerj
						ameerj