diff options
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 41 | 
2 files changed, 60 insertions, 0 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 67194b0e3..a36df65f9 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -280,6 +280,19 @@ union Instruction {              BitField<56, 1, u64> invert_b;          } lop32i; +        union { +            BitField<28, 8, u64> imm_lut28; +            BitField<48, 8, u64> imm_lut48; + +            u32 GetImmLut28() const { +                return static_cast<u32>(imm_lut28); +            } + +            u32 GetImmLut48() const { +                return static_cast<u32>(imm_lut48); +            } +        } lop3; +          u32 GetImm20_19() const {              u32 imm{static_cast<u32>(imm20_19)};              imm <<= 12; @@ -650,6 +663,9 @@ public:          LOP_R,          LOP_IMM,          LOP32I, +        LOP3_C, +        LOP3_R, +        LOP3_IMM,          MOV_C,          MOV_R,          MOV_IMM, @@ -872,6 +888,9 @@ private:              INST("0101110001000---", Id::LOP_R, Type::ArithmeticInteger, "LOP_R"),              INST("0011100001000---", Id::LOP_IMM, Type::ArithmeticInteger, "LOP_IMM"),              INST("000001----------", Id::LOP32I, Type::ArithmeticIntegerImmediate, "LOP32I"), +            INST("0000001---------", Id::LOP3_C, Type::ArithmeticInteger, "LOP3_C"), +            INST("0101101111100---", Id::LOP3_R, Type::ArithmeticInteger, "LOP3_R"), +            INST("0011110---------", Id::LOP3_IMM, Type::ArithmeticInteger, "LOP3_IMM"),              INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"),              INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"),              INST("0011100-01001---", Id::SHL_IMM, Type::Shift, "SHL_IMM"), diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index f1e00c93c..94e318966 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -849,6 +849,33 @@ private:          }      } +    void WriteLop3Instruction(Register dest, const std::string& op_a, const std::string& op_b, +                              const std::string& op_c, const std::string& imm_lut) { +        if (dest == Tegra::Shader::Register::ZeroIndex) { +            return; +        } + +        static constexpr std::array<const char*, 32> shift_amounts = { +            "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",  "8",  "9",  "10", +            "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", +            "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"}; + +        std::string result; +        result += '('; + +        for (size_t i = 0; i < shift_amounts.size(); ++i) { +            if (i) +                result += '|'; +            result += "(((" + imm_lut + " >> (((" + op_c + " >> " + shift_amounts[i] + +                      ") & 1) | ((" + op_b + " >> " + shift_amounts[i] + ") & 1) << 1 | ((" + op_a + +                      " >> " + shift_amounts[i] + ") & 1) << 2)) & 1) << " + shift_amounts[i] + ")"; +        } + +        result += ')'; + +        regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); +    } +      void WriteTexsInstruction(const Instruction& instr, const std::string& coord,                                const std::string& texture) {          // Add an extra scope and declare the texture coords inside to prevent @@ -1297,6 +1324,20 @@ private:                                      instr.alu.lop.pred_result_mode, instr.alu.lop.pred48);                  break;              } +            case OpCode::Id::LOP3_C: +            case OpCode::Id::LOP3_R: +            case OpCode::Id::LOP3_IMM: { +                std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); +                std::string lut; +                if (opcode->GetId() == OpCode::Id::LOP3_R) { +                    lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')'; +                } else { +                    lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')'; +                } + +                WriteLop3Instruction(instr.gpr0, op_a, op_b, op_c, lut); +                break; +            }              case OpCode::Id::IMNMX_C:              case OpCode::Id::IMNMX_R:              case OpCode::Id::IMNMX_IMM: {  | 
