diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index a8df03f902..ddd34e9150 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -78,6 +78,7 @@ add_library(shader_recompiler STATIC
     frontend/maxwell/translate/impl/integer_add_three_input.cpp
     frontend/maxwell/translate/impl/integer_compare.cpp
     frontend/maxwell/translate/impl/integer_compare_and_set.cpp
+    frontend/maxwell/translate/impl/integer_funnel_shift.cpp
     frontend/maxwell/translate/impl/integer_minimum_maximum.cpp
     frontend/maxwell/translate/impl/integer_popcount.cpp
     frontend/maxwell/translate/impl/integer_scaled_add.cpp
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index 1f7d848715..bf1b5ace60 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -232,9 +232,11 @@ Id EmitINeg32(EmitContext& ctx, Id value);
 Id EmitINeg64(EmitContext& ctx, Id value);
 Id EmitIAbs32(EmitContext& ctx, Id value);
 Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift);
-Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b);
-Id EmitShiftRightLogical64(EmitContext& ctx, Id a, Id b);
-Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b);
+Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift);
+Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift);
+Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift);
+Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift);
+Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift);
 Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b);
 Id EmitBitwiseOr32(EmitContext& ctx, Id a, Id b);
 Id EmitBitwiseXor32(EmitContext& ctx, Id a, Id b);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
index f5001cdaa1..5ab3b5e864 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp
@@ -74,16 +74,24 @@ Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) {
     return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift);
 }
 
-Id EmitShiftRightLogical32(EmitContext& ctx, Id a, Id b) {
-    return ctx.OpShiftRightLogical(ctx.U32[1], a, b);
+Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift) {
+    return ctx.OpShiftLeftLogical(ctx.U64, base, shift);
 }
 
-Id EmitShiftRightLogical64(EmitContext& ctx, Id a, Id b) {
-    return ctx.OpShiftRightLogical(ctx.U64, a, b);
+Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift) {
+    return ctx.OpShiftRightLogical(ctx.U32[1], base, shift);
 }
 
-Id EmitShiftRightArithmetic32(EmitContext& ctx, Id a, Id b) {
-    return ctx.OpShiftRightArithmetic(ctx.U32[1], a, b);
+Id EmitShiftRightLogical64(EmitContext& ctx, Id base, Id shift) {
+    return ctx.OpShiftRightLogical(ctx.U64, base, shift);
+}
+
+Id EmitShiftRightArithmetic32(EmitContext& ctx, Id base, Id shift) {
+    return ctx.OpShiftRightArithmetic(ctx.U32[1], base, shift);
+}
+
+Id EmitShiftRightArithmetic64(EmitContext& ctx, Id base, Id shift) {
+    return ctx.OpShiftRightArithmetic(ctx.U64, base, shift);
 }
 
 Id EmitBitwiseAnd32(EmitContext& ctx, Id a, Id b) {
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 01f52183cc..1659b7f3b6 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -813,8 +813,15 @@ U32 IREmitter::IAbs(const U32& value) {
     return Inst<U32>(Opcode::IAbs32, value);
 }
 
-U32 IREmitter::ShiftLeftLogical(const U32& base, const U32& shift) {
-    return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift);
+U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) {
+    switch (base.Type()) {
+    case Type::U32:
+        return Inst<U32>(Opcode::ShiftLeftLogical32, base, shift);
+    case Type::U64:
+        return Inst<U64>(Opcode::ShiftLeftLogical64, base, shift);
+    default:
+        ThrowInvalidType(base.Type());
+    }
 }
 
 U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) {
@@ -828,8 +835,15 @@ U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) {
     }
 }
 
-U32 IREmitter::ShiftRightArithmetic(const U32& base, const U32& shift) {
-    return Inst<U32>(Opcode::ShiftRightArithmetic32, base, shift);
+U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) {
+    switch (base.Type()) {
+    case Type::U32:
+        return Inst<U32>(Opcode::ShiftRightArithmetic32, base, shift);
+    case Type::U64:
+        return Inst<U64>(Opcode::ShiftRightArithmetic64, base, shift);
+    default:
+        ThrowInvalidType(base.Type());
+    }
 }
 
 U32 IREmitter::BitwiseAnd(const U32& a, const U32& b) {
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 33bf2a7d08..6e29bf0e20 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -150,9 +150,9 @@ public:
     [[nodiscard]] U32 IMul(const U32& a, const U32& b);
     [[nodiscard]] U32U64 INeg(const U32U64& value);
     [[nodiscard]] U32 IAbs(const U32& value);
-    [[nodiscard]] U32 ShiftLeftLogical(const U32& base, const U32& shift);
+    [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift);
     [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift);
-    [[nodiscard]] U32 ShiftRightArithmetic(const U32& base, const U32& shift);
+    [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift);
     [[nodiscard]] U32 BitwiseAnd(const U32& a, const U32& b);
     [[nodiscard]] U32 BitwiseOr(const U32& a, const U32& b);
     [[nodiscard]] U32 BitwiseXor(const U32& a, const U32& b);
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index b51aaaef51..75f09ebfcd 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -236,9 +236,11 @@ OPCODE(INeg32,                                              U32,            U32,
 OPCODE(INeg64,                                              U64,            U64,                                                            )
 OPCODE(IAbs32,                                              U32,            U32,                                                            )
 OPCODE(ShiftLeftLogical32,                                  U32,            U32,            U32,                                            )
+OPCODE(ShiftLeftLogical64,                                  U64,            U64,            U32,                                            )
 OPCODE(ShiftRightLogical32,                                 U32,            U32,            U32,                                            )
 OPCODE(ShiftRightLogical64,                                 U64,            U64,            U32,                                            )
 OPCODE(ShiftRightArithmetic32,                              U32,            U32,            U32,                                            )
+OPCODE(ShiftRightArithmetic64,                              U64,            U64,            U32,                                            )
 OPCODE(BitwiseAnd32,                                        U32,            U32,            U32,                                            )
 OPCODE(BitwiseOr32,                                         U32,            U32,            U32,                                            )
 OPCODE(BitwiseXor32,                                        U32,            U32,            U32,                                            )
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp
new file mode 100644
index 0000000000..d8d6c939ed
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_funnel_shift.cpp
@@ -0,0 +1,77 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
+
+namespace Shader::Maxwell {
+namespace {
+enum class MaxShift : u64 {
+    U32,
+    Undefined,
+    U64,
+    S64,
+};
+
+IR::U64 PackedShift(IR::IREmitter& ir, const IR::U64& packed_int, const IR::U32& safe_shift,
+                    bool right_shift, bool is_signed) {
+    if (!right_shift) {
+        return ir.ShiftLeftLogical(packed_int, safe_shift);
+    }
+    if (is_signed) {
+        return ir.ShiftRightArithmetic(packed_int, safe_shift);
+    }
+    return ir.ShiftRightLogical(packed_int, safe_shift);
+}
+
+void SHF(TranslatorVisitor& v, u64 insn, const IR::U32& shift, const IR::U32& high_bits,
+         bool right_shift) {
+    union {
+        u64 insn;
+        BitField<0, 8, IR::Reg> dest_reg;
+        BitField<0, 8, IR::Reg> lo_bits_reg;
+        BitField<37, 2, MaxShift> max_shift;
+        BitField<48, 2, u64> x_mode;
+        BitField<50, 1, u64> wrap;
+    } const shf{insn};
+    if (shf.x_mode != 0) {
+        throw NotImplementedException("SHF X Mode");
+    }
+    if (shf.max_shift == MaxShift::Undefined) {
+        throw NotImplementedException("SHF Use of undefined MaxShift value");
+    }
+    const IR::U32 low_bits{v.X(shf.lo_bits_reg)};
+    const IR::U64 packed_int{v.ir.PackUint2x32(v.ir.CompositeConstruct(low_bits, high_bits))};
+    const IR::U32 max_shift{shf.max_shift == MaxShift::U32 ? v.ir.Imm32(32) : v.ir.Imm32(63)};
+    const IR::U32 safe_shift{shf.wrap != 0
+                                 ? v.ir.BitwiseAnd(shift, v.ir.ISub(max_shift, v.ir.Imm32(1)))
+                                 : v.ir.UMin(shift, max_shift)};
+
+    const bool is_signed{shf.max_shift == MaxShift::S64};
+    const IR::U64 shifted_value{PackedShift(v.ir, packed_int, safe_shift, right_shift, is_signed)};
+    const IR::Value unpacked_value{v.ir.UnpackUint2x32(shifted_value)};
+
+    const IR::U32 result{v.ir.CompositeExtract(unpacked_value, right_shift ? 0 : 1)};
+    v.X(shf.dest_reg, result);
+}
+} // Anonymous namespace
+
+void TranslatorVisitor::SHF_l_reg(u64 insn) {
+    SHF(*this, insn, GetReg20(insn), GetReg39(insn), false);
+}
+
+void TranslatorVisitor::SHF_l_imm(u64 insn) {
+    SHF(*this, insn, GetImm20(insn), GetReg39(insn), false);
+}
+
+void TranslatorVisitor::SHF_r_reg(u64 insn) {
+    SHF(*this, insn, GetReg20(insn), GetReg39(insn), true);
+}
+
+void TranslatorVisitor::SHF_r_imm(u64 insn) {
+    SHF(*this, insn, GetImm20(insn), GetReg39(insn), true);
+}
+
+} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
index 62863aff61..2ab90d1bf0 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -553,22 +553,6 @@ void TranslatorVisitor::SETLMEMBASE(u64) {
     ThrowNotImplemented(Opcode::SETLMEMBASE);
 }
 
-void TranslatorVisitor::SHF_l_reg(u64) {
-    ThrowNotImplemented(Opcode::SHF_l_reg);
-}
-
-void TranslatorVisitor::SHF_l_imm(u64) {
-    ThrowNotImplemented(Opcode::SHF_l_imm);
-}
-
-void TranslatorVisitor::SHF_r_reg(u64) {
-    ThrowNotImplemented(Opcode::SHF_r_reg);
-}
-
-void TranslatorVisitor::SHF_r_imm(u64) {
-    ThrowNotImplemented(Opcode::SHF_r_imm);
-}
-
 void TranslatorVisitor::SHFL(u64) {
     ThrowNotImplemented(Opcode::SHFL);
 }