diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 9176a8dbce..2db906ea50 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -423,6 +423,45 @@ union Instruction { } } bfe; + union { + BitField<48, 3, u64> pred48; + + union { + BitField<20, 20, u64> entry_a; + BitField<39, 5, u64> entry_b; + BitField<45, 1, u64> neg; + BitField<46, 1, u64> uses_cc; + } imm; + + union { + BitField<20, 14, u64> cb_index; + BitField<34, 5, u64> cb_offset; + BitField<56, 1, u64> neg; + BitField<57, 1, u64> uses_cc; + } hi; + + union { + BitField<20, 14, u64> cb_index; + BitField<34, 5, u64> cb_offset; + BitField<39, 5, u64> entry_a; + BitField<45, 1, u64> neg; + BitField<46, 1, u64> uses_cc; + } rz; + + union { + BitField<39, 5, u64> entry_a; + BitField<45, 1, u64> neg; + BitField<46, 1, u64> uses_cc; + } r1; + + union { + BitField<28, 8, u64> entry_a; + BitField<37, 1, u64> neg; + BitField<38, 1, u64> uses_cc; + } r2; + + } lea; + union { BitField<0, 5, FlowCondition> cond; } flow; @@ -477,6 +516,18 @@ union Instruction { BitField<45, 2, PredOperation> op; } psetp; + union { + BitField<12, 3, u64> pred12; + BitField<15, 1, u64> neg_pred12; + BitField<24, 2, PredOperation> cond; + BitField<29, 3, u64> pred29; + BitField<32, 1, u64> neg_pred29; + BitField<39, 3, u64> pred39; + BitField<42, 1, u64> neg_pred39; + BitField<44, 1, u64> bf; + BitField<45, 2, PredOperation> op; + } pset; + union { BitField<39, 3, u64> pred39; BitField<42, 1, u64> neg_pred; @@ -726,6 +777,11 @@ public: ISCADD_C, // Scale and Add ISCADD_R, ISCADD_IMM, + LEA_R1, + LEA_R2, + LEA_RZ, + LEA_IMM, + LEA_HI, POPC_C, POPC_R, POPC_IMM, @@ -784,6 +840,7 @@ public: ISET_C, ISET_IMM, PSETP, + PSET, XMAD_IMM, XMAD_CR, XMAD_RC, @@ -807,6 +864,7 @@ public: IntegerSet, IntegerSetPredicate, PredicateSetPredicate, + PredicateSetRegister, Conversion, Xmad, Unknown, @@ -958,6 +1016,11 @@ private: INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"), INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"), INST("0011100-10100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"), + INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"), + INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"), + INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"), + INST("010010111101----", Id::LEA_RZ, Type::ArithmeticInteger, "LEA_RZ"), + INST("00011000--------", Id::LEA_HI, Type::ArithmeticInteger, "LEA_HI"), INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), @@ -1012,6 +1075,7 @@ private: INST("010110110101----", Id::ISET_R, Type::IntegerSet, "ISET_R"), INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"), INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), + INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"), INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"), INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"), diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e350113f12..582c811e06 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -1505,6 +1505,73 @@ private: 1, 1); break; } + case OpCode::Id::LEA_R2: + case OpCode::Id::LEA_R1: + case OpCode::Id::LEA_IMM: + case OpCode::Id::LEA_RZ: + case OpCode::Id::LEA_HI: { + std::string op_a; + std::string op_b; + std::string op_c; + + switch (opcode->GetId()) { + case OpCode::Id::LEA_R2: { + op_a = regs.GetRegisterAsInteger(instr.gpr20); + op_b = regs.GetRegisterAsInteger(instr.gpr39); + op_c = std::to_string(instr.lea.r2.entry_a); + break; + } + + case OpCode::Id::LEA_R1: { + const bool neg = instr.lea.r1.neg != 0; + op_a = regs.GetRegisterAsInteger(instr.gpr8); + if (neg) + op_a = "-(" + op_a + ')'; + op_b = regs.GetRegisterAsInteger(instr.gpr20); + op_c = std::to_string(instr.lea.r1.entry_a); + break; + } + + case OpCode::Id::LEA_IMM: { + const bool neg = instr.lea.imm.neg != 0; + op_b = regs.GetRegisterAsInteger(instr.gpr8); + if (neg) + op_b = "-(" + op_b + ')'; + op_a = std::to_string(instr.lea.imm.entry_a); + op_c = std::to_string(instr.lea.imm.entry_b); + break; + } + + case OpCode::Id::LEA_RZ: { + const bool neg = instr.lea.rz.neg != 0; + op_b = regs.GetRegisterAsInteger(instr.gpr8); + if (neg) + op_b = "-(" + op_b + ')'; + op_a = regs.GetUniform(instr.lea.rz.cb_index, instr.lea.rz.cb_offset, + GLSLRegister::Type::Integer); + op_c = std::to_string(instr.lea.rz.entry_a); + + break; + } + + case OpCode::Id::LEA_HI: + default: { + op_b = regs.GetRegisterAsInteger(instr.gpr8); + op_a = std::to_string(instr.lea.imm.entry_a); + op_c = std::to_string(instr.lea.imm.entry_b); + LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", opcode->GetName()); + UNREACHABLE(); + } + } + if (instr.lea.pred48 != static_cast(Pred::UnusedIndex)) { + LOG_ERROR(HW_GPU, "Unhandled LEA Predicate"); + UNREACHABLE(); + } + const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))"; + regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1); + + break; + } default: { LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}", opcode->GetName()); @@ -2087,6 +2154,30 @@ private: } break; } + case OpCode::Type::PredicateSetRegister: { + const std::string op_a = + GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0); + const std::string op_b = + GetPredicateCondition(instr.pset.pred29, instr.pset.neg_pred29 != 0); + + const std::string second_pred = + GetPredicateCondition(instr.pset.pred39, instr.pset.neg_pred39 != 0); + + const std::string combiner = GetPredicateCombiner(instr.pset.op); + + const std::string predicate = + '(' + op_a + ") " + GetPredicateCombiner(instr.pset.cond) + " (" + op_b + ')'; + const std::string result = '(' + predicate + ") " + combiner + " (" + second_pred + ')'; + if (instr.pset.bf == 0) { + const std::string value = '(' + result + ") ? 0xFFFFFFFF : 0"; + regs.SetRegisterToInteger(instr.gpr0, false, 0, value, 1, 1); + } else { + const std::string value = '(' + result + ") ? 1.0 : 0.0"; + regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1); + } + + break; + } case OpCode::Type::PredicateSetPredicate: { const std::string op_a = GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);