summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h19
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp41
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: {