From 621a73edb7c8a8429b7b5ade1a3600d58fa8199d Mon Sep 17 00:00:00 2001 From: CloudP4bbs Date: Fri, 6 Nov 2026 17:54:30 -0400 Subject: [PATCH] shader: lower the Ampere right funnel shift with both words set Ocarina of Time rejects its vertex program at instruction 0x790 with 'native funnel-shift mode': [op 819 0e0e7819 00000015 00001211 020fe200] bits(73,2)=1 bit75=0 bit76=1 bit80=0 shift=21 low=14 high=17 The case already covers the left funnel with two words and the right shift with a zero high word. The gap is a right funnel with both words real, which lowers like the left form with the right-shift opcode. Rebased onto nx2-experimental efd41e36, which already contains the gather, USHF and UBREV work this branch used to carry. --- src/shader_recompiler/frontend/ampere/lower_to_maxwell.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h index 188193bad4..8c5642f08e 100644 --- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h +++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h @@ -3102,6 +3102,14 @@ inline LoweredProgram LowerToMaxwellWith(std::span code, u32 emit(base(0x3828000000000000ULL) | (u64{insn.Bits(24, 8)} << 8) | (u64{insn.words[1]} << 20)); break; } + if (insn.Bits(73, 2) == 1 && insn.Bits(76, 1) && !insn.Bits(75, 1) && + insn.words[1] <= 32 && insn.Bits(24, 8) != 255 && insn.Bits(64, 8) != 255) { + // Right funnel shift of the pair (high:low) with neither word zero: the mirror of + // the left funnel below, low word as the destination and high word as Rc. + emit(base(0x3828000000000000ULL) | (u64{insn.Bits(24, 8)} << 8) | + (u64{insn.Bits(64, 8)} << 39) | (u64{insn.words[1]} << 20)); + break; + } if ((insn.Bits(73, 2) != 3 && !is_signed) || insn.Bits(75, 1) || !insn.Bits(80, 1) || insn.words[1] > 32) return fail(index, "native funnel-shift mode"); const u32 low = insn.Bits(24, 8), high = insn.Bits(64, 8), shift = insn.words[1]; if (insn.Bits(76, 1)) {