From 0565d0174489758832c4ab47345d05e60ccf1043 Mon Sep 17 00:00:00 2001 From: Deeptanshu Lal <143280861+Deeptanshuu@users.noreply.github.com> Date: Mon, 13 Jul 2026 21:23:19 +0530 Subject: [PATCH] [AGC] Support VOP3 signed 32-bit multiplies (v_mul_lo_i32, v_mul_hi_i32) (#106) Two gaps around the VOP3 signed multiplies caused whole-shader SPIR-V compilation failures: - v_mul_lo_i32 (0x16B) decoded correctly but had no emission case, so any shader containing it failed with "unsupported vector opcode VMulLoI32". Its low 32 result bits are identical to the unsigned multiply in two's complement, so it now shares the v_mul_lo_u32 IMul case. - v_mul_hi_i32 (0x16C) was missing from the VOP3 decode table entirely and decoded as an opaque Vop3Raw16C, which also fails at emission. It is now decoded and emitted by sign-extending both operands to 64 bits, multiplying, and taking the upper 32 bits of the product, mirroring the existing v_mul_hi_u32 pattern. Opcode numbers verified against LLVM's AMDGPU backend (VOP3Instructions.td): V_MUL_LO_U32 gfx10 = 0x169, V_MUL_HI_U32 = 0x16a, V_MUL_LO_I32 = 0x16b, V_MUL_HI_I32 = 0x16c. Behavior verified by decoding and fully compiling a synthetic program containing all four multiplies: previously the 0x16C word decoded as Vop3Raw16C and compilation failed at the v_mul_lo_i32 instruction; now all four decode by name and the program compiles to SPIR-V. Co-authored-by: Claude Fable 5 --- src/SharpEmu.Libs/Agc/Gen5ShaderTranslator.cs | 1 + .../Agc/Gen5SpirvTranslator.Alu.cs | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/SharpEmu.Libs/Agc/Gen5ShaderTranslator.cs b/src/SharpEmu.Libs/Agc/Gen5ShaderTranslator.cs index cfb4c7e..7337969 100644 --- a/src/SharpEmu.Libs/Agc/Gen5ShaderTranslator.cs +++ b/src/SharpEmu.Libs/Agc/Gen5ShaderTranslator.cs @@ -900,6 +900,7 @@ internal static class Gen5ShaderTranslator 0x169 => "VMulLoU32", 0x16A => "VMulHiU32", 0x16B => "VMulLoI32", + 0x16C => "VMulHiI32", 0x360 => "VMadU32U16", 0x361 => "VMulLoU32", 0x362 => "VLdexpF32", diff --git a/src/SharpEmu.Libs/Agc/Gen5SpirvTranslator.Alu.cs b/src/SharpEmu.Libs/Agc/Gen5SpirvTranslator.Alu.cs index 9df8d40..2d8d3c7 100644 --- a/src/SharpEmu.Libs/Agc/Gen5SpirvTranslator.Alu.cs +++ b/src/SharpEmu.Libs/Agc/Gen5SpirvTranslator.Alu.cs @@ -337,6 +337,7 @@ internal static partial class Gen5SpirvTranslator result = EmitSubtractWithBorrow(instruction, reverse: true); break; case "VMulLoU32": + case "VMulLoI32": case "VMulU32U24": result = EmitIntegerBinary(instruction, SpirvOp.IMul); break; @@ -372,6 +373,29 @@ internal static partial class Gen5SpirvTranslator _module.Constant64(_ulongType, 32))); break; } + case "VMulHiI32": + { + var wideLeft = _module.AddInstruction( + SpirvOp.SConvert, + _longType, + Bitcast(_intType, GetRawSource(instruction, 0))); + var wideRight = _module.AddInstruction( + SpirvOp.SConvert, + _longType, + Bitcast(_intType, GetRawSource(instruction, 1))); + var product = _module.AddInstruction( + SpirvOp.IMul, + _longType, + wideLeft, + wideRight); + result = _module.AddInstruction( + SpirvOp.UConvert, + _uintType, + ShiftRightLogical64( + Bitcast(_ulongType, product), + _module.Constant64(_ulongType, 32))); + break; + } case "VMadU32U24": { var left = BitwiseAnd(