Răsfoiți Sursa

gl_shader_decompiler: Implement BFI_IMM_R

ReinUsesLisp 7 ani în urmă
părinte
comite
642dfeda2a

+ 3 - 0
src/video_core/engines/shader_bytecode.h

@@ -1256,6 +1256,7 @@ public:
         BFE_C,
         BFE_R,
         BFE_IMM,
+        BFI_IMM_R,
         BRA,
         PBK,
         LD_A,
@@ -1396,6 +1397,7 @@ public:
         ArithmeticHalf,
         ArithmeticHalfImmediate,
         Bfe,
+        Bfi,
         Shift,
         Ffma,
         Hfma2,
@@ -1613,6 +1615,7 @@ private:
             INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"),
             INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"),
             INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"),
+            INST("0011011-11110---", Id::BFI_IMM_R, Type::Bfi, "BFI_IMM_R"),
             INST("0100110001000---", Id::LOP_C, Type::ArithmeticInteger, "LOP_C"),
             INST("0101110001000---", Id::LOP_R, Type::ArithmeticInteger, "LOP_R"),
             INST("0011100001000---", Id::LOP_IMM, Type::ArithmeticInteger, "LOP_IMM"),

+ 20 - 0
src/video_core/renderer_opengl/gl_shader_decompiler.cpp

@@ -1700,6 +1700,26 @@ private:
 
             break;
         }
+        case OpCode::Type::Bfi: {
+            UNIMPLEMENTED_IF(instr.generates_cc);
+
+            const auto [base, packed_shift] = [&]() -> std::tuple<std::string, std::string> {
+                switch (opcode->get().GetId()) {
+                case OpCode::Id::BFI_IMM_R:
+                    return {regs.GetRegisterAsInteger(instr.gpr39, 0, false),
+                            std::to_string(instr.alu.GetSignedImm20_20())};
+                default:
+                    UNREACHABLE();
+                }
+            }();
+            const std::string offset = '(' + packed_shift + " & 0xff)";
+            const std::string bits = "((" + packed_shift + " >> 8) & 0xff)";
+            const std::string insert = regs.GetRegisterAsInteger(instr.gpr8, 0, false);
+            regs.SetRegisterToInteger(
+                instr.gpr0, false, 0,
+                "bitfieldInsert(" + base + ", " + insert + ", " + offset + ", " + bits + ')', 1, 1);
+            break;
+        }
         case OpCode::Type::Shift: {
             std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true);
             std::string op_b;