mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-16 00:40:59 +00:00
[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 <noreply@anthropic.com>
This commit is contained in:
@@ -900,6 +900,7 @@ internal static class Gen5ShaderTranslator
|
||||
0x169 => "VMulLoU32",
|
||||
0x16A => "VMulHiU32",
|
||||
0x16B => "VMulLoI32",
|
||||
0x16C => "VMulHiI32",
|
||||
0x360 => "VMadU32U16",
|
||||
0x361 => "VMulLoU32",
|
||||
0x362 => "VLdexpF32",
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user