From 501284a81a60a19713aa0509f3db994617f44659 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 16 Dec 2018 18:19:17 -0300
Subject: [PATCH] shader_decode: Implement BFE

---
 src/video_core/shader/decode/bfe.cpp | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/src/video_core/shader/decode/bfe.cpp b/src/video_core/shader/decode/bfe.cpp
index ffd904c54..6532a3bce 100644
--- a/src/video_core/shader/decode/bfe.cpp
+++ b/src/video_core/shader/decode/bfe.cpp
@@ -16,7 +16,31 @@ u32 ShaderIR::DecodeBfe(BasicBlock& bb, u32 pc) {
     const Instruction instr = {program_code[pc]};
     const auto opcode = OpCode::Decode(instr);
 
-    UNIMPLEMENTED();
+    UNIMPLEMENTED_IF(instr.bfe.negate_b);
+
+    Node op_a = GetRegister(instr.gpr8);
+    op_a = GetOperandAbsNegInteger(op_a, false, instr.bfe.negate_a, false);
+
+    switch (opcode->get().GetId()) {
+    case OpCode::Id::BFE_IMM: {
+        UNIMPLEMENTED_IF_MSG(instr.generates_cc,
+                             "Condition codes generation in BFE is not implemented");
+
+        const Node inner_shift_imm = Immediate(static_cast<u32>(instr.bfe.GetLeftShiftValue()));
+        const Node outer_shift_imm =
+            Immediate(static_cast<u32>(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position));
+
+        const Node inner_shift =
+            Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, op_a, inner_shift_imm);
+        const Node outer_shift =
+            Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, inner_shift, outer_shift_imm);
+
+        SetRegister(bb, instr.gpr0, outer_shift);
+        break;
+    }
+    default:
+        UNIMPLEMENTED_MSG("Unhandled BFE instruction: {}", opcode->get().GetName());
+    }
 
     return pc;
 }