summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h16
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp43
2 files changed, 58 insertions, 1 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index da64430e9..14d72920f 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -156,6 +156,13 @@ enum class PredOperation : u64 {
156 Xor = 2, 156 Xor = 2,
157}; 157};
158 158
159enum class LogicOperation : u64 {
160 And = 0,
161 Or = 1,
162 Xor = 2,
163 PassB = 3,
164};
165
159enum class SubOp : u64 { 166enum class SubOp : u64 {
160 Cos = 0x0, 167 Cos = 0x0,
161 Sin = 0x1, 168 Sin = 0x1,
@@ -202,6 +209,12 @@ union Instruction {
202 BitField<42, 1, u64> negate_pred; 209 BitField<42, 1, u64> negate_pred;
203 } fmnmx; 210 } fmnmx;
204 211
212 union {
213 BitField<53, 2, LogicOperation> operation;
214 BitField<55, 1, u64> invert_a;
215 BitField<56, 1, u64> invert_b;
216 } lop;
217
205 float GetImm20_19() const { 218 float GetImm20_19() const {
206 float result{}; 219 float result{};
207 u32 imm{static_cast<u32>(imm20_19)}; 220 u32 imm{static_cast<u32>(imm20_19)};
@@ -367,6 +380,7 @@ public:
367 enum class Type { 380 enum class Type {
368 Trivial, 381 Trivial,
369 Arithmetic, 382 Arithmetic,
383 Logic,
370 Ffma, 384 Ffma,
371 Flow, 385 Flow,
372 Memory, 386 Memory,
@@ -499,7 +513,6 @@ private:
499 INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), 513 INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"),
500 INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), 514 INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"),
501 INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), 515 INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"),
502 INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
503 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), 516 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
504 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), 517 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
505 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), 518 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"),
@@ -510,6 +523,7 @@ private:
510 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), 523 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
511 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), 524 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
512 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), 525 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
526 INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"),
513 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), 527 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
514 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), 528 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
515 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), 529 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index bb5209a7e..e29f0a1d3 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -808,6 +808,49 @@ private:
808 } 808 }
809 break; 809 break;
810 } 810 }
811 case OpCode::Type::Logic: {
812 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false);
813
814 if (instr.alu.lop.invert_a)
815 op_a = "~(" + op_a + ')';
816
817 switch (opcode->GetId()) {
818 case OpCode::Id::LOP32I: {
819 u32 imm = static_cast<u32>(instr.alu.imm20_32.Value());
820
821 if (instr.alu.lop.invert_b)
822 imm = ~imm;
823
824 switch (instr.alu.lop.operation) {
825 case Tegra::Shader::LogicOperation::And: {
826 regs.SetRegisterToInteger(instr.gpr0, false, 0,
827 '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1);
828 break;
829 }
830 case Tegra::Shader::LogicOperation::Or: {
831 regs.SetRegisterToInteger(instr.gpr0, false, 0,
832 '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1);
833 break;
834 }
835 case Tegra::Shader::LogicOperation::Xor: {
836 regs.SetRegisterToInteger(instr.gpr0, false, 0,
837 '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1);
838 break;
839 }
840 default:
841 NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}",
842 static_cast<u32>(instr.alu.lop.operation.Value()));
843 UNREACHABLE();
844 }
845 break;
846 }
847 default: {
848 NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName());
849 UNREACHABLE();
850 }
851 }
852 break;
853 }
811 case OpCode::Type::Ffma: { 854 case OpCode::Type::Ffma: {
812 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 855 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
813 std::string op_b = instr.ffma.negate_b ? "-" : ""; 856 std::string op_b = instr.ffma.negate_b ? "-" : "";