diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 67194b0e36..a36df65f96 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 5b976b6361..7926726a1c 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -849,6 +849,28 @@ 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) {
+        std::string result;
+        result += '(';
+
+        for (u32 i = 0; i < 32; ++i) {
+            std::string ix = std::to_string(i);
+            if (i)
+                result += '|';
+            result += "(((" + imm_lut + ">>(((" + op_c + ">>" + ix + ")&1)|((" + op_b + ">>" + ix +
+                      ")&1)<<1|((" + op_a + ">>" + ix + ")&1)<<2))&1)<<" + ix + ")";
+        }
+
+        result += ')';
+
+        LOG_DEBUG(HW_GPU, "LOP3 Shader code: {}", result);
+
+        if (dest != Tegra::Shader::Register::ZeroIndex) {
+            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 +1319,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: {