diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h deleted file mode 100644 index 9acb715..0000000 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ /dev/null @@ -1,493 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/types.h" - -namespace Shader::IR { -enum class Attribute : u64; -enum class ScalarReg : u32; -enum class Patch : u64; -class Inst; -class Value; -} // namespace Shader::IR - -namespace Shader::Backend::SPIRV { - -using Sirit::Id; - -class EmitContext; - -// Microinstruction emitters -Id EmitPhi(EmitContext& ctx, IR::Inst* inst); -void EmitVoid(EmitContext& ctx); -Id EmitConditionRef(EmitContext& ctx, const IR::Value& value); -void EmitGetScc(EmitContext& ctx); -void EmitGetExec(EmitContext& ctx); -void EmitGetVcc(EmitContext& ctx); -void EmitGetVccLo(EmitContext& ctx); -void EmitGetVccHi(EmitContext& ctx); -void EmitGetM0(EmitContext& ctx); -void EmitSetScc(EmitContext& ctx); -void EmitSetExec(EmitContext& ctx); -void EmitSetVcc(EmitContext& ctx); -void EmitSetVccLo(EmitContext& ctx); -void EmitSetVccHi(EmitContext& ctx); -void EmitSetM0(EmitContext& ctx); -void EmitFPCmpClass32(EmitContext& ctx); -void EmitPrologue(EmitContext& ctx); -void EmitEpilogue(EmitContext& ctx); -void EmitDiscard(EmitContext& ctx); -void EmitDiscardCond(EmitContext& ctx, Id condition); -void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4); -Id EmitMemtime(EmitContext& ctx); -void EmitBarrier(EmitContext& ctx); -void EmitWorkgroupMemoryBarrier(EmitContext& ctx); -void EmitDeviceMemoryBarrier(EmitContext& ctx); -Id EmitGetUserData(EmitContext& ctx, IR::ScalarReg reg); -void EmitGetThreadBitScalarReg(EmitContext& ctx); -void EmitSetThreadBitScalarReg(EmitContext& ctx); -void EmitGetScalarRegister(EmitContext& ctx); -void EmitSetScalarRegister(EmitContext& ctx); -void EmitGetVectorRegister(EmitContext& ctx); -void EmitSetVectorRegister(EmitContext& ctx); -void EmitSetVirtualRegister(EmitContext& ctx); -void EmitGetVirtualRegister(EmitContext& ctx); -void EmitSetGotoVariable(EmitContext& ctx); -void EmitGetGotoVariable(EmitContext& ctx); -void EmitSetMaskLaneVariable(EmitContext& ctx); -void EmitGetMaskLaneVariable(EmitContext& ctx); -void EmitSetScc(EmitContext& ctx); -Id EmitReadConst(EmitContext& ctx, IR::Inst* inst, Id addr, Id offset); -Id EmitReadConstBuffer(EmitContext& ctx, u32 handle, Id index); -Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferU64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -void EmitStoreBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferU64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x2(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x3(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferF32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -void EmitStoreBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicIAdd64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicISub32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicSMin64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicUMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicUMin64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicSMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicSMax64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicUMax64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicInc32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitBufferAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address); -Id EmitBufferAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value); -Id EmitBufferAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value, - Id cmp_value); -Id EmitBufferAtomicFCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value, - Id cmp_value); -Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, u32 index); -Id EmitGetAttributeU1(EmitContext& ctx, IR::Attribute attr, u32 comp); -Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp); -void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 comp); -Id EmitGetTessGenericAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, Id comp_index); -void EmitSetTcsGenericAttribute(EmitContext& ctx, Id value, Id attr_index, Id comp_index); -Id EmitReadTcsGenericOuputAttribute(EmitContext& ctx, Id vertex_index, Id attr_index, - Id comp_index); -Id EmitGetPcLo(EmitContext& ctx, const IR::Value& value); -Id EmitGetPatch(EmitContext& ctx, IR::Patch patch); -void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value); -Id EmitWorkgroupId(EmitContext& ctx); -Id EmitLocalInvocationId(EmitContext& ctx); -Id EmitInvocationId(EmitContext& ctx); -Id EmitInvocationInfo(EmitContext& ctx); -Id EmitUndefU1(EmitContext& ctx); -Id EmitUndefU8(EmitContext& ctx); -Id EmitUndefU16(EmitContext& ctx); -Id EmitUndefU32(EmitContext& ctx); -Id EmitUndefU32x2(EmitContext& ctx); -Id EmitUndefU32x3(EmitContext& ctx); -Id EmitUndefU32x4(EmitContext& ctx); -Id EmitUndefF32(EmitContext& ctx); -Id EmitUndefU64(EmitContext& ctx); -Id EmitLoadSharedU16(EmitContext& ctx, Id offset); -Id EmitLoadSharedU32(EmitContext& ctx, Id offset); -Id EmitLoadSharedU64(EmitContext& ctx, Id offset); -void EmitWriteSharedU16(EmitContext& ctx, Id offset, Id value); -void EmitWriteSharedU32(EmitContext& ctx, Id offset, Id value); -void EmitWriteSharedU64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicIAdd32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicIAdd64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicUMax32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicUMax64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicSMax32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicSMax64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicUMin32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicUMin64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicSMin32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicSMin64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicAnd32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicAnd64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicOr32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicOr64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicXor64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicInc32(EmitContext& ctx, Id offset); -Id EmitSharedAtomicInc64(EmitContext& ctx, Id offset); -Id EmitSharedAtomicDec32(EmitContext& ctx, Id offset); -Id EmitSharedAtomicDec64(EmitContext& ctx, Id offset); -Id EmitSharedAtomicISub32(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicISub64(EmitContext& ctx, Id offset, Id value); -Id EmitSharedAtomicCmpSwap32(EmitContext& ctx, Id offset, Id value, Id cmp_value); -Id EmitSharedAtomicCmpSwap64(EmitContext& ctx, Id offset, Id value, Id cmp_value); - -Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); -Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); -Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); -Id EmitCompositeConstructU32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); -Id EmitCompositeExtractU32x2(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeExtractU32x3(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeExtractU32x4(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeInsertU32x2(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeInsertU32x3(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeInsertU32x4(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeShuffleU32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); -Id EmitCompositeShuffleU32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, - u32 comp2); -Id EmitCompositeShuffleU32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, - u32 comp2, u32 comp3); -Id EmitCompositeConstructF32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); -Id EmitCompositeConstructF32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); -Id EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); -Id EmitCompositeConstructF32x2x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); -Id EmitCompositeExtractF32x2(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeExtractF32x3(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeExtractF32x4(EmitContext& ctx, Id composite, u32 index); -Id EmitCompositeInsertF32x2(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeInsertF32x3(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeInsertF32x4(EmitContext& ctx, Id composite, Id object, u32 index); -Id EmitCompositeShuffleF32x2(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1); -Id EmitCompositeShuffleF32x3(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, - u32 comp2); -Id EmitCompositeShuffleF32x4(EmitContext& ctx, Id composite1, Id composite2, u32 comp0, u32 comp1, - u32 comp2, u32 comp3); -Id EmitSelectU1(EmitContext& ctx, Id cond, Id true_value, Id false_value); -Id EmitSelectU32(EmitContext& ctx, Id cond, Id true_value, Id false_value); -Id EmitSelectF32(EmitContext& ctx, Id cond, Id true_value, Id false_value); -Id EmitSelectU64(EmitContext& ctx, Id cond, Id true_value, Id false_value); -Id EmitBitCastU16F16(EmitContext& ctx, Id value); -Id EmitBitCastU32F32(EmitContext& ctx, Id value); -Id EmitBitCastF16U16(EmitContext& ctx, Id value); -Id EmitBitCastF32U32(EmitContext& ctx, Id value); -Id EmitPackUint2x32(EmitContext& ctx, Id value); -Id EmitUnpackUint2x32(EmitContext& ctx, Id value); -Id EmitPackDouble2x32(EmitContext& ctx, Id value); -Id EmitUnpackDouble2x32(EmitContext& ctx, Id value); -Id EmitPackUnorm2x16(EmitContext& ctx, Id value); -Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value); -Id EmitPackSnorm2x16(EmitContext& ctx, Id value); -Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value); -Id EmitPackUint2x16(EmitContext& ctx, Id value); -Id EmitUnpackUint2x16(EmitContext& ctx, Id value); -Id EmitPackSint2x16(EmitContext& ctx, Id value); -Id EmitUnpackSint2x16(EmitContext& ctx, Id value); -Id EmitPackHalf2x16(EmitContext& ctx, Id value); -Id EmitUnpackHalf2x16(EmitContext& ctx, Id value); -Id EmitPackUnorm4x8(EmitContext& ctx, Id value); -Id EmitUnpackUnorm4x8(EmitContext& ctx, Id value); -Id EmitPackSnorm4x8(EmitContext& ctx, Id value); -Id EmitUnpackSnorm4x8(EmitContext& ctx, Id value); -Id EmitPackUint4x8(EmitContext& ctx, Id value); -Id EmitUnpackUint4x8(EmitContext& ctx, Id value); -Id EmitPackSint4x8(EmitContext& ctx, Id value); -Id EmitUnpackSint4x8(EmitContext& ctx, Id value); -Id EmitPackUfloat10_11_11(EmitContext& ctx, Id value); -Id EmitUnpackUfloat10_11_11(EmitContext& ctx, Id value); -Id EmitPackUnorm2_10_10_10(EmitContext& ctx, Id value); -Id EmitUnpackUnorm2_10_10_10(EmitContext& ctx, Id value); -Id EmitPackSnorm2_10_10_10(EmitContext& ctx, Id value); -Id EmitUnpackSnorm2_10_10_10(EmitContext& ctx, Id value); -Id EmitPackUint2_10_10_10(EmitContext& ctx, Id value); -Id EmitUnpackUint2_10_10_10(EmitContext& ctx, Id value); -Id EmitPackSint2_10_10_10(EmitContext& ctx, Id value); -Id EmitUnpackSint2_10_10_10(EmitContext& ctx, Id value); -Id EmitFPAbs32(EmitContext& ctx, Id value); -Id EmitFPAbs64(EmitContext& ctx, Id value); -Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPSub32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); -Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c); -Id EmitFPMax32(EmitContext& ctx, Id a, Id b); -Id EmitFPMax64(EmitContext& ctx, Id a, Id b); -Id EmitFPMin32(EmitContext& ctx, Id a, Id b); -Id EmitFPMin64(EmitContext& ctx, Id a, Id b); -Id EmitFPMinTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitFPMaxTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitFPMedTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPDiv32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPDiv64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitFPNeg32(EmitContext& ctx, Id value); -Id EmitFPNeg64(EmitContext& ctx, Id value); -Id EmitFPSin(EmitContext& ctx, Id value); -Id EmitFPCos(EmitContext& ctx, Id value); -Id EmitFPExp2(EmitContext& ctx, Id value); -Id EmitFPPow(EmitContext& ctx, Id x, Id y); -Id EmitFPLdexp(EmitContext& ctx, Id value, Id exp); -Id EmitFPLog2(EmitContext& ctx, Id value); -Id EmitFPRecip32(EmitContext& ctx, Id value); -Id EmitFPRecip64(EmitContext& ctx, Id value); -Id EmitFPRecipSqrt32(EmitContext& ctx, Id value); -Id EmitFPRecipSqrt64(EmitContext& ctx, Id value); -Id EmitFPSqrt(EmitContext& ctx, Id value); -Id EmitFPSaturate32(EmitContext& ctx, Id value); -Id EmitFPSaturate64(EmitContext& ctx, Id value); -Id EmitFPClamp32(EmitContext& ctx, Id value, Id min_value, Id max_value); -Id EmitFPClamp64(EmitContext& ctx, Id value, Id min_value, Id max_value); -Id EmitFPRoundEven32(EmitContext& ctx, Id value); -Id EmitFPRoundEven64(EmitContext& ctx, Id value); -Id EmitFPFloor32(EmitContext& ctx, Id value); -Id EmitFPFloor64(EmitContext& ctx, Id value); -Id EmitFPCeil32(EmitContext& ctx, Id value); -Id EmitFPCeil64(EmitContext& ctx, Id value); -Id EmitFPTrunc32(EmitContext& ctx, Id value); -Id EmitFPTrunc64(EmitContext& ctx, Id value); -Id EmitFPFract32(EmitContext& ctx, Id value); -Id EmitFPFract64(EmitContext& ctx, Id value); -Id EmitFPFrexpSig32(EmitContext& ctx, Id value); -Id EmitFPFrexpSig64(EmitContext& ctx, Id value); -Id EmitFPFrexpExp32(EmitContext& ctx, Id value); -Id EmitFPFrexpExp64(EmitContext& ctx, Id value); -Id EmitFPOrdEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdNotEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdNotEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordNotEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordNotEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdLessThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdLessThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordLessThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordLessThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdGreaterThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdGreaterThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordGreaterThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordGreaterThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdLessThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdLessThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordLessThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordLessThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPOrdGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPUnordGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitFPIsNan32(EmitContext& ctx, Id value); -Id EmitFPIsNan64(EmitContext& ctx, Id value); -Id EmitFPIsInf32(EmitContext& ctx, Id value); -Id EmitFPIsInf64(EmitContext& ctx, Id value); -Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitIAdd64(EmitContext& ctx, Id a, Id b); -Id EmitISub32(EmitContext& ctx, Id a, Id b); -Id EmitISub64(EmitContext& ctx, Id a, Id b); -Id EmitSMulHi(EmitContext& ctx, Id a, Id b); -Id EmitUMulHi(EmitContext& ctx, Id a, Id b); -Id EmitIMul32(EmitContext& ctx, Id a, Id b); -Id EmitIMul64(EmitContext& ctx, Id a, Id b); -Id EmitSDiv32(EmitContext& ctx, Id a, Id b); -Id EmitUDiv32(EmitContext& ctx, Id a, Id b); -Id EmitSMod32(EmitContext& ctx, Id a, Id b); -Id EmitUMod32(EmitContext& ctx, Id a, Id b); -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 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, IR::Inst* inst, Id a, Id b); -Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitBitwiseOr64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitBitwiseXor64(EmitContext& ctx, IR::Inst* inst, Id a, Id b); -Id EmitBitFieldInsert32(EmitContext& ctx, Id base, Id insert, Id offset, Id count); -Id EmitBitFieldInsert64(EmitContext& ctx, Id base, Id insert, Id offset, Id count); -Id EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id count); -Id EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id count); -Id EmitBitReverse32(EmitContext& ctx, Id value); -Id EmitBitCount32(EmitContext& ctx, Id value); -Id EmitBitCount64(EmitContext& ctx, Id value); -Id EmitBitwiseNot32(EmitContext& ctx, Id value); -Id EmitBitwiseNot64(EmitContext& ctx, Id value); -Id EmitMaskedBitCount32(EmitContext& ctx, Id value, Id addend, bool hi); -Id EmitFindSMsb32(EmitContext& ctx, Id value); -Id EmitFindUMsb32(EmitContext& ctx, Id value); -Id EmitFindUMsb64(EmitContext& ctx, Id value); -Id EmitFindILsb32(EmitContext& ctx, Id value); -Id EmitFindILsb64(EmitContext& ctx, Id value); -Id EmitSMin32(EmitContext& ctx, Id a, Id b); -Id EmitUMin32(EmitContext& ctx, Id a, Id b); -Id EmitSMax32(EmitContext& ctx, Id a, Id b); -Id EmitUMax32(EmitContext& ctx, Id a, Id b); -Id EmitSMinTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitUMinTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitSMaxTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitUMaxTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitSMedTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitUMedTri32(EmitContext& ctx, Id a, Id b, Id c); -Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max); -Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max); -Id EmitSLessThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSLessThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitULessThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitULessThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitIEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitIEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSLessThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSLessThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitULessThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitULessThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSGreaterThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSGreaterThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitUGreaterThan32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitUGreaterThan64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitINotEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitINotEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitSGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitUGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs); -Id EmitUGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs); -Id EmitLogicalOr(EmitContext& ctx, Id a, Id b); -Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b); -Id EmitLogicalXor(EmitContext& ctx, Id a, Id b); -Id EmitLogicalNot(EmitContext& ctx, Id value); -Id EmitConvertS16F32(EmitContext& ctx, Id value); -Id EmitConvertS16F64(EmitContext& ctx, Id value); -Id EmitConvertS32F32(EmitContext& ctx, Id value); -Id EmitConvertS32F64(EmitContext& ctx, Id value); -Id EmitConvertS64F32(EmitContext& ctx, Id value); -Id EmitConvertS64F64(EmitContext& ctx, Id value); -Id EmitConvertU16F32(EmitContext& ctx, Id value); -Id EmitConvertU16F64(EmitContext& ctx, Id value); -Id EmitConvertU32F32(EmitContext& ctx, Id value); -Id EmitConvertU32F64(EmitContext& ctx, Id value); -Id EmitConvertU64F32(EmitContext& ctx, Id value); -Id EmitConvertU64F64(EmitContext& ctx, Id value); -Id EmitConvertU64U32(EmitContext& ctx, Id value); -Id EmitConvertU32U64(EmitContext& ctx, Id value); -Id EmitConvertF16F32(EmitContext& ctx, Id value); -Id EmitConvertF32F16(EmitContext& ctx, Id value); -Id EmitConvertF32F64(EmitContext& ctx, Id value); -Id EmitConvertF64F32(EmitContext& ctx, Id value); -Id EmitConvertF32S8(EmitContext& ctx, Id value); -Id EmitConvertF32S16(EmitContext& ctx, Id value); -Id EmitConvertF32S32(EmitContext& ctx, Id value); -Id EmitConvertF32S64(EmitContext& ctx, Id value); -Id EmitConvertF32U8(EmitContext& ctx, Id value); -Id EmitConvertF32U16(EmitContext& ctx, Id value); -Id EmitConvertF32U32(EmitContext& ctx, Id value); -Id EmitConvertF32U64(EmitContext& ctx, Id value); -Id EmitConvertF64S8(EmitContext& ctx, Id value); -Id EmitConvertF64S16(EmitContext& ctx, Id value); -Id EmitConvertF64S32(EmitContext& ctx, Id value); -Id EmitConvertF64S64(EmitContext& ctx, Id value); -Id EmitConvertF64U8(EmitContext& ctx, Id value); -Id EmitConvertF64U16(EmitContext& ctx, Id value); -Id EmitConvertF64U32(EmitContext& ctx, Id value); -Id EmitConvertF64U64(EmitContext& ctx, Id value); -Id EmitConvertU16U32(EmitContext& ctx, Id value); -Id EmitConvertU32U16(EmitContext& ctx, Id value); -Id EmitConvertU8U32(EmitContext& ctx, Id value); -Id EmitConvertU32U8(EmitContext& ctx, Id value); -Id EmitConvertS32S8(EmitContext& ctx, Id value); -Id EmitConvertS32S16(EmitContext& ctx, Id value); - -Id EmitImageHandle(EmitContext& ctx, Id, Id); -Id EmitImageSampleRaw(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address1, Id address2, - Id address3, Id address4); -Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias, - const IR::Value& offset); -Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, - const IR::Value& offset); -Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref, - Id bias, const IR::Value& offset); -Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref, - Id lod, const IR::Value& offset); -Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, - const IR::Value& offset); -Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, - const IR::Value& offset, Id dref); -Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod, bool skip_mips); -Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords); -Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id derivatives_dx, - Id derivatives_dy, const IR::Value& offset, const IR::Value& lod_clamp); -Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms); -void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod, Id ms, - Id color); - -Id EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicSMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicUMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicSMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicUMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicInc32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicDec32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value); -Id EmitImageAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value, - Id cmp_value); -Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id x, Id y, Id z); -Id EmitCubeFaceCoordS(EmitContext& ctx, IR::Inst* inst, Id x, Id y, Id z); -Id EmitCubeFaceCoordT(EmitContext& ctx, IR::Inst* inst, Id x, Id y, Id z); -Id EmitCubeFaceMajorAxis(EmitContext& ctx, IR::Inst* inst, Id x, Id y, Id z); -Id EmitLaneId(EmitContext& ctx); -Id EmitWarpId(EmitContext& ctx); -Id EmitQuadBroadcast(EmitContext& ctx, Id value, Id index); -Id EmitShuffle(EmitContext& ctx, Id value, Id index); -Id EmitShuffleXor(EmitContext& ctx, Id value, Id mask); -Id EmitReadFirstLane(EmitContext& ctx, Id value, Id exec); -Id EmitReadLane(EmitContext& ctx, Id value, Id lane); -Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane); -Id EmitBallot(EmitContext& ctx, Id bit); -Id EmitBallotFindLsb(EmitContext& ctx, Id mask); -Id EmitInverseBallot(EmitContext& ctx, Id mask); -Id EmitGroupAny(EmitContext& ctx, Id bit); -Id EmitDataAppend(EmitContext& ctx, Id gds_dw_offset, Id exec); -Id EmitDataConsume(EmitContext& ctx, Id gds_dw_offset, Id exec); - -void EmitEmitVertex(EmitContext& ctx); -void EmitEmitPrimitive(EmitContext& ctx); - -} // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp deleted file mode 100644 index 1453652..0000000 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ /dev/null @@ -1,461 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" -#include "shader_recompiler/backend/spirv/spirv_emit_context.h" - -namespace Shader::Backend::SPIRV { -namespace { -void SetZeroFlag(EmitContext& ctx, IR::Inst* inst, Id result) { - // IR::Inst* const zero{inst->GetAssociatedPseudoOperation(IR::Opcode::GetZeroFromOp)}; - // if (!zero) { - // return; - // } - // zero->SetDefinition(ctx.OpIEqual(ctx.U1[1], result, ctx.u32_zero_value)); - // zero->Invalidate(); -} - -void SetSignFlag(EmitContext& ctx, IR::Inst* inst, Id result) { - // IR::Inst* const sign{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSignFromOp)}; - // if (!sign) { - // return; - // } - // sign->SetDefinition(ctx.OpSLessThan(ctx.U1[1], result, ctx.u32_zero_value)); - // sign->Invalidate(); -} -} // Anonymous namespace - -Id EmitIAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - return ctx.OpIAdd(ctx.U32[1], a, b); - // Id result{}; - // if (IR::Inst* const carry{inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp)}) { - // const Id carry_type{ctx.TypeStruct(ctx.U32[1], ctx.U32[1])}; - // const Id carry_result{ctx.OpIAddCarry(carry_type, a, b)}; - // result = ctx.OpCompositeExtract(ctx.U32[1], carry_result, 0U); - - // const Id carry_value{ctx.OpCompositeExtract(ctx.U32[1], carry_result, 1U)}; - // carry->SetDefinition(ctx.OpINotEqual(ctx.U1[1][1], carry_value, ctx.u32_zero_value)); - // carry->Invalidate(); - //} else { - // result = ctx.OpIAdd(ctx.U32[1], a, b); - //} - // SetZeroFlag(ctx, inst, result); - // SetSignFlag(ctx, inst, result); - // if (IR::Inst * overflow{inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)}) { - // // https://stackoverflow.com/questions/55468823/how-to-detect-integer-overflow-in-c - // constexpr u32 s32_max{static_cast(std::numeric_limits::max())}; - // const Id is_positive{ctx.OpSGreaterThanEqual(ctx.U1[1], a, ctx.u32_zero_value)}; - // const Id sub_a{ctx.OpISub(ctx.U32[1], ctx.Const(s32_max), a)}; - - // const Id positive_test{ctx.OpSGreaterThan(ctx.U1[1], b, sub_a)}; - // const Id negative_test{ctx.OpSLessThan(ctx.U1[1], b, sub_a)}; - // const Id carry_flag{ctx.OpSelect(ctx.U1[1], is_positive, positive_test, negative_test)}; - // overflow->SetDefinition(carry_flag); - // overflow->Invalidate(); - //} - // return result; -} - -Id EmitIAdd64(EmitContext& ctx, Id a, Id b) { - return ctx.OpIAdd(ctx.U64, a, b); -} - -Id EmitISub32(EmitContext& ctx, Id a, Id b) { - return ctx.OpISub(ctx.U32[1], a, b); -} - -Id EmitISub64(EmitContext& ctx, Id a, Id b) { - return ctx.OpISub(ctx.U64, a, b); -} - -Id EmitSMulHi(EmitContext& ctx, Id a, Id b) { - const auto signed_a{ctx.OpBitcast(ctx.S32[1], a)}; - const auto signed_b{ctx.OpBitcast(ctx.S32[1], b)}; - const auto mul_ext{ctx.OpSMulExtended(ctx.full_result_i32x2, signed_a, signed_b)}; - const auto signed_hi{ctx.OpCompositeExtract(ctx.S32[1], mul_ext, 1)}; - return ctx.OpBitcast(ctx.U32[1], signed_hi); -} - -Id EmitUMulHi(EmitContext& ctx, Id a, Id b) { - const auto mul_ext{ctx.OpUMulExtended(ctx.full_result_u32x2, a, b)}; - return ctx.OpCompositeExtract(ctx.U32[1], mul_ext, 1); -} - -Id EmitIMul32(EmitContext& ctx, Id a, Id b) { - return ctx.OpIMul(ctx.U32[1], a, b); -} - -Id EmitIMul64(EmitContext& ctx, Id a, Id b) { - return ctx.OpIMul(ctx.U64, a, b); -} - -Id EmitSDiv32(EmitContext& ctx, Id a, Id b) { - return ctx.OpSDiv(ctx.U32[1], a, b); -} - -Id EmitUDiv32(EmitContext& ctx, Id a, Id b) { - return ctx.OpUDiv(ctx.U32[1], a, b); -} - -Id EmitSMod32(EmitContext& ctx, Id a, Id b) { - return ctx.OpSMod(ctx.U32[1], a, b); -} - -Id EmitUMod32(EmitContext& ctx, Id a, Id b) { - return ctx.OpUMod(ctx.U32[1], a, b); -} - -Id EmitINeg32(EmitContext& ctx, Id value) { - return ctx.OpSNegate(ctx.U32[1], value); -} - -Id EmitINeg64(EmitContext& ctx, Id value) { - return ctx.OpSNegate(ctx.U64, value); -} - -Id EmitIAbs32(EmitContext& ctx, Id value) { - return ctx.OpSAbs(ctx.U32[1], value); -} - -Id EmitShiftLeftLogical32(EmitContext& ctx, Id base, Id shift) { - return ctx.OpShiftLeftLogical(ctx.U32[1], base, shift); -} - -Id EmitShiftLeftLogical64(EmitContext& ctx, Id base, Id shift) { - return ctx.OpShiftLeftLogical(ctx.U64, base, shift); -} - -Id EmitShiftRightLogical32(EmitContext& ctx, Id base, Id shift) { - return ctx.OpShiftRightLogical(ctx.U32[1], base, shift); -} - -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, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseAnd(ctx.U32[1], a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitwiseAnd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseAnd(ctx.U64, a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitwiseOr32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseOr(ctx.U32[1], a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitwiseOr64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseOr(ctx.U64, a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitwiseXor32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseXor(ctx.U32[1], a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitwiseXor64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) { - const Id result{ctx.OpBitwiseXor(ctx.U64, a, b)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitFieldInsert32(EmitContext& ctx, Id base, Id insert, Id offset, Id count) { - return ctx.OpBitFieldInsert(ctx.U32[1], base, insert, offset, count); -} - -Id EmitBitFieldInsert64(EmitContext& ctx, Id base, Id insert, Id offset, Id count) { - // Vulkan restricts OpBitFieldInsert to a 32-bit base, so build the field mask with - // 64-bit shifts and insert with bitwise operations. - const Id all_ones{ctx.Constant(ctx.U64, ~0ULL)}; - const Id ones{ctx.OpShiftRightLogical(ctx.U64, all_ones, - ctx.OpISub(ctx.U32[1], ctx.ConstU32(64U), count))}; - const Id is_empty{ctx.OpIEqual(ctx.U1[1], count, ctx.u32_zero_value)}; - const Id field{ctx.OpSelect(ctx.U64, is_empty, ctx.u64_zero_value, ones)}; - const Id mask{ctx.OpShiftLeftLogical(ctx.U64, field, offset)}; - const Id kept{ctx.OpBitwiseAnd(ctx.U64, base, ctx.OpNot(ctx.U64, mask))}; - const Id inserted{ - ctx.OpBitwiseAnd(ctx.U64, ctx.OpShiftLeftLogical(ctx.U64, insert, offset), mask)}; - return ctx.OpBitwiseOr(ctx.U64, kept, inserted); -} - -Id EmitBitFieldSExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id count) { - const Id result{ctx.OpBitFieldSExtract(ctx.U32[1], base, offset, count)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitFieldUExtract(EmitContext& ctx, IR::Inst* inst, Id base, Id offset, Id count) { - const Id result{ctx.OpBitFieldUExtract(ctx.U32[1], base, offset, count)}; - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitBitReverse32(EmitContext& ctx, Id value) { - return ctx.OpBitReverse(ctx.U32[1], value); -} - -Id EmitBitCount32(EmitContext& ctx, Id value) { - return ctx.OpBitCount(ctx.U32[1], value); -} - -Id EmitBitCount64(EmitContext& ctx, Id value) { - // Vulkan restricts some bitwise operations to 32-bit only, so decompose into - // two 32-bit values and add the result. - const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; - const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; - const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; - const Id lo_count{ctx.OpBitCount(ctx.U32[1], lo)}; - const Id hi_count{ctx.OpBitCount(ctx.U32[1], hi)}; - return ctx.OpIAdd(ctx.U32[1], lo_count, hi_count); -} - -Id EmitBitwiseNot32(EmitContext& ctx, Id value) { - return ctx.OpNot(ctx.U32[1], value); -} - -Id EmitBitwiseNot64(EmitContext& ctx, Id value) { - return ctx.OpNot(ctx.U64, value); -} - -Id EmitFindSMsb32(EmitContext& ctx, Id value) { - return ctx.OpFindSMsb(ctx.U32[1], value); -} - -Id EmitFindUMsb32(EmitContext& ctx, Id value) { - return ctx.OpFindUMsb(ctx.U32[1], value); -} - -Id EmitFindUMsb64(EmitContext& ctx, Id value) { - // Vulkan restricts some bitwise operations to 32-bit only, so decompose into - // two 32-bit values and select the correct result. - const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; - const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; - const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; - const Id hi_msb{ctx.OpFindUMsb(ctx.U32[1], hi)}; - const Id lo_msb{ctx.OpFindUMsb(ctx.U32[1], lo)}; - const Id found_hi{ctx.OpINotEqual(ctx.U1[1], hi_msb, ctx.ConstU32(u32(-1)))}; - const Id shifted_hi{ctx.OpIAdd(ctx.U32[1], hi_msb, ctx.ConstU32(32u))}; - // value == 0 case is checked in IREmitter - return ctx.OpSelect(ctx.U32[1], found_hi, shifted_hi, lo_msb); -} - -Id EmitFindILsb32(EmitContext& ctx, Id value) { - return ctx.OpFindILsb(ctx.U32[1], value); -} - -Id EmitFindILsb64(EmitContext& ctx, Id value) { - // Vulkan restricts some bitwise operations to 32-bit only, so decompose into - // two 32-bit values and select the correct result. - const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; - const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; - const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; - const Id lo_lsb{ctx.OpFindILsb(ctx.U32[1], lo)}; - const Id hi_lsb{ctx.OpFindILsb(ctx.U32[1], hi)}; - const Id not_found{ctx.ConstU32(u32(-1))}; - const Id found_lo{ctx.OpINotEqual(ctx.U1[1], lo_lsb, not_found)}; - const Id found_hi{ctx.OpINotEqual(ctx.U1[1], hi_lsb, not_found)}; - // The high half holds bits 32..63; -1 when no bit is set at all. - const Id hi_pos{ctx.OpSelect(ctx.U32[1], found_hi, - ctx.OpIAdd(ctx.U32[1], hi_lsb, ctx.ConstU32(32U)), not_found)}; - return ctx.OpSelect(ctx.U32[1], found_lo, lo_lsb, hi_pos); -} - -Id EmitSMin32(EmitContext& ctx, Id a, Id b) { - return ctx.OpSMin(ctx.U32[1], a, b); -} - -Id EmitUMin32(EmitContext& ctx, Id a, Id b) { - return ctx.OpUMin(ctx.U32[1], a, b); -} - -Id EmitSMax32(EmitContext& ctx, Id a, Id b) { - return ctx.OpSMax(ctx.U32[1], a, b); -} - -Id EmitUMax32(EmitContext& ctx, Id a, Id b) { - return ctx.OpUMax(ctx.U32[1], a, b); -} - -Id EmitSMinTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpSMin3AMD(ctx.U32[1], a, b, c); - } - return ctx.OpSMin(ctx.U32[1], a, ctx.OpSMin(ctx.U32[1], b, c)); -} - -Id EmitUMinTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpUMin3AMD(ctx.U32[1], a, b, c); - } - return ctx.OpUMin(ctx.U32[1], a, ctx.OpUMin(ctx.U32[1], b, c)); -} - -Id EmitSMaxTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpSMax3AMD(ctx.U32[1], a, b, c); - } - return ctx.OpSMax(ctx.U32[1], a, ctx.OpSMax(ctx.U32[1], b, c)); -} - -Id EmitUMaxTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpUMax3AMD(ctx.U32[1], a, b, c); - } - return ctx.OpUMax(ctx.U32[1], a, ctx.OpUMax(ctx.U32[1], b, c)); -} - -Id EmitSMedTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpSMid3AMD(ctx.U32[1], a, b, c); - } - const Id mmx{ctx.OpSMin(ctx.U32[1], ctx.OpSMax(ctx.U32[1], a, b), c)}; - return ctx.OpSMax(ctx.U32[1], ctx.OpSMin(ctx.U32[1], a, b), mmx); -} - -Id EmitUMedTri32(EmitContext& ctx, Id a, Id b, Id c) { - if (ctx.profile.supports_trinary_minmax) { - return ctx.OpUMid3AMD(ctx.U32[1], a, b, c); - } - const Id mmx{ctx.OpUMin(ctx.U32[1], ctx.OpUMax(ctx.U32[1], a, b), c)}; - return ctx.OpUMax(ctx.U32[1], ctx.OpUMin(ctx.U32[1], a, b), mmx); -} - -Id EmitSClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { - Id result{}; - if (ctx.profile.has_broken_spirv_clamp) { - value = ctx.OpBitcast(ctx.S32[1], value); - min = ctx.OpBitcast(ctx.S32[1], min); - max = ctx.OpBitcast(ctx.S32[1], max); - result = ctx.OpSMax(ctx.S32[1], ctx.OpSMin(ctx.S32[1], value, max), min); - result = ctx.OpBitcast(ctx.U32[1], result); - } else { - result = ctx.OpSClamp(ctx.U32[1], value, min, max); - } - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitUClamp32(EmitContext& ctx, IR::Inst* inst, Id value, Id min, Id max) { - Id result{}; - if (ctx.profile.has_broken_spirv_clamp) { - result = ctx.OpUMax(ctx.U32[1], ctx.OpUMin(ctx.U32[1], value, max), min); - } else { - result = ctx.OpUClamp(ctx.U32[1], value, min, max); - } - SetZeroFlag(ctx, inst, result); - SetSignFlag(ctx, inst, result); - return result; -} - -Id EmitSLessThan32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSLessThan(ctx.U1[1], lhs, rhs); -} - -Id EmitSLessThan64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSLessThan(ctx.U1[1], lhs, rhs); -} - -Id EmitULessThan32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpULessThan(ctx.U1[1], lhs, rhs); -} - -Id EmitULessThan64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpULessThan(ctx.U1[1], lhs, rhs); -} - -Id EmitIEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpIEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitIEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpIEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitSLessThanEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSLessThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitSLessThanEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSLessThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitULessThanEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpULessThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitULessThanEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpULessThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitSGreaterThan32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSGreaterThan(ctx.U1[1], lhs, rhs); -} - -Id EmitSGreaterThan64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSGreaterThan(ctx.U1[1], lhs, rhs); -} - -Id EmitUGreaterThan32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpUGreaterThan(ctx.U1[1], lhs, rhs); -} - -Id EmitUGreaterThan64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpUGreaterThan(ctx.U1[1], lhs, rhs); -} - -Id EmitINotEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpINotEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitINotEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpINotEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitSGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSGreaterThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitSGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpSGreaterThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitUGreaterThanEqual32(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpUGreaterThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitUGreaterThanEqual64(EmitContext& ctx, Id lhs, Id rhs) { - return ctx.OpUGreaterThanEqual(ctx.U1[1], lhs, rhs); -} - -Id EmitMaskedBitCount32(EmitContext& ctx, Id value, Id addend, bool hi) { - UNREACHABLE_MSG("Unreachable instruction"); -} - -} // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp deleted file mode 100644 index d79896a..0000000 --- a/src/shader_recompiler/backend/spirv/emit_spirv_undefined.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" -#include "shader_recompiler/backend/spirv/spirv_emit_context.h" - -namespace Shader::Backend::SPIRV { - -Id EmitUndefU1(EmitContext& ctx) { - return ctx.OpUndef(ctx.U1[1]); -} - -Id EmitUndefU8(EmitContext&) { - UNREACHABLE_MSG("SPIR-V Instruction"); -} - -Id EmitUndefU16(EmitContext&) { - UNREACHABLE_MSG("SPIR-V Instruction"); -} - -Id EmitUndefU32(EmitContext& ctx) { - return ctx.OpUndef(ctx.U32[1]); -} - -Id EmitUndefU32x2(EmitContext& ctx) { - return ctx.OpUndef(ctx.U32[2]); -} - -Id EmitUndefU32x3(EmitContext& ctx) { - return ctx.OpUndef(ctx.U32[3]); -} - -Id EmitUndefU32x4(EmitContext& ctx) { - return ctx.OpUndef(ctx.U32[4]); -} - -Id EmitUndefF32(EmitContext& ctx) { - return ctx.OpUndef(ctx.F32[1]); -} - -Id EmitUndefU64(EmitContext& ctx) { - return ctx.OpUndef(ctx.U64); -} - -} // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp deleted file mode 100644 index c2547af..0000000 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" -#include "shader_recompiler/backend/spirv/spirv_emit_context.h" - -namespace Shader::Backend::SPIRV { - -Id SubgroupScope(EmitContext& ctx) { - return ctx.ConstU32(static_cast(spv::Scope::Subgroup)); -} - -Id EmitWarpId(EmitContext& ctx) { - UNREACHABLE(); -} - -Id EmitLaneId(EmitContext& ctx) { - return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id); -} - -Id EmitQuadBroadcast(EmitContext& ctx, Id value, Id index) { - return ctx.OpGroupNonUniformQuadBroadcast(ctx.U32[1], SubgroupScope(ctx), value, index); -} - -Id EmitReadFirstLane(EmitContext& ctx, Id value, Id exec) { - // The first lane with EXEC set, lane 0 when EXEC is empty. - const Id ballot{ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), exec)}; - const Id lsb{ctx.OpGroupNonUniformBallotFindLSB(ctx.U32[1], SubgroupScope(ctx), ballot)}; - const Id any{ - ctx.OpINotEqual(ctx.U1[1], - ctx.OpBitwiseOr(ctx.U32[1], ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U), - ctx.OpCompositeExtract(ctx.U32[1], ballot, 1U)), - ctx.u32_zero_value)}; - const Id lane{ctx.OpSelect(ctx.U32[1], any, lsb, ctx.u32_zero_value)}; - return ctx.OpGroupNonUniformBroadcast(ctx.U32[1], SubgroupScope(ctx), value, lane); -} - -Id EmitShuffle(EmitContext& ctx, Id value, Id index) { - return ctx.OpGroupNonUniformShuffle(ctx.U32[1], SubgroupScope(ctx), value, index); -} - -Id EmitShuffleXor(EmitContext& ctx, Id value, Id mask) { - return ctx.OpGroupNonUniformShuffleXor(ctx.U32[1], SubgroupScope(ctx), value, mask); -} - -Id EmitReadLane(EmitContext& ctx, Id value, Id lane) { - return ctx.OpGroupNonUniformBroadcast(ctx.U32[1], SubgroupScope(ctx), value, lane); -} - -Id EmitWriteLane(EmitContext& ctx, Id value, Id write_value, u32 lane) { - return ctx.u32_zero_value; -} - -Id EmitBallot(EmitContext& ctx, Id bit) { - const Id ballot{ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), bit)}; - return ctx.OpBitcast(ctx.U64, ctx.OpVectorShuffle(ctx.U32[2], ballot, ballot, 0, 1)); -} - -Id EmitBallotFindLsb(EmitContext& ctx, Id mask) { - const Id value{ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpBitcast(ctx.U32[2], mask), - ctx.u32_zero_value, ctx.u32_zero_value)}; - return ctx.OpGroupNonUniformBallotFindLSB(ctx.U32[1], SubgroupScope(ctx), value); -} - -Id EmitInverseBallot(EmitContext& ctx, Id mask) { - const Id value{ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpBitcast(ctx.U32[2], mask), - ctx.u32_zero_value, ctx.u32_zero_value)}; - return ctx.OpGroupNonUniformInverseBallot(ctx.U1[1], SubgroupScope(ctx), value); -} - -Id EmitGroupAny(EmitContext& ctx, Id bit) { - return ctx.OpGroupNonUniformAny(ctx.U1[1], SubgroupScope(ctx), bit); -} - -} // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp deleted file mode 100644 index b666a9d..0000000 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ /dev/null @@ -1,650 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include "common/assert.h" -#include "common/logging/log.h" -#include "shader_recompiler/frontend/control_flow_graph.h" -#include "shader_recompiler/ir/condition.h" - -namespace Shader::Gcn { - -struct Compare { - bool operator()(const Block& lhs, u32 rhs) const noexcept { - return lhs.begin < rhs; - } - - bool operator()(u32 lhs, const Block& rhs) const noexcept { - return lhs < rhs.begin; - } - - bool operator()(const Block& lhs, const Block& rhs) const noexcept { - return lhs.begin < rhs.begin; - } -}; - -static IR::Condition MakeCondition(const GcnInst& inst) { - if (inst.IsCmpx()) { - return IR::Condition::Execnz; - } - - switch (inst.opcode) { - case Opcode::S_CBRANCH_SCC0: - return IR::Condition::Scc0; - case Opcode::S_CBRANCH_SCC1: - return IR::Condition::Scc1; - case Opcode::S_CBRANCH_VCCZ: - return IR::Condition::Vccz; - case Opcode::S_CBRANCH_VCCNZ: - return IR::Condition::Vccnz; - case Opcode::S_CBRANCH_EXECZ: - return IR::Condition::Execz; - case Opcode::S_CBRANCH_EXECNZ: - return IR::Condition::Execnz; - default: - return IR::Condition::True; - } -} - -static bool IgnoresExecMask(const GcnInst& inst) { - // EXEC mask does not affect scalar instructions or branches. Exports run in every lane, a - // fragment export discards the lanes with EXEC clear. - switch (inst.category) { - case InstCategory::ScalarALU: - case InstCategory::ScalarMemory: - case InstCategory::FlowControl: - case InstCategory::Export: - return true; - default: - break; - } - // Compares run in every lane, they clear the bits of the lanes with EXEC clear themselves. - if (inst.opcode >= Opcode::V_CMP_F_F32 && inst.opcode <= Opcode::V_CMPX_T_U64) { - return true; - } - // Read/Write Lane instructions are not affected either. - switch (inst.opcode) { - case Opcode::V_READLANE_B32: - case Opcode::V_WRITELANE_B32: - case Opcode::V_READFIRSTLANE_B32: - return true; - default: - break; - } - return false; -} - -static std::optional ResolveSetPcTarget(std::span list, u32 setpc_index, - std::span pc_map) { - if (setpc_index < 3) { - return std::nullopt; - } - - const auto& getpc = list[setpc_index - 3]; - const auto& arith = list[setpc_index - 2]; - const auto& setpc = list[setpc_index]; - - if (getpc.opcode != Opcode::S_GETPC_B64 || - !(arith.opcode == Opcode::S_ADD_U32 || arith.opcode == Opcode::S_SUB_U32) || - setpc.opcode != Opcode::S_SETPC_B64) - return std::nullopt; - - if (getpc.dst[0].code != setpc.src[0].code || arith.dst[0].code != setpc.src[0].code) - return std::nullopt; - - if (arith.src_count < 2 || arith.src[1].field != OperandField::LiteralConst) - return std::nullopt; - - const u32 imm = arith.src[1].code; - - const s32 signed_offset = - (arith.opcode == Opcode::S_ADD_U32) ? static_cast(imm) : -static_cast(imm); - - const u32 base_pc = pc_map[setpc_index - 3] + getpc.length; - - const u32 result_pc = static_cast(static_cast(base_pc) + signed_offset); - LOG_DEBUG(Render_Recompiler, "SetPC target: {} + {} = {}", base_pc, signed_offset, result_pc); - return result_pc & ~0x3u; -} - -static constexpr size_t LabelReserveSize = 32; - -CFG::CFG(Common::ObjectPool& block_pool_, std::span inst_list_) - : block_pool{block_pool_}, inst_list{inst_list_} { - index_to_pc.resize(inst_list.size() + 1); - labels.reserve(LabelReserveSize); - EmitLabels(); - EmitBlocks(); - LinkBlocks(); - SplitDivergenceScopes(); - RemoveUnreachableBlocks(); -} - -void CFG::EmitLabels() { - // Always set a label at entry point. - u32 pc = 0; - AddLabel(pc); - - // Iterate instruction list and add labels to branch targets. - for (u32 i = 0; i < inst_list.size(); i++) { - index_to_pc[i] = pc; - const GcnInst inst = inst_list[i]; - if (inst.IsUnconditionalBranch()) { - u32 target = inst.BranchTarget(pc); - if (inst.opcode == Opcode::S_SETPC_B64) { - if (auto t = ResolveSetPcTarget(inst_list, i, index_to_pc)) { - target = *t; - } else { - ASSERT_MSG( - false, - "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " - "instructions not recognized or invalid pattern", - pc, i); - } - } - AddLabel(target); - // Emit this label so that the block ends with the branching instruction - AddLabel(pc + inst.length); - } else if (inst.IsConditionalBranch()) { - const u32 true_label = inst.BranchTarget(pc); - const u32 false_label = pc + inst.length; - if (true_label != false_label) { - AddLabel(true_label); - AddLabel(false_label); - } - } else if (inst.opcode == Opcode::S_ENDPGM) { - const u32 next_label = pc + inst.length; - AddLabel(next_label); - } - - pc += inst.length; - } - index_to_pc[inst_list.size()] = pc; - - // Sort labels to make sure block insertion is correct. - std::ranges::sort(labels); -} - -// Instructions without any effect, they can stay inside an EXEC scope. -static bool IsExecNeutral(const GcnInst& inst) { - switch (inst.opcode) { - case Opcode::S_NOP: - case Opcode::S_WAITCNT: - case Opcode::S_SETPRIO: - return true; - default: - return false; - } -} - -static bool IsSaveExec(const GcnInst& inst) { - return inst.opcode >= Opcode::S_AND_SAVEEXEC_B64 && inst.opcode <= Opcode::S_XNOR_SAVEEXEC_B64; -} - -static bool WritesExec(const GcnInst& inst) { - // S_WQM_B64 is translated as a no-op, it does not change the EXEC of an invocation. - if (inst.opcode == Opcode::S_WQM_B64) { - return false; - } - return IsSaveExec(inst) || inst.IsCmpx() || - (inst.dst_count > 0 && (inst.dst[0].field == OperandField::ExecLo || - inst.dst[0].field == OperandField::ExecHi)); -} - -// Registers written by a scalar memory instruction. -static u32 ScalarLoadWidth(Opcode opcode) { - switch (opcode) { - case Opcode::S_LOAD_DWORD: - case Opcode::S_BUFFER_LOAD_DWORD: - return 1; - case Opcode::S_LOAD_DWORDX2: - case Opcode::S_BUFFER_LOAD_DWORDX2: - case Opcode::S_MEMTIME: - return 2; - case Opcode::S_LOAD_DWORDX4: - case Opcode::S_BUFFER_LOAD_DWORDX4: - return 4; - case Opcode::S_LOAD_DWORDX8: - case Opcode::S_BUFFER_LOAD_DWORDX8: - return 8; - default: - return 16; - } -} - -namespace { -// What is known about EXEC at a program point: whether every lane that executes it has its EXEC -// bit set, and which registers hold a half of a copy of such a full mask. A tag is -// (copy id << 1) | half; the copy id is the index of the instruction that saved it. -struct ExecState { - bool full{}; - std::array sgpr_tag{}; // SGPRs and VCC (106, 107) - std::map lane_tag{}; // VGPR lanes holding a spilled half: vgpr * 64 + lane - - bool operator==(const ExecState&) const = default; - - bool HoldsFullCopy(u32 reg) const { - return reg + 1 < sgpr_tag.size() && sgpr_tag[reg] != 0 && (sgpr_tag[reg] & 1) == 0 && - sgpr_tag[reg + 1] == sgpr_tag[reg] + 1; - } - - static ExecState Merge(const ExecState& a, const ExecState& b) { - ExecState merged{.full = a.full && b.full}; - for (u32 i = 0; i < merged.sgpr_tag.size(); ++i) { - merged.sgpr_tag[i] = a.sgpr_tag[i] == b.sgpr_tag[i] ? a.sgpr_tag[i] : 0; - } - for (const auto& [key, tag] : a.lane_tag) { - const auto it = b.lane_tag.find(key); - if (it != b.lane_tag.end() && it->second == tag) { - merged.lane_tag.emplace(key, tag); - } - } - return merged; - } -}; -} // Anonymous namespace - -// The value of an inline integer constant operand, if it is one. -static std::optional InlineInt(const InstOperand& op) { - if (op.field == OperandField::ConstZero) { - return 0; - } - if (op.field == OperandField::SignedConstIntPos) { - return op.code - static_cast(OperandField::ConstZero); - } - return std::nullopt; -} - -static void ExecTransfer(const GcnInst& inst, u32 index, ExecState& state) { - const bool full_before = state.full; - const auto is_full_copy = [&](const InstOperand& op) { - return (op.field == OperandField::ScalarGPR || op.field == OperandField::VccLo) && - state.HoldsFullCopy(op.code); - }; - if (WritesExec(inst)) { - // Restoring a copy of the full mask, s_mov_b64 exec, -1 and the s_or_b64 exec, exec, copy - // that ends an if/else make EXEC full again; any other write can leave lanes off. - bool full = false; - if (inst.opcode == Opcode::S_MOV_B64) { - full = - is_full_copy(inst.src[0]) || - (inst.src[0].field == OperandField::SignedConstIntNeg && inst.src[0].code == 193); - } else if (inst.opcode == Opcode::S_OR_B64) { - full = is_full_copy(inst.src[0]) || is_full_copy(inst.src[1]); - } else if (inst.opcode == Opcode::S_ORN2_SAVEEXEC_B64) { - // EXEC = src | ~EXEC: with src = EXEC every lane is on. - full = inst.src[0].field == OperandField::ExecLo || is_full_copy(inst.src[0]); - } else if (inst.opcode == Opcode::S_AND_B64) { - // Ending whole quad mode: a full EXEC and a copy of the full mask stay full. - const auto is_exec = [](const InstOperand& op) { - return op.field == OperandField::ExecLo; - }; - full = full_before && ((is_exec(inst.src[0]) && is_full_copy(inst.src[1])) || - (is_exec(inst.src[1]) && is_full_copy(inst.src[0]))); - } - state.full = full; - } - - // A half of a copy moved through a VGPR lane: v_writelane / v_readlane with a constant lane. - if (inst.opcode == Opcode::V_READLANE_B32 && inst.dst[0].field == OperandField::ScalarGPR && - inst.dst[0].code < 128) { - const auto lane = InlineInt(inst.src[1]); - u32 tag = 0; - if (lane && inst.src[0].field == OperandField::VectorGPR) { - const auto it = state.lane_tag.find(inst.src[0].code * 64 + *lane); - tag = it != state.lane_tag.end() ? it->second : 0; - } - state.sgpr_tag[inst.dst[0].code] = tag; - return; - } - if (inst.opcode == Opcode::V_WRITELANE_B32 && inst.dst[0].field == OperandField::VectorGPR) { - const auto lane = InlineInt(inst.src[1]); - if (!lane) { - std::erase_if(state.lane_tag, - [&](const auto& entry) { return entry.first / 64 == inst.dst[0].code; }); - return; - } - const u32 key = inst.dst[0].code * 64 + *lane; - const bool from_sgpr = inst.src[0].field == OperandField::ScalarGPR || - inst.src[0].field == OperandField::VccLo || - inst.src[0].field == OperandField::VccHi; - const u32 tag = from_sgpr && inst.src[0].code < 128 ? state.sgpr_tag[inst.src[0].code] : 0; - if (tag != 0) { - state.lane_tag[key] = tag; - } else { - state.lane_tag.erase(key); - } - return; - } - - // Registers written here no longer hold a half of a copy. Every destination slot is checked: - // an implicit VCC write is stored in dst[1] without being counted in dst_count. - for (const InstOperand& dst : inst.dst) { - if (dst.field == OperandField::VccLo || dst.field == OperandField::VccHi) { - state.sgpr_tag[static_cast(OperandField::VccLo)] = 0; - state.sgpr_tag[static_cast(OperandField::VccHi)] = 0; - continue; - } - if (dst.field == OperandField::VectorGPR) { - // Vector memory writes up to four VGPRs (dwordx4, four image components, read2_b64). - u32 vwidth = 1; - if (inst.category == InstCategory::VectorMemory || - inst.category == InstCategory::DataShare) { - vwidth = 4; - } else if (dst.type == ScalarType::Uint64 || dst.type == ScalarType::Sint64 || - dst.type == ScalarType::Float64) { - vwidth = 2; - } - std::erase_if(state.lane_tag, [&](const auto& entry) { - return entry.first / 64 >= dst.code && entry.first / 64 < dst.code + vwidth; - }); - continue; - } - if (dst.field != OperandField::ScalarGPR) { - continue; - } - u32 width = 2; - if (inst.category == InstCategory::ScalarMemory) { - width = ScalarLoadWidth(inst.opcode); - } else if (dst.type == ScalarType::Uint32 || dst.type == ScalarType::Sint32 || - dst.type == ScalarType::Float32 || dst.type == ScalarType::Uint16 || - dst.type == ScalarType::Sint16 || dst.type == ScalarType::Float16) { - width = 1; - } - for (u32 reg = dst.code; reg < std::min(dst.code + width, 128); ++reg) { - state.sgpr_tag[reg] = 0; - } - } - // A save of the full mask: saveexec stores the old EXEC, as does s_mov_b64 sdst, exec. - if (full_before && inst.dst_count > 0 && - (inst.dst[0].field == OperandField::ScalarGPR || - inst.dst[0].field == OperandField::VccLo) && - inst.dst[0].code + 1 < 128 && - (IsSaveExec(inst) || - (inst.opcode == Opcode::S_MOV_B64 && inst.src[0].field == OperandField::ExecLo))) { - state.sgpr_tag[inst.dst[0].code] = (index + 1) << 1; - state.sgpr_tag[inst.dst[0].code + 1] = ((index + 1) << 1) | 1; - } -} - -void CFG::SplitDivergenceScopes() { - // Which instructions can run with lanes off in EXEC: forward over the CFG from the entry, - // where EXEC is full; paths merge to "partial" when any of them is. - std::unordered_map block_in; - block_in[&*blocks.begin()] = ExecState{.full = true}; - for (bool changed = true; changed;) { - changed = false; - for (const Block& blk : blocks) { - const auto it = block_in.find(&blk); - if (it == block_in.end()) { - continue; - } - ExecState state = it->second; - for (u32 i = blk.begin_index; i <= blk.end_index; ++i) { - ExecTransfer(inst_list[i], i, state); - } - for (const Block* succ : {blk.branch_true, blk.branch_false}) { - if (!succ) { - continue; - } - // A per-lane EXEC branch sends the lanes with EXEC set one way: EXEC is set in - // every lane on that edge, and clear in every lane on the other. - ExecState edge = state; - if (blk.cond == IR::Condition::Execz || blk.cond == IR::Condition::Execnz) { - const bool exec_set_edge = - (blk.cond == IR::Condition::Execnz) == (succ == blk.branch_true); - edge.full = exec_set_edge; - } - const auto [succ_it, inserted] = block_in.try_emplace(succ, edge); - if (inserted) { - changed = true; - continue; - } - const ExecState merged = ExecState::Merge(succ_it->second, edge); - if (merged != succ_it->second) { - succ_it->second = merged; - changed = true; - } - } - } - } - std::vector exec_partial(inst_list.size(), false); - for (const Block& blk : blocks) { - const auto it = block_in.find(&blk); - if (it == block_in.end()) { - continue; - } - ExecState state = it->second; - for (u32 i = blk.begin_index; i <= blk.end_index; ++i) { - exec_partial[i] = !state.full; - ExecTransfer(inst_list[i], i, state); - } - } - const auto is_masked = [&](u32 i) { return exec_partial[i] && !IgnoresExecMask(inst_list[i]); }; - - // EXEC masks the vector instructions only. Each run of them that can execute with lanes off - // goes into its own block, which only the lanes with EXEC set enter; scalar instructions and - // branches stay outside and run in every lane. - for (auto blk = blocks.begin(); blk != blocks.end(); blk++) { - if (blk->is_exec_scope) { - continue; - } - u32 first = blk->begin_index; - while (first <= blk->end_index && !is_masked(first)) { - ++first; - } - if (first > blk->end_index) { - continue; - } - u32 last = first; - while (last < blk->end_index && - (is_masked(last + 1) || IsExecNeutral(inst_list[last + 1]))) { - ++last; - } - while (IsExecNeutral(inst_list[last])) { - --last; - } - const auto next_blk = std::next(blk); - - // Create a new block for the run. - Block* block = block_pool.Create(); - block->begin = index_to_pc[first]; - block->end = index_to_pc[last + 1]; - block->begin_index = first; - block->end_index = last; - block->end_inst = inst_list[last]; - block->num_predecessors = 1; - block->is_exec_scope = true; - block->cond = IR::Condition::True; - block->end_class = EndClass::Branch; - blocks.insert_before(next_blk, *block); - - if (last != blk->end_index) { - // The rest of the parent block follows the run, the lanes that skipped it join there. - Block* epi_block = block_pool.Create(); - epi_block->begin = index_to_pc[last + 1]; - epi_block->end = blk->end; - epi_block->begin_index = last + 1; - epi_block->end_index = blk->end_index; - epi_block->end_inst = blk->end_inst; - epi_block->cond = blk->cond; - epi_block->end_class = blk->end_class; - epi_block->branch_true = blk->branch_true; - epi_block->branch_false = blk->branch_false; - epi_block->num_predecessors = 2; - blocks.insert_before(next_blk, *epi_block); - block->branch_true = epi_block; - blk->branch_false = epi_block; - } else { - // The run ends the parent block, both paths continue at its successor. - ASSERT(blk->cond == IR::Condition::True && blk->branch_true); - block->branch_true = blk->branch_true; - blk->branch_false = blk->branch_true; - blk->branch_true->num_predecessors++; - } - - // The parent block ends right before the run (it is empty when the run starts it) and - // enters the run with the lane's EXEC bit. - blk->end = index_to_pc[first]; - blk->end_index = first - 1; - if (first != blk->begin_index) { - blk->end_inst = inst_list[first - 1]; - } - blk->cond = IR::Condition::Execnz; - blk->end_class = EndClass::Branch; - blk->branch_true = block; - } -} - -void CFG::EmitBlocks() { - for (auto it = labels.cbegin(); it != labels.cend(); ++it) { - const Label start = *it; - const auto next_it = std::next(it); - const bool is_last = (next_it == labels.cend()); - if (is_last) { - // Last label is special. - return; - } - // The end label is the start instruction of next block. - // The end instruction of this block is the previous one. - const Label end = *next_it; - const size_t end_index = GetIndex(end) - 1; - const auto& end_inst = inst_list[end_index]; - - // Insert block between the labels using the last instruction - // as an indicator for branching type. - Block* block = block_pool.Create(); - block->begin = start; - block->end = end; - block->begin_index = GetIndex(start); - block->end_index = end_index; - block->end_inst = end_inst; - block->cond = MakeCondition(end_inst); - blocks.insert(*block); - } -} - -void CFG::LinkBlocks() { - const auto get_block = [this](u32 address) { - auto it = blocks.find(address, Compare{}); - ASSERT_MSG(it != blocks.cend() && it->begin == address); - return &*it; - }; - - for (auto it = blocks.begin(); it != blocks.end(); it++) { - auto& block = *it; - const auto end_inst{block.end_inst}; - - // If the block doesn't end with a branch we simply - // need to link with the next block. - if (!end_inst.IsTerminateInstruction()) { - auto* next_block = get_block(block.end); - block.branch_true = next_block; - block.end_class = EndClass::Branch; - next_block->num_predecessors++; - continue; - } - - // Find the branch targets from the instruction and link the blocks. - // Note: Block end address is one instruction after end_inst. - const u32 branch_pc = block.end - end_inst.length; - u32 target_pc = 0; - if (end_inst.opcode == Opcode::S_SETPC_B64) { - auto tgt = ResolveSetPcTarget(inst_list, block.end_index, index_to_pc); - ASSERT_MSG(tgt, - "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " - "instructions not recognized or invalid pattern", - branch_pc, block.end_index); - target_pc = *tgt; - } else { - target_pc = end_inst.BranchTarget(branch_pc); - } - - if (end_inst.IsUnconditionalBranch()) { - auto* target_block = get_block(target_pc); - block.branch_true = target_block; - block.end_class = EndClass::Branch; - target_block->num_predecessors++; - } else if (end_inst.IsConditionalBranch()) { - auto* end_block = get_block(block.end); - block.end_class = EndClass::Branch; - if (target_pc != block.end) { - auto* target_block = get_block(target_pc); - block.branch_true = target_block; - block.branch_false = end_block; - target_block->num_predecessors++; - } else { - block.branch_true = end_block; - block.cond = IR::Condition::True; - } - end_block->num_predecessors++; - } else if (end_inst.opcode == Opcode::S_ENDPGM) { - block.end_class = EndClass::Exit; - } else { - UNREACHABLE(); - } - } -} - -void CFG::RemoveUnreachableBlocks() { - for (auto it = std::next(blocks.begin()); it != blocks.end();) { - if (it->num_predecessors == 0) { - LOG_WARNING(Render_Recompiler, "Removing unreachable block begin={:#x}", it->begin); - it = blocks.erase(it); - } else { - it++; - } - } -} - -std::string CFG::Dot() const { - int node_uid{0}; - - const auto name_of = [](const Block& block) { return fmt::format("\"{:#x}\"", block.begin); }; - - std::string dot{"digraph shader {\n"}; - dot += fmt::format("\tsubgraph cluster_{} {{\n", 0); - dot += fmt::format("\t\tnode [style=filled];\n"); - for (const Block& block : blocks) { - const std::string name{name_of(block)}; - const auto add_branch = [&](Block* branch, bool add_label) { - dot += fmt::format("\t\t{}->{}", name, name_of(*branch)); - if (add_label && block.cond != IR::Condition::True && - block.cond != IR::Condition::False) { - dot += fmt::format(" [label=\"{}\"]", block.cond); - } - dot += '\n'; - }; - dot += fmt::format("\t\t{};\n", name); - switch (block.end_class) { - case EndClass::Branch: - if (block.cond != IR::Condition::False) { - add_branch(block.branch_true, true); - } - if (block.cond != IR::Condition::True) { - add_branch(block.branch_false, false); - } - break; - case EndClass::Exit: - dot += fmt::format("\t\t{}->N{};\n", name, node_uid); - dot += - fmt::format("\t\tN{} [label=\"Exit\"][shape=square][style=stripped];\n", node_uid); - ++node_uid; - break; - } - } - dot += "\t\tlabel = \"main\";\n\t}\n"; - if (blocks.empty()) { - dot += "Start;\n"; - } else { - dot += fmt::format("\tStart -> {};\n", name_of(*blocks.begin())); - } - dot += fmt::format("\tStart [shape=diamond];\n"); - dot += "}\n"; - return dot; -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/control_flow_graph.h b/src/shader_recompiler/frontend/control_flow_graph.h deleted file mode 100644 index b2bbe95..0000000 --- a/src/shader_recompiler/frontend/control_flow_graph.h +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include - -#include "common/assert.h" -#include "common/object_pool.h" -#include "common/types.h" -#include "shader_recompiler/frontend/instruction.h" -#include "shader_recompiler/ir/condition.h" - -namespace Shader::IR { -class Block; -} - -namespace Shader::Gcn { - -using Hook = - boost::intrusive::set_base_hook>; - -enum class EndClass { - Branch, ///< Block ends with a (un)conditional branch. - Exit, ///< Block ends with an exit instruction. -}; - -/// A block represents a linear range of instructions. -struct Block : Hook { - [[nodiscard]] bool Contains(u32 pc) const noexcept; - - bool operator<(const Block& rhs) const noexcept { - // An empty block ahead of an EXEC scope shares its begin, it sorts first. - return begin < rhs.begin || (begin == rhs.begin && end < rhs.end); - } - - u32 begin; - u32 end; - u32 begin_index; - u32 end_index; - u32 num_predecessors{}; - IR::Condition cond{}; - GcnInst end_inst{}; - EndClass end_class{}; - Block* branch_true{}; - Block* branch_false{}; - IR::Block* ir_block{}; - bool is_dummy{}; - bool is_exec_scope{}; -}; - -class CFG { - using Label = u32; - using BlockList = boost::intrusive::set; - using iterator = BlockList::iterator; - -public: - explicit CFG(Common::ObjectPool& block_pool, std::span inst_list); - - [[nodiscard]] iterator begin() { - return blocks.begin(); - } - [[nodiscard]] iterator end() { - return blocks.end(); - } - - [[nodiscard]] std::string Dot() const; - -private: - void EmitLabels(); - void EmitBlocks(); - void LinkBlocks(); - void SplitDivergenceScopes(); - void RemoveUnreachableBlocks(); - - void AddLabel(Label address) { - const auto it = std::ranges::find(labels, address); - if (it == labels.end()) { - labels.push_back(address); - } - } - - size_t GetIndex(Label label) { - if (label == 0) { - return 0ULL; - } - const auto it_index = std::ranges::lower_bound(index_to_pc, label); - ASSERT(it_index != index_to_pc.end() || label > index_to_pc.back()); - return std::distance(index_to_pc.begin(), it_index); - } - -public: - Common::ObjectPool& block_pool; - std::span inst_list; - std::vector index_to_pc; - boost::container::small_vector labels; - BlockList blocks; -}; - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/decode.cpp b/src/shader_recompiler/frontend/decode.cpp deleted file mode 100644 index 5a64dde..0000000 --- a/src/shader_recompiler/frontend/decode.cpp +++ /dev/null @@ -1,1304 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/assert.h" -#include "core/libraries/kernel/process.h" -#include "shader_recompiler/frontend/decode.h" - -#include - -namespace Shader::Gcn { - -namespace bit { -template -T extract(T value, u32 lst, u32 fst) { - return (value >> fst) & ~(~T(0) << (lst - fst + 1)); -} -} // namespace bit - -InstEncoding GetInstructionEncoding(u32 token) { - auto encoding = static_cast(token & (u32)EncodingMask::MASK_9bit); - switch (encoding) { - case InstEncoding::SOP1: - case InstEncoding::SOPP: - case InstEncoding::SOPC: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_7bit); - switch (encoding) { - case InstEncoding::VOP1: - case InstEncoding::VOPC: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_6bit); - switch (encoding) { - case InstEncoding::VOP3: - case InstEncoding::VOP3P: - case InstEncoding::EXP: - case InstEncoding::VINTRP: - case InstEncoding::DS: - case InstEncoding::MUBUF: - case InstEncoding::MTBUF: - case InstEncoding::MIMG: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_5bit); - switch (encoding) { - case InstEncoding::SMRD: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_4bit); - switch (encoding) { - case InstEncoding::SOPK: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_2bit); - switch (encoding) { - case InstEncoding::SOP2: - return encoding; - default: - break; - } - - encoding = static_cast(token & (u32)EncodingMask::MASK_1bit); - switch (encoding) { - case InstEncoding::VOP2: - return encoding; - default: - break; - } - - return InstEncoding::ILLEGAL; -} - -bool HasAdditionalLiteral(InstEncoding encoding, Opcode opcode) { - switch (encoding) { - case InstEncoding::SOPK: { - return opcode == Opcode::S_SETREG_IMM32_B32; - } - case InstEncoding::VOP2: { - return opcode == Opcode::V_MADMK_F32 || opcode == Opcode::V_MADAK_F32; - } - default: - return false; - } -} - -bool IsVop3BEncoding(Opcode opcode) { - return opcode == Opcode::V_ADD_I32 || opcode == Opcode::V_ADDC_U32 || - opcode == Opcode::V_SUB_I32 || opcode == Opcode::V_SUBB_U32 || - opcode == Opcode::V_SUBREV_I32 || opcode == Opcode::V_SUBBREV_U32 || - opcode == Opcode::V_DIV_SCALE_F32 || opcode == Opcode::V_DIV_SCALE_F64 || - opcode == Opcode::V_MAD_U64_U32 || opcode == Opcode::V_MAD_I64_I32; -} - -GcnInst GcnDecodeContext::decodeInstruction(GcnCodeSlice& code) { - const uint32_t token = code.at(0); - - InstEncoding encoding = GetInstructionEncoding(token); - ASSERT_MSG(encoding != InstEncoding::ILLEGAL, "illegal encoding: {:#x}", token); - uint32_t encodingLen = getEncodingLength(encoding); - - // Clear the instruction - m_instruction = GcnInst(); - - // Decode - if (encodingLen == sizeof(uint32_t)) { - decodeInstruction32(encoding, code); - } else { - decodeInstruction64(encoding, code); - } - - // Update instruction meta info. - updateInstructionMeta(encoding); - - // Detect literal constant. Only 32 bits instructions may have literal constant. - // Note: Literal constant decode must be performed after meta info updated. - if (encodingLen == sizeof(u32)) { - decodeLiteralConstant(encoding, code); - decodeSubDwordAddressing(encoding, code); - decodeDataParallelPrimitive(encoding, code); - } - - repairOperandType(); - return m_instruction; -} - -uint32_t GcnDecodeContext::getEncodingLength(InstEncoding encoding) { - uint32_t instLength = 0; - - switch (encoding) { - case InstEncoding::SOP1: - case InstEncoding::SOPP: - case InstEncoding::SOPC: - case InstEncoding::SOPK: - case InstEncoding::SOP2: - case InstEncoding::VOP1: - case InstEncoding::VOPC: - case InstEncoding::VOP2: - case InstEncoding::SMRD: - case InstEncoding::VINTRP: - instLength = sizeof(uint32_t); - break; - - case InstEncoding::VOP3: - case InstEncoding::VOP3P: - case InstEncoding::MUBUF: - case InstEncoding::MTBUF: - case InstEncoding::MIMG: - case InstEncoding::DS: - case InstEncoding::EXP: - instLength = sizeof(uint64_t); - break; - default: - break; - } - return instLength; -} - -uint32_t GcnDecodeContext::getOpMapOffset(InstEncoding encoding) { - uint32_t offset = 0; - switch (encoding) { - case InstEncoding::SOP1: - offset = (uint32_t)OpcodeMap::OP_MAP_SOP1; - break; - case InstEncoding::SOPP: - offset = (uint32_t)OpcodeMap::OP_MAP_SOPP; - break; - case InstEncoding::SOPC: - offset = (uint32_t)OpcodeMap::OP_MAP_SOPC; - break; - case InstEncoding::VOP1: - offset = (uint32_t)OpcodeMap::OP_MAP_VOP1; - break; - case InstEncoding::VOPC: - offset = (uint32_t)OpcodeMap::OP_MAP_VOPC; - break; - case InstEncoding::VOP3: - offset = (uint32_t)OpcodeMap::OP_MAP_VOP3; - break; - case InstEncoding::VOP3P: - offset = (uint32_t)OpcodeMap::OP_MAP_VOP3P; - break; - case InstEncoding::EXP: - offset = (uint32_t)OpcodeMap::OP_MAP_EXP; - break; - case InstEncoding::VINTRP: - offset = (uint32_t)OpcodeMap::OP_MAP_VINTRP; - break; - case InstEncoding::DS: - offset = (uint32_t)OpcodeMap::OP_MAP_DS; - break; - case InstEncoding::MUBUF: - offset = (uint32_t)OpcodeMap::OP_MAP_MUBUF; - break; - case InstEncoding::MTBUF: - offset = (uint32_t)OpcodeMap::OP_MAP_MTBUF; - break; - case InstEncoding::MIMG: - offset = (uint32_t)OpcodeMap::OP_MAP_MIMG; - break; - case InstEncoding::SMRD: - offset = (uint32_t)OpcodeMap::OP_MAP_SMRD; - break; - case InstEncoding::SOPK: - offset = (uint32_t)OpcodeMap::OP_MAP_SOPK; - break; - case InstEncoding::SOP2: - offset = (uint32_t)OpcodeMap::OP_MAP_SOP2; - break; - case InstEncoding::VOP2: - offset = (uint32_t)OpcodeMap::OP_MAP_VOP2; - break; - default: - break; - } - return offset; -} - -uint32_t GcnDecodeContext::mapEncodingOp(InstEncoding encoding, Opcode opcode) { - // Map from uniform opcode to encoding specific opcode. - uint32_t encodingOp = 0; - if (encoding == InstEncoding::VOP3) { - if (opcode >= Opcode::V_CMP_F_F32 && opcode <= Opcode::V_CMPX_T_U64) { - uint32_t op = - static_cast(opcode) - static_cast(OpcodeMap::OP_MAP_VOPC); - encodingOp = op + static_cast(OpMapVOP3VOPX::VOP3_TO_VOPC); - } else if (opcode >= Opcode::V_CNDMASK_B32 && opcode <= Opcode::V_LDEXP_F16) { - uint32_t op = - static_cast(opcode) - static_cast(OpcodeMap::OP_MAP_VOP2); - encodingOp = op + static_cast(OpMapVOP3VOPX::VOP3_TO_VOP2); - } else if (opcode >= Opcode::V_NOP && opcode <= Opcode::V_SQRT_F16) { - uint32_t op = - static_cast(opcode) - static_cast(OpcodeMap::OP_MAP_VOP1); - encodingOp = op + static_cast(OpMapVOP3VOPX::VOP3_TO_VOP1); - } else { - encodingOp = - static_cast(opcode) - static_cast(OpcodeMap::OP_MAP_VOP3); - } - } else { - uint32_t mapOffset = getOpMapOffset(encoding); - encodingOp = static_cast(opcode) - mapOffset; - } - - return encodingOp; -} - -void GcnDecodeContext::updateInstructionMeta(InstEncoding encoding) { - uint32_t encodingOp = mapEncodingOp(encoding, m_instruction.opcode); - InstFormat instFormat = InstructionFormat(encoding, encodingOp); - - ASSERT_MSG(instFormat.src_type != ScalarType::Undefined && - instFormat.dst_type != ScalarType::Undefined, - "Instruction format table incomplete for opcode {} ({}, encoding = 0x{:x})", - magic_enum::enum_name(m_instruction.opcode), u32(m_instruction.opcode), - u32(encoding)); - - m_instruction.inst_class = instFormat.inst_class; - m_instruction.category = instFormat.inst_category; - m_instruction.encoding = encoding; - m_instruction.src_count = instFormat.src_count; - m_instruction.length = getEncodingLength(encoding); - - // Update src operand scalar type. - auto setOperandType = [&instFormat](InstOperand& src) { - // Only update uninitialized numeric type. - if (src.type == ScalarType::Undefined) { - src.type = instFormat.src_type; - } - }; - - std::for_each_n(m_instruction.src.begin(), m_instruction.src_count, setOperandType); - - // Update dst operand scalar type. - switch (m_instruction.dst_count) { - case 2: { - if (m_instruction.dst[1].type == ScalarType::Undefined) { - // Only VOP3B has an additional sdst operand, - // and it must be Uint64 - m_instruction.dst[1].type = ScalarType::Uint64; - } - } - [[fallthrough]]; - case 1: { - if (m_instruction.dst[0].type == ScalarType::Undefined) { - m_instruction.dst[0].type = instFormat.dst_type; - } - } - } -} - -void GcnDecodeContext::repairOperandType() { - // Some instructions' operand type is not uniform, - // it's best to change the instruction table's format and fix them there, - // but it's a hard work. - // We fix them here. - switch (m_instruction.opcode) { - case Opcode::V_MAD_U64_U32: - m_instruction.src[2].type = ScalarType::Uint64; - break; - case Opcode::V_MAD_I64_I32: - m_instruction.src[2].type = ScalarType::Sint64; - break; - case Opcode::V_ADDC_U32: - m_instruction.src[2].type = ScalarType::Uint64; - break; - case Opcode::IMAGE_GATHER4_C: - case Opcode::IMAGE_GATHER4_C_O: - m_instruction.src[0].type = ScalarType::Any; - break; - default: - break; - } -} - -OperandField GcnDecodeContext::getOperandField(uint32_t code) { - OperandField field = {}; - if (code >= ScalarGPRMin && code <= ScalarGPRMax) { - field = OperandField::ScalarGPR; - } else if (code >= SignedConstIntPosMin && code <= SignedConstIntPosMax) { - field = OperandField::SignedConstIntPos; - } else if (code >= SignedConstIntNegMin && code <= SignedConstIntNegMax) { - field = OperandField::SignedConstIntNeg; - } else if (code >= VectorGPRMin && code <= VectorGPRMax) { - field = OperandField::VectorGPR; - } else { - field = static_cast(code); - } - return field; -} - -void GcnDecodeContext::decodeInstruction32(InstEncoding encoding, GcnCodeSlice& code) { - u32 hexInstruction = code.readu32(); - switch (encoding) { - case InstEncoding::SOP1: - decodeInstructionSOP1(hexInstruction); - break; - case InstEncoding::SOPP: - decodeInstructionSOPP(hexInstruction); - break; - case InstEncoding::SOPC: - decodeInstructionSOPC(hexInstruction); - break; - case InstEncoding::SOPK: - decodeInstructionSOPK(hexInstruction); - break; - case InstEncoding::SOP2: - decodeInstructionSOP2(hexInstruction); - break; - case InstEncoding::VOP1: - decodeInstructionVOP1(hexInstruction); - break; - case InstEncoding::VOPC: - decodeInstructionVOPC(hexInstruction); - break; - case InstEncoding::VOP2: - decodeInstructionVOP2(hexInstruction); - break; - case InstEncoding::SMRD: - decodeInstructionSMRD(hexInstruction); - break; - case InstEncoding::VINTRP: - decodeInstructionVINTRP(hexInstruction); - break; - default: - break; - } -} - -void GcnDecodeContext::decodeInstruction64(InstEncoding encoding, GcnCodeSlice& code) { - uint64_t hexInstruction = code.readu64(); - switch (encoding) { - case InstEncoding::VOP3: - decodeInstructionVOP3(hexInstruction); - break; - case InstEncoding::VOP3P: - decodeInstructionVOP3P(hexInstruction); - break; - case InstEncoding::MUBUF: - decodeInstructionMUBUF(hexInstruction); - break; - case InstEncoding::MTBUF: - decodeInstructionMTBUF(hexInstruction); - break; - case InstEncoding::MIMG: - decodeInstructionMIMG(hexInstruction); - break; - case InstEncoding::DS: - decodeInstructionDS(hexInstruction); - break; - case InstEncoding::EXP: - decodeInstructionEXP(hexInstruction); - break; - default: - break; - } -} - -void GcnDecodeContext::decodeLiteralConstant(InstEncoding encoding, GcnCodeSlice& code) { - // There is one literal dword per instruction; every source encoded as a literal reads it. - if (HasAdditionalLiteral(encoding, m_instruction.opcode)) { - u32 encoding_op = mapEncodingOp(encoding, m_instruction.opcode); - InstFormat instFormat = InstructionFormat(encoding, encoding_op); - const u32 literal = code.readu32(); - for (u32 i = 0; i < m_instruction.src_count; ++i) { - if (m_instruction.src[i].field == OperandField::LiteralConst) { - m_instruction.src[i].code = literal; - } - } - m_instruction.src[m_instruction.src_count].field = OperandField::LiteralConst; - m_instruction.src[m_instruction.src_count].type = instFormat.src_type; - m_instruction.src[m_instruction.src_count].code = literal; - ++m_instruction.src_count; - m_instruction.length += sizeof(u32); - return; - } - - bool has_literal = false; - u32 literal = 0; - for (auto& src : m_instruction.src) { - if (src.field != OperandField::LiteralConst) { - continue; - } - if (!has_literal) { - literal = code.readu32(); - m_instruction.length += sizeof(u32); - has_literal = true; - } - src.code = literal; - } -} - -void GcnDecodeContext::decodeSubDwordAddressing(InstEncoding encoding, GcnCodeSlice& code) { - // Find if the instruction contains SDWA (it's legal only as src0) - if (m_instruction.src[0].field == OperandField::Sdwa) { - m_instruction.src[0].code = code.readu32(); - m_instruction.length += sizeof(u32); - - if (encoding == InstEncoding::VOPC) { - SdwaVopc sdwa = *reinterpret_cast(&m_instruction.src[0].code); - - m_instruction.src[0].field = - sdwa.s0 == 0 ? OperandField::VectorGPR : getOperandField(sdwa.src0); - m_instruction.src[0].code = sdwa.src0; - m_instruction.src[0].sdwa_sel = SdwaSelector(sdwa.src0_sel); - - m_instruction.src[0].input_modifier.neg = sdwa.src0_neg; - m_instruction.src[0].input_modifier.abs = sdwa.src0_abs; - m_instruction.src[0].input_modifier.sext = sdwa.src0_sext; - - m_instruction.src[1].field = - sdwa.s1 == 0 ? OperandField::VectorGPR : getOperandField(m_instruction.src[1].code); - m_instruction.src[1].sdwa_sel = SdwaSelector(sdwa.src1_sel); - - m_instruction.src[1].input_modifier.neg = sdwa.src1_neg; - m_instruction.src[1].input_modifier.abs = sdwa.src1_abs; - m_instruction.src[1].input_modifier.sext = sdwa.src1_sext; - - m_instruction.dst[0].field = sdwa.sd ? OperandField::ScalarGPR : OperandField::VccLo; - m_instruction.dst[0].code = sdwa.sdst; - - } else if (encoding == InstEncoding::VOP1 || encoding == InstEncoding::VOP2) { - SdwaVop12 sdwa = *reinterpret_cast(&m_instruction.src[0].code); - - m_instruction.src[0].field = - sdwa.s0 == 0 ? OperandField::VectorGPR : getOperandField(sdwa.src0); - m_instruction.src[0].code = sdwa.src0; - m_instruction.src[0].sdwa_sel = SdwaSelector(sdwa.src0_sel); - - m_instruction.src[0].input_modifier.neg = sdwa.src0_neg; - m_instruction.src[0].input_modifier.abs = sdwa.src0_abs; - m_instruction.src[0].input_modifier.sext = sdwa.src0_sext; - - m_instruction.src[1].field = - sdwa.s1 == 0 ? OperandField::VectorGPR : getOperandField(m_instruction.src[1].code); - m_instruction.src[1].sdwa_sel = SdwaSelector(sdwa.src1_sel); - - m_instruction.src[1].input_modifier.neg = sdwa.src1_neg; - m_instruction.src[1].input_modifier.abs = sdwa.src1_abs; - m_instruction.src[1].input_modifier.sext = sdwa.src1_sext; - - m_instruction.dst[0].sdwa_sel = SdwaSelector(sdwa.dst_sel); - m_instruction.dst[0].sdwa_dst = SdwaDstUnused(sdwa.dst_u); - m_instruction.dst[0].output_modifier.clamp = sdwa.clamp; - - switch (sdwa.omod) { - case 0: - m_instruction.dst[0].output_modifier.multiplier = 0.f; - break; - case 1: - m_instruction.dst[0].output_modifier.multiplier = 2.0f; - break; - case 2: - m_instruction.dst[0].output_modifier.multiplier = 4.0f; - break; - case 3: - m_instruction.dst[0].output_modifier.multiplier = 0.5f; - break; - } - } else { - LOG_WARNING(Render_Recompiler, "illegal instruction: SDWA used outside VOP1/VOP2/VOPC"); - } - } -} - -void GcnDecodeContext::decodeDataParallelPrimitive(InstEncoding encoding, GcnCodeSlice& code) { - // Find if the instruction contains DPP - if (m_instruction.src[0].field == OperandField::Dpp) { - m_instruction.src[0].code = code.readu32(); - m_instruction.length += sizeof(u32); - - Dpp dpp = *reinterpret_cast(&m_instruction.src[0].code); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = dpp.src0; - - if (dpp.src0_abs) { - m_instruction.src[0].input_modifier.abs = true; - } - if (dpp.src0_neg) { - m_instruction.src[0].input_modifier.neg = true; - } - if (dpp.src1_abs) { - m_instruction.src[1].input_modifier.abs = true; - } - if (dpp.src1_neg) { - m_instruction.src[1].input_modifier.neg = true; - } - - auto op = dpp.GetOperation(); - LOG_ERROR( - Render_Recompiler, - "unhandled DPP operation: {} ({:#x}), value {}, bc {}, row_mask {:#b}, bank_mask {:#b}", - magic_enum::enum_name(op.op), u32(op.op), op.value, bool(dpp.bc), u8(dpp.row_mask), - u8(dpp.bank_mask)); - - m_instruction.src[0].dpp = op; - } -} - -void GcnDecodeContext::decodeInstructionSOP1(u32 hexInstruction) { - u32 ssrc0 = bit::extract(hexInstruction, 7, 0); - u32 op = bit::extract(hexInstruction, 15, 8); - u32 sdst = bit::extract(hexInstruction, 22, 16); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SOP1)); - - m_instruction.src[0].field = getOperandField(ssrc0); - m_instruction.src[0].code = ssrc0; - m_instruction.dst[0].field = getOperandField(sdst); - m_instruction.dst[0].code = sdst; - m_instruction.dst_count = 1; -} - -void GcnDecodeContext::decodeInstructionSOPP(u32 hexInstruction) { - u32 op = bit::extract(hexInstruction, 22, 16); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SOPP)); - - m_instruction.control.sopp = *reinterpret_cast(&hexInstruction); -} - -void GcnDecodeContext::decodeInstructionSOPC(u32 hexInstruction) { - u32 ssrc0 = bit::extract(hexInstruction, 7, 0); - u32 ssrc1 = bit::extract(hexInstruction, 15, 8); - u32 op = bit::extract(hexInstruction, 22, 16); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SOPC)); - - m_instruction.src[0].field = getOperandField(ssrc0); - m_instruction.src[0].code = ssrc0; - m_instruction.src[1].field = getOperandField(ssrc1); - m_instruction.src[1].code = ssrc1; -} - -void GcnDecodeContext::decodeInstructionSOPK(u32 hexInstruction) { - u32 sdst = bit::extract(hexInstruction, 22, 16); - u32 op = bit::extract(hexInstruction, 27, 23); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SOPK)); - - m_instruction.dst[0].field = getOperandField(sdst); - m_instruction.dst[0].code = sdst; - m_instruction.dst_count = 1; - - m_instruction.control.sopk = *reinterpret_cast(&hexInstruction); -} - -void GcnDecodeContext::decodeInstructionSOP2(u32 hexInstruction) { - u32 ssrc0 = bit::extract(hexInstruction, 7, 0); - u32 ssrc1 = bit::extract(hexInstruction, 15, 8); - u32 sdst = bit::extract(hexInstruction, 22, 16); - u32 op = bit::extract(hexInstruction, 29, 23); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SOP2)); - - m_instruction.src[0].field = getOperandField(ssrc0); - m_instruction.src[0].code = ssrc0; - m_instruction.src[1].field = getOperandField(ssrc1); - m_instruction.src[1].code = ssrc1; - m_instruction.dst[0].field = getOperandField(sdst); - m_instruction.dst[0].code = sdst; - m_instruction.dst_count = 1; -} - -void GcnDecodeContext::decodeInstructionVOP1(u32 hexInstruction) { - u32 src0 = bit::extract(hexInstruction, 8, 0); - u32 op = bit::extract(hexInstruction, 16, 9); - u32 vdst = bit::extract(hexInstruction, 24, 17); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VOP1)); - - m_instruction.src[0].field = getOperandField(src0); - m_instruction.src[0].code = - m_instruction.src[0].field == OperandField::VectorGPR ? src0 - VectorGPRMin : src0; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - m_instruction.dst_count = 1; - - OpcodeVOP1 vop1Op = static_cast(op); - if (vop1Op == OpcodeVOP1::V_READFIRSTLANE_B32) { - m_instruction.dst[0].field = getOperandField(vdst); - m_instruction.dst[0].type = ScalarType::Uint32; - } -} - -void GcnDecodeContext::decodeInstructionVOPC(u32 hexInstruction) { - u32 src0 = bit::extract(hexInstruction, 8, 0); - u32 vsrc1 = bit::extract(hexInstruction, 16, 9); - u32 op = bit::extract(hexInstruction, 24, 17); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VOPC)); - - m_instruction.src[0].field = getOperandField(src0); - m_instruction.src[0].code = - m_instruction.src[0].field == OperandField::VectorGPR ? src0 - VectorGPRMin : src0; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = vsrc1; - // VOPC dst is forced to VCC. - // In order to be unified with VOP3 encoding, - // we store it to dst[1] - m_instruction.dst[1].field = OperandField::VccLo; - m_instruction.dst[1].type = ScalarType::Uint64; - m_instruction.dst[1].code = static_cast(OperandField::VccLo); -} - -void GcnDecodeContext::decodeInstructionVOP2(u32 hexInstruction) { - u32 src0 = bit::extract(hexInstruction, 8, 0); - u32 vsrc1 = bit::extract(hexInstruction, 16, 9); - u32 vdst = bit::extract(hexInstruction, 24, 17); - u32 op = bit::extract(hexInstruction, 30, 25); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VOP2)); - - m_instruction.src[0].field = getOperandField(src0); - m_instruction.src[0].code = - m_instruction.src[0].field == OperandField::VectorGPR ? src0 - VectorGPRMin : src0; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = vsrc1; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - m_instruction.dst_count = 1; - - OpcodeVOP2 vop2Op = static_cast(op); - if (vop2Op == OpcodeVOP2::V_READLANE_B32) { - // vsrc1 is scalar for lane instructions - m_instruction.src[1].field = getOperandField(vsrc1); - // dst is sgpr - m_instruction.dst[0].field = getOperandField(vdst); - m_instruction.dst[0].type = ScalarType::Uint32; - } else if (vop2Op == OpcodeVOP2::V_WRITELANE_B32) { - m_instruction.src[1].field = getOperandField(vsrc1); - // dst is vgpr, as normal - } else if (IsVop3BEncoding(m_instruction.opcode)) { - m_instruction.dst[1].field = OperandField::VccLo; - m_instruction.dst[1].type = ScalarType::Uint64; - m_instruction.dst[1].code = static_cast(OperandField::VccLo); - } -} - -void GcnDecodeContext::decodeInstructionSMRD(u32 hexInstruction) { - u32 sbase = bit::extract(hexInstruction, 14, 9); - u32 sdst = bit::extract(hexInstruction, 21, 15); - u32 op = bit::extract(hexInstruction, 26, 22); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_SMRD)); - - m_instruction.src[0].field = OperandField::ScalarGPR; - m_instruction.src[0].code = sbase; - m_instruction.dst[0].field = OperandField::ScalarGPR; - m_instruction.dst[0].code = sdst; - m_instruction.dst_count = 1; - - m_instruction.control.smrd = *reinterpret_cast(&hexInstruction); - - if (op <= static_cast(OpcodeSMRD::S_LOAD_DWORDX16)) { - m_instruction.control.smrd.count = 1 << op; - } else if (op >= static_cast(OpcodeSMRD::S_BUFFER_LOAD_DWORD) && - op <= static_cast(OpcodeSMRD::S_BUFFER_LOAD_DWORDX16)) { - m_instruction.control.smrd.count = 1 << (op - 8); - } - - if (m_instruction.control.smrd.imm == 0) { - u32 code = m_instruction.control.smrd.offset; - m_instruction.src[1].field = getOperandField(code); - m_instruction.src[1].type = ScalarType::Uint32; - m_instruction.src[1].code = code; - } -} - -void GcnDecodeContext::decodeInstructionVINTRP(u32 hexInstruction) { - u32 vsrc = bit::extract(hexInstruction, 7, 0); - u32 op = bit::extract(hexInstruction, 17, 16); - u32 vdst = bit::extract(hexInstruction, 25, 18); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VINTRP)); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = vsrc; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - m_instruction.dst_count = 1; - - m_instruction.control.vintrp = *reinterpret_cast(&hexInstruction); -} - -void GcnDecodeContext::decodeInstructionVOP3(uint64_t hexInstruction) { - u32 vdst = bit::extract(hexInstruction, 7, 0); - u32 sdst = bit::extract(hexInstruction, 14, 8); // For VOP3B - u32 op = bit::extract(hexInstruction, 25, 17); - u32 op_msb = bit::extract(hexInstruction, 16, 16); - op = op + op_msb * (1 << 9); - u32 src0 = bit::extract(hexInstruction, 40, 32); - u32 src1 = bit::extract(hexInstruction, 49, 41); - u32 src2 = bit::extract(hexInstruction, 58, 50); - - if (op >= static_cast(OpcodeVOP3::V_CMP_F_F32) && - op <= static_cast(OpcodeVOP3::V_CMPX_T_U64)) { - // Map from VOP3 to VOPC - u32 vopcOp = op - static_cast(OpMapVOP3VOPX::VOP3_TO_VOPC); - m_instruction.opcode = - static_cast(vopcOp + static_cast(OpcodeMap::OP_MAP_VOPC)); - } else if (op >= static_cast(OpcodeVOP3::V_CNDMASK_B32) && - op <= static_cast(OpcodeVOP3::V_LDEXP_F16)) { - // Map from VOP3 to VOP2 - u32 vop2Op = op - static_cast(OpMapVOP3VOPX::VOP3_TO_VOP2); - m_instruction.opcode = - static_cast(vop2Op + static_cast(OpcodeMap::OP_MAP_VOP2)); - } else if (op >= static_cast(OpcodeVOP3::V_NOP) && - op <= static_cast(OpcodeVOP3::V_SQRT_F16)) { - // Map from VOP3 to VOP1 - u32 vop1Op = op - static_cast(OpMapVOP3VOPX::VOP3_TO_VOP1); - m_instruction.opcode = - static_cast(vop1Op + static_cast(OpcodeMap::OP_MAP_VOP1)); - } else { - // VOP3 encoding, do not map. - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VOP3)); - } - - m_instruction.src[0].field = getOperandField(src0); - m_instruction.src[0].code = - m_instruction.src[0].field == OperandField::VectorGPR ? src0 - VectorGPRMin : src0; - m_instruction.src[1].field = getOperandField(src1); - m_instruction.src[1].code = - m_instruction.src[1].field == OperandField::VectorGPR ? src1 - VectorGPRMin : src1; - m_instruction.src[2].field = getOperandField(src2); - m_instruction.src[2].code = - m_instruction.src[2].field == OperandField::VectorGPR ? src2 - VectorGPRMin : src2; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - - OpcodeVOP3 vop3Op = static_cast(op); - if (IsVop3BEncoding(m_instruction.opcode)) { - m_instruction.dst[1].field = getOperandField(sdst); - m_instruction.dst[1].type = ScalarType::Uint64; - m_instruction.dst[1].code = sdst; - } else { - if (vop3Op >= OpcodeVOP3::V_CMP_F_F32 && vop3Op <= OpcodeVOP3::V_CMPX_T_U64) { - m_instruction.dst[1].field = getOperandField(vdst); - m_instruction.dst[1].type = ScalarType::Uint64; - m_instruction.dst[1].code = vdst; - } else if (vop3Op == OpcodeVOP3::V_READLANE_B32 || - vop3Op == OpcodeVOP3::V_READFIRSTLANE_B32) { - m_instruction.dst[0].field = getOperandField(vdst); - m_instruction.dst[0].type = ScalarType::Uint32; - // WRITELANE can be decoded like other VOP3's - } - } - - if (op >= static_cast(OpcodeVOP3::V_ADD_I32) && - op <= static_cast(OpcodeVOP3::V_DIV_SCALE_F64)) { - // VOP3B has a sdst operand. - m_instruction.dst_count = 2; - } else { - m_instruction.dst_count = 1; - } - - m_instruction.control.vop3 = *reinterpret_cast(&hexInstruction); - - // update input modifier - auto& control = m_instruction.control.vop3; - - // update output modifier - auto& outputMod = m_instruction.dst[0].output_modifier; - - if (!IsVop3BEncoding(m_instruction.opcode)) { - for (u32 i = 0; i != 3; ++i) { - if (control.abs & (1u << i)) { - m_instruction.src[i].input_modifier.abs = true; - } - } - outputMod.clamp = static_cast(control.clmp); - } - for (u32 i = 0; i != 3; ++i) { - if (control.neg & (1u << i)) { - m_instruction.src[i].input_modifier.neg = true; - } - - if (control.op_sel & (1u << i)) { - m_instruction.src[i].op_sel.op_sel = true; - } - } - - m_instruction.dst[0].op_sel.op_sel = control.op_sel & (1u << 3); - - switch (control.omod) { - case 0: - outputMod.multiplier = 0.f; - break; - case 1: - outputMod.multiplier = 2.0f; - break; - case 2: - outputMod.multiplier = 4.0f; - break; - case 3: - outputMod.multiplier = 0.5f; - break; - } -} - -void GcnDecodeContext::decodeInstructionVOP3P(uint64_t hexInstruction) { - u32 vdst = bit::extract(hexInstruction, 7, 0); - u32 op = bit::extract(hexInstruction, 22, 16); - u32 src0 = bit::extract(hexInstruction, 40, 32); - u32 src1 = bit::extract(hexInstruction, 49, 41); - u32 src2 = bit::extract(hexInstruction, 58, 50); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_VOP3P)); - - m_instruction.src[0].field = getOperandField(src0); - m_instruction.src[0].code = - m_instruction.src[0].field == OperandField::VectorGPR ? src0 - VectorGPRMin : src0; - m_instruction.src[1].field = getOperandField(src1); - m_instruction.src[1].code = - m_instruction.src[1].field == OperandField::VectorGPR ? src1 - VectorGPRMin : src1; - m_instruction.src[2].field = getOperandField(src2); - m_instruction.src[2].code = - m_instruction.src[2].field == OperandField::VectorGPR ? src2 - VectorGPRMin : src2; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - - m_instruction.control.vop3p = *reinterpret_cast(&hexInstruction); - - // update input modifier - auto& control = m_instruction.control.vop3p; - for (u32 i = 0; i != 3; ++i) { - if (control.neg & (1u << i)) { - m_instruction.src[i].input_modifier.neg = true; - } - - if (control.neg_hi & (1u << i)) { - m_instruction.src[i].input_modifier.neg_hi = true; - } - - if (control.op_sel & (1u << i)) { - m_instruction.src[i].op_sel.op_sel = true; - } - - if (control.get_op_sel_hi(i)) { - m_instruction.src[i].op_sel.op_sel_hi = true; - } - } - - // update output modifier - auto& outputMod = m_instruction.dst[0].output_modifier; - - outputMod.clamp = static_cast(control.clamp); -} - -void GcnDecodeContext::decodeInstructionMUBUF(uint64_t hexInstruction) { - u32 op = bit::extract(hexInstruction, 24, 18); - u32 vaddr = bit::extract(hexInstruction, 39, 32); - u32 vdata = bit::extract(hexInstruction, 47, 40); - u32 srsrc = bit::extract(hexInstruction, 52, 48); - u32 soffset = bit::extract(hexInstruction, 63, 56); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_MUBUF)); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = vaddr; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = vdata; - m_instruction.src[2].field = OperandField::ScalarGPR; - m_instruction.src[2].code = srsrc; - m_instruction.src[3].field = getOperandField(soffset); - m_instruction.src[3].code = soffset; - - m_instruction.control.mubuf = *reinterpret_cast(&hexInstruction); - - if (op >= static_cast(OpcodeMUBUF::BUFFER_LOAD_FORMAT_X) && - op <= static_cast(OpcodeMUBUF::BUFFER_LOAD_FORMAT_XYZW)) { - m_instruction.control.mubuf.count = op + 1; - m_instruction.control.mubuf.size = (op + 1) * sizeof(u32); - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_STORE_FORMAT_X) && - op <= static_cast(OpcodeMUBUF::BUFFER_STORE_FORMAT_XYZW)) { - m_instruction.control.mubuf.count = op - 3; - m_instruction.control.mubuf.size = (op - 3) * sizeof(u32); - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_LOAD_DWORD) && - op <= static_cast(OpcodeMUBUF::BUFFER_LOAD_DWORDX3)) { - m_instruction.control.mubuf.count = - op == static_cast(OpcodeMUBUF::BUFFER_LOAD_DWORDX3) ? 3 : 1 << (op - 12); - m_instruction.control.mubuf.size = m_instruction.control.mubuf.count * sizeof(u32); - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_STORE_DWORD) && - op <= static_cast(OpcodeMUBUF::BUFFER_STORE_DWORDX3)) { - m_instruction.control.mubuf.count = - op == static_cast(OpcodeMUBUF::BUFFER_STORE_DWORDX3) ? 3 : 1 << (op - 28); - m_instruction.control.mubuf.size = m_instruction.control.mubuf.count * sizeof(u32); - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_LOAD_UBYTE) && - op <= static_cast(OpcodeMUBUF::BUFFER_LOAD_SSHORT)) { - m_instruction.control.mubuf.count = 1; - if (op >= static_cast(OpcodeMUBUF::BUFFER_LOAD_UBYTE) && - op <= static_cast(OpcodeMUBUF::BUFFER_LOAD_SBYTE)) { - m_instruction.control.mubuf.size = 1; - } else { - m_instruction.control.mubuf.size = 2; - } - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_STORE_BYTE) && - op <= static_cast(OpcodeMUBUF::BUFFER_STORE_SHORT)) { - m_instruction.control.mubuf.count = 1; - if (op == static_cast(OpcodeMUBUF::BUFFER_STORE_BYTE)) { - m_instruction.control.mubuf.size = 1; - } else { - m_instruction.control.mubuf.size = 2; - } - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_ATOMIC_SWAP) && - op <= static_cast(OpcodeMUBUF::BUFFER_ATOMIC_FMAX)) { - m_instruction.control.mubuf.count = 1; - m_instruction.control.mubuf.size = sizeof(u32); - } else if (op >= static_cast(OpcodeMUBUF::BUFFER_ATOMIC_SWAP_X2) && - op <= static_cast(OpcodeMUBUF::BUFFER_ATOMIC_FMAX_X2)) { - m_instruction.control.mubuf.count = 2; - m_instruction.control.mubuf.size = sizeof(u32) * 2; - } -} - -void GcnDecodeContext::decodeInstructionMTBUF(uint64_t hexInstruction) { - u32 op = bit::extract(hexInstruction, 18, 16); - u32 vaddr = bit::extract(hexInstruction, 39, 32); - u32 vdata = bit::extract(hexInstruction, 47, 40); - u32 srsrc = bit::extract(hexInstruction, 52, 48); - u32 soffset = bit::extract(hexInstruction, 63, 56); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_MTBUF)); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = vaddr; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = vdata; - m_instruction.src[2].field = OperandField::ScalarGPR; - m_instruction.src[2].code = srsrc; - m_instruction.src[3].field = getOperandField(soffset); - m_instruction.src[3].code = soffset; - - m_instruction.control.mtbuf = *reinterpret_cast(&hexInstruction); - - if (op >= static_cast(OpcodeMTBUF::TBUFFER_LOAD_FORMAT_X) && - op <= static_cast(OpcodeMTBUF::TBUFFER_LOAD_FORMAT_XYZW)) { - m_instruction.control.mtbuf.count = op + 1; - } else if (op >= static_cast(OpcodeMTBUF::TBUFFER_STORE_FORMAT_X) && - op <= static_cast(OpcodeMTBUF::TBUFFER_STORE_FORMAT_XYZW)) { - m_instruction.control.mtbuf.count = op - 3; - } -} - -u32 GcnDecodeContext::getMimgModifier(Opcode opcode) { - MimgModifierFlags flags = {}; - - switch (opcode) { - case Opcode::IMAGE_SAMPLE: - break; - case Opcode::IMAGE_SAMPLE_CL: - flags.set(MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_D: - flags.set(MimgModifier::Derivative); - break; - case Opcode::IMAGE_SAMPLE_D_CL: - flags.set(MimgModifier::Derivative, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_L: - flags.set(MimgModifier::Lod); - break; - case Opcode::IMAGE_SAMPLE_B: - flags.set(MimgModifier::LodBias); - break; - case Opcode::IMAGE_SAMPLE_B_CL: - flags.set(MimgModifier::LodBias, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_LZ: - flags.set(MimgModifier::Level0); - break; - case Opcode::IMAGE_SAMPLE_C: - flags.set(MimgModifier::Pcf); - break; - case Opcode::IMAGE_SAMPLE_C_CL: - flags.set(MimgModifier::Pcf, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_C_D: - flags.set(MimgModifier::Pcf, MimgModifier::Derivative); - break; - case Opcode::IMAGE_SAMPLE_C_D_CL: - flags.set(MimgModifier::Pcf, MimgModifier::Derivative, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_C_L: - flags.set(MimgModifier::Pcf, MimgModifier::Lod); - break; - case Opcode::IMAGE_SAMPLE_C_B: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias); - break; - case Opcode::IMAGE_SAMPLE_C_B_CL: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_C_LZ: - flags.set(MimgModifier::Pcf, MimgModifier::Level0); - break; - case Opcode::IMAGE_SAMPLE_O: - flags.set(MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_CL_O: - flags.set(MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_D_O: - flags.set(MimgModifier::Derivative, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_D_CL_O: - flags.set(MimgModifier::Derivative, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_L_O: - flags.set(MimgModifier::Lod, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_B_O: - flags.set(MimgModifier::LodBias, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_B_CL_O: - flags.set(MimgModifier::LodBias, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_LZ_O: - flags.set(MimgModifier::Level0, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_O: - flags.set(MimgModifier::Pcf, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_D_O: - flags.set(MimgModifier::Pcf, MimgModifier::Derivative, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_D_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::Derivative, MimgModifier::LodClamp, - MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_L_O: - flags.set(MimgModifier::Pcf, MimgModifier::Lod, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_B_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_B_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::LodClamp, - MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_LZ_O: - flags.set(MimgModifier::Pcf, MimgModifier::Level0, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4: - break; - case Opcode::IMAGE_GATHER4_CL: - flags.set(MimgModifier::LodClamp); - break; - case Opcode::IMAGE_GATHER4_L: - flags.set(MimgModifier::Lod); - break; - case Opcode::IMAGE_GATHER4_B: - flags.set(MimgModifier::LodBias); - break; - case Opcode::IMAGE_GATHER4_B_CL: - flags.set(MimgModifier::LodBias, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_GATHER4_LZ: - flags.set(MimgModifier::Level0); - break; - case Opcode::IMAGE_GATHER4_C: - flags.set(MimgModifier::Pcf); - break; - case Opcode::IMAGE_GATHER4_C_CL: - flags.set(MimgModifier::Pcf, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_GATHER4_C_L: - flags.set(MimgModifier::Pcf, MimgModifier::Lod); - break; - case Opcode::IMAGE_GATHER4_C_B: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias); - break; - case Opcode::IMAGE_GATHER4_C_B_CL: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_GATHER4_C_LZ: - flags.set(MimgModifier::Pcf, MimgModifier::Level0); - break; - case Opcode::IMAGE_GATHER4_O: - flags.set(MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_CL_O: - flags.set(MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_L_O: - flags.set(MimgModifier::Lod, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_B_O: - flags.set(MimgModifier::LodBias, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_B_CL_O: - flags.set(MimgModifier::LodBias, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_LZ_O: - flags.set(MimgModifier::Level0, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_O: - flags.set(MimgModifier::Pcf, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_L_O: - flags.set(MimgModifier::Pcf, MimgModifier::Lod, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_B_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_B_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::LodBias, MimgModifier::LodClamp, - MimgModifier::Offset); - break; - case Opcode::IMAGE_GATHER4_C_LZ_O: - flags.set(MimgModifier::Pcf, MimgModifier::Level0, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_CD: - flags.set(MimgModifier::CoarseDerivative); - break; - case Opcode::IMAGE_SAMPLE_CD_CL: - flags.set(MimgModifier::CoarseDerivative, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_C_CD: - flags.set(MimgModifier::Pcf, MimgModifier::CoarseDerivative); - break; - case Opcode::IMAGE_SAMPLE_C_CD_CL: - flags.set(MimgModifier::Pcf, MimgModifier::CoarseDerivative, MimgModifier::LodClamp); - break; - case Opcode::IMAGE_SAMPLE_CD_O: - flags.set(MimgModifier::CoarseDerivative, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_CD_CL_O: - flags.set(MimgModifier::CoarseDerivative, MimgModifier::LodClamp, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_CD_O: - flags.set(MimgModifier::Pcf, MimgModifier::CoarseDerivative, MimgModifier::Offset); - break; - case Opcode::IMAGE_SAMPLE_C_CD_CL_O: - flags.set(MimgModifier::Pcf, MimgModifier::CoarseDerivative, MimgModifier::LodClamp, - MimgModifier::Offset); - break; - default: - break; - } - - return flags.raw(); -} - -void GcnDecodeContext::decodeInstructionMIMG(uint64_t hexInstruction) { - u32 op = bit::extract(hexInstruction, 24, 18); - u32 vaddr = bit::extract(hexInstruction, 39, 32); - u32 vdata = bit::extract(hexInstruction, 47, 40); - u32 srsrc = bit::extract(hexInstruction, 52, 48); - u32 ssamp = bit::extract(hexInstruction, 57, 53); - - m_instruction.opcode = static_cast(op + static_cast(OpcodeMap::OP_MAP_MIMG)); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = vaddr; - m_instruction.src[2].field = OperandField::ScalarGPR; - m_instruction.src[2].code = srsrc; - m_instruction.src[3].field = OperandField::ScalarGPR; - m_instruction.src[3].code = ssamp; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdata; - - m_instruction.control.mimg = *reinterpret_cast(&hexInstruction); - m_instruction.control.mimg.mod = getMimgModifier(m_instruction.opcode); -} - -void GcnDecodeContext::decodeInstructionDS(uint64_t hexInstruction) { - OpcodeDS op = (OpcodeDS)bit::extract(hexInstruction, 25, 18); - u32 addr = bit::extract(hexInstruction, 39, 32); - u32 data0 = bit::extract(hexInstruction, 47, 40); - u32 data1 = bit::extract(hexInstruction, 55, 48); - u32 vdst = bit::extract(hexInstruction, 63, 56); - - m_instruction.opcode = static_cast(u32(op) + static_cast(OpcodeMap::OP_MAP_DS)); - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = addr; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = data0; - m_instruction.src[2].field = OperandField::VectorGPR; - m_instruction.src[2].code = data1; - m_instruction.dst[0].field = OperandField::VectorGPR; - m_instruction.dst[0].code = vdst; - m_instruction.dst_count = 1; - - m_instruction.control.ds = *reinterpret_cast(&hexInstruction); - - auto instFormat = InstructionFormat(InstEncoding::DS, (u32)op); - - m_instruction.control.ds.dual = - op == OpcodeDS::DS_WRITE2_B32 || op == OpcodeDS::DS_WRXCHG2_RTN_B32 || - op == OpcodeDS::DS_READ2_B32 || op == OpcodeDS::DS_WRITE2_B64 || - op == OpcodeDS::DS_WRXCHG2_RTN_B64 || op == OpcodeDS::DS_READ2_B64; - - m_instruction.control.ds.sign = instFormat.src_type == ScalarType::Sint32; - - m_instruction.control.ds.relative = - op >= OpcodeDS::DS_ADD_SRC2_U32 && op <= OpcodeDS::DS_MAX_SRC2_F64; - - m_instruction.control.ds.stride = - op == OpcodeDS::DS_WRITE2ST64_B32 || op == OpcodeDS::DS_WRXCHG2ST64_RTN_B32 || - op == OpcodeDS::DS_READ2ST64_B32 || op == OpcodeDS::DS_WRITE2ST64_B64 || - op == OpcodeDS::DS_WRXCHG2ST64_RTN_B64 || op == OpcodeDS::DS_READ2ST64_B64; - - if (op == OpcodeDS::DS_WRITE_B8 || op == OpcodeDS::DS_READ_I8 || op == OpcodeDS::DS_READ_U8) { - m_instruction.control.ds.size = 1; - } else if (op == OpcodeDS::DS_WRITE_B16 || op == OpcodeDS::DS_READ_I16 || - op == OpcodeDS::DS_READ_U16) { - m_instruction.control.ds.size = 2; - } else { - if (instFormat.src_type == ScalarType::Sint32 || - instFormat.src_type == ScalarType::Uint32) { - m_instruction.control.ds.size = 4; - } else if (instFormat.src_type == ScalarType::Sint64 || - instFormat.src_type == ScalarType::Uint64) { - m_instruction.control.ds.size = 8; - } else { - m_instruction.control.ds.size = 0; - } - } -} - -void GcnDecodeContext::decodeInstructionEXP(uint64_t hexInstruction) { - u32 vsrc0 = bit::extract(hexInstruction, 39, 32); - u32 vsrc1 = bit::extract(hexInstruction, 47, 40); - u32 vsrc2 = bit::extract(hexInstruction, 55, 48); - u32 vsrc3 = bit::extract(hexInstruction, 63, 56); - - m_instruction.opcode = Opcode::EXP; - - m_instruction.src[0].field = OperandField::VectorGPR; - m_instruction.src[0].code = vsrc0; - m_instruction.src[1].field = OperandField::VectorGPR; - m_instruction.src[1].code = vsrc1; - m_instruction.src[2].field = OperandField::VectorGPR; - m_instruction.src[2].code = vsrc2; - m_instruction.src[3].field = OperandField::VectorGPR; - m_instruction.src[3].code = vsrc3; - - m_instruction.control.exp = *reinterpret_cast(&hexInstruction); -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/format.cpp b/src/shader_recompiler/frontend/format.cpp deleted file mode 100644 index d1726f2..0000000 --- a/src/shader_recompiler/frontend/format.cpp +++ /dev/null @@ -1,4414 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/assert.h" -#include "shader_recompiler/frontend/decode.h" - -namespace Shader::Gcn { - -constexpr std::array InstructionFormatSOP2 = {{ - // 0 = S_ADD_U32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 1 = S_SUB_U32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 2 = S_ADD_I32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 3 = S_SUB_I32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 4 = S_ADDC_U32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 5 = S_SUBB_U32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 6 = S_MIN_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 7 = S_MIN_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 8 = S_MAX_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 9 = S_MAX_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 10 = S_CSELECT_B32 - {InstClass::ScalarSelect, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 11 = S_CSELECT_B64 - {InstClass::ScalarSelect, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - {}, - // 14 = S_AND_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 15 = S_AND_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 16 = S_OR_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 17 = S_OR_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 18 = S_XOR_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 19 = S_XOR_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 20 = S_ANDN2_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 21 = S_ANDN2_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 22 = S_ORN2_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 23 = S_ORN2_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 24 = S_NAND_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 25 = S_NAND_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 26 = S_NOR_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 27 = S_NOR_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 28 = S_XNOR_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 29 = S_XNOR_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 30 = S_LSHL_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 31 = S_LSHL_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 32 = S_LSHR_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 33 = S_LSHR_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 34 = S_ASHR_I32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 35 = S_ASHR_I64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 36 = S_BFM_B32 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 37 = S_BFM_B64 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint64}, - // 38 = S_MUL_I32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 39 = S_BFE_U32 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 40 = S_BFE_I32 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 41 = S_BFE_U64 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 42 = S_BFE_I64 - {InstClass::ScalarBitField, InstCategory::ScalarALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 43 = S_CBRANCH_G_FORK - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 2, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 44 = S_ABSDIFF_I32 - {InstClass::ScalarAbs, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, -}}; - -constexpr std::array InstructionFormatSOPK = {{ - // 0 = S_MOVK_I32 - {InstClass::ScalarMov, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - {}, - // 2 = S_CMOVK_I32 - {InstClass::ScalarMov, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 3 = S_CMPK_EQ_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 4 = S_CMPK_LI32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 5 = S_CMPK_GT_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 6 = S_CMPK_GE_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 7 = S_CMPK_LT_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 8 = S_CMPK_LE_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 9 = S_CMPK_EQ_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 10 = S_CMPK_LG_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 11 = S_CMPK_GT_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 12 = S_CMPK_GE_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 13 = S_CMPK_LT_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 14 = S_CMPK_LE_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 0, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 15 = S_ADDK_I32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 16 = S_MULK_I32 - {InstClass::ScalarArith, InstCategory::ScalarALU, 0, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 17 = S_CBRANCH_I_FORK - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 18 = S_GETREG_B32 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 19 = S_SETREG_B32 - {InstClass::ScalarRegAccess, InstCategory::FlowControl, 0, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 21 = S_SETREIMM32_B32 - {InstClass::ScalarRegAccess, InstCategory::FlowControl, 0, 1, ScalarType::Uint32, - ScalarType::Uint32}, -}}; - -constexpr std::array InstructionFormatSOP1 = {{ - {}, - {}, - {}, - // 3 = S_MOV_B32 - {InstClass::ScalarMov, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 4 = S_MOV_B64 - {InstClass::ScalarMov, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 5 = S_CMOV_B32 - {InstClass::ScalarMov, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 6 = S_CMOV_B64 - {InstClass::ScalarMov, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 7 = S_NOT_B32 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 8 = S_NOT_B64 - {InstClass::ScalarBitLogic, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 9 = S_WQM_B32 - {InstClass::ScalarQuadMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 10 = S_WQM_B64 - {InstClass::ScalarQuadMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 11 = S_BREV_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 12 = S_BREV_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 13 = S_BCNT0_I32_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Sint32}, - // 14 = S_BCNT0_I32_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Sint32}, - // 15 = S_BCNT1_I32_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Sint32}, - // 16 = S_BCNT1_I32_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Sint32}, - // 17 = S_FF0_I32_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Sint32}, - // 18 = S_FF0_I32_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Sint32}, - // 19 = S_FF1_I32_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Sint32}, - // 20 = S_FF1_I32_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Sint32}, - // 21 = S_FLBIT_I32_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Sint32}, - // 22 = S_FLBIT_I32_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Sint32}, - // 23 = S_FLBIT_I32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 24 = S_FLBIT_I32_I64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Sint64, - ScalarType::Sint32}, - // 25 = S_SEXT_I32_I8 - {InstClass::ScalarConv, InstCategory::ScalarALU, 1, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 26 = S_SEXT_I32_I16 - {InstClass::ScalarConv, InstCategory::ScalarALU, 1, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 27 = S_BITSET0_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 28 = S_BITSET0_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 29 = S_BITSET1_B32 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 30 = S_BITSET1_B64 - {InstClass::ScalarBitManip, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 31 = S_GETPC_B64 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 32 = S_SETPC_B64 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 33 = S_SWAPPC_B64 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 34 = S_RFE_B64 - {InstClass::Undefined, InstCategory::Undefined, 1, 1, ScalarType::Uint64, ScalarType::Uint64}, - {}, - // 36 = S_AND_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 37 = S_OR_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 38 = S_XOR_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 39 = S_ANDN2_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 40 = S_ORN2_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 41 = S_NAND_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 42 = S_NOR_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 43 = S_XNOR_SAVEEXEC_B64 - {InstClass::ScalarExecMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 44 = S_QUADMASK_B32 - {InstClass::ScalarQuadMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 45 = S_QUADMASK_B64 - {InstClass::ScalarQuadMask, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 46 = S_MOVRELS_B32 - {InstClass::ScalarMovRel, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 47 = S_MOVRELS_B64 - {InstClass::ScalarMovRel, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 48 = S_MOVRELD_B32 - {InstClass::ScalarMovRel, InstCategory::ScalarALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 49 = S_MOVRELD_B64 - {InstClass::ScalarMovRel, InstCategory::ScalarALU, 1, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 50 = S_CBRANCH_JOIN - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - {}, - // 52 = S_ABS_I32 - {InstClass::ScalarAbs, InstCategory::ScalarALU, 1, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 53 = S_MOV_FED_B32 - {InstClass::Undefined, InstCategory::Undefined, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, -}}; - -constexpr std::array InstructionFormatSOPC = {{ - // 0 = S_CMP_EQ_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 1 = S_CMP_LI32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 2 = S_CMP_GT_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 3 = S_CMP_GE_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 4 = S_CMP_LT_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 5 = S_CMP_LE_I32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 6 = S_CMP_EQ_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 7 = S_CMP_LG_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 8 = S_CMP_GT_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 9 = S_CMP_GE_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 10 = S_CMP_LT_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 11 = S_CMP_LE_U32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 12 = S_BITCMP0_B32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 13 = S_BITCMP1_B32 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 14 = S_BITCMP0_B64 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 15 = S_BITCMP1_B64 - {InstClass::ScalarCmp, InstCategory::ScalarALU, 2, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 16 = S_SETVSKIP - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 2, 1, ScalarType::Undefined, - ScalarType::Undefined}, -}}; - -constexpr std::array InstructionFormatSOPP = {{ - // 0 = S_NOP - {InstClass::ScalarWait, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 1 = S_ENDPGM - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 2 = S_BRANCH - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - {}, - // 4 = S_CBRANCH_SCC0 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 5 = S_CBRANCH_SCC1 - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 6 = S_CBRANCH_VCCZ - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 7 = S_CBRANCH_VCCNZ - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 8 = S_CBRANCH_EXECZ - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 9 = S_CBRANCH_EXECNZ - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 10 = S_BARRIER - {InstClass::ScalarSync, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - {}, - // 12 = S_WAITCNT - {InstClass::ScalarSync, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 13 = S_SETHALT - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Any, ScalarType::Any}, - // 14 = S_SLEEP - {InstClass::ScalarSync, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 15 = S_SETPRIO - {InstClass::ScalarSync, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 16 = S_SENDMSG - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 17 = S_SENDMSGHALT - {InstClass::ScalarProgFlow, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 18 = S_TRAP - {InstClass::Undefined, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 19 = S_ICACHE_INV - {InstClass::ScalarCache, InstCategory::FlowControl, 0, 1, ScalarType::Any, ScalarType::Any}, - // 20 = S_INCPERFLEVEL - {InstClass::DbgProf, InstCategory::DebugProfile, 0, 1, ScalarType::Any, ScalarType::Any}, - // 21 = S_DECPERFLEVEL - {InstClass::DbgProf, InstCategory::DebugProfile, 0, 1, ScalarType::Any, ScalarType::Any}, - // 22 = S_TTRACEDATA - {InstClass::DbgProf, InstCategory::DebugProfile, 0, 1, ScalarType::Any, ScalarType::Any}, - // 23 = S_CBRANCH_CDBGSYS - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Any, ScalarType::Any}, - // 24 = S_CBRANCH_CDBGUSER - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Any, ScalarType::Any}, - // 25 = S_CBRANCH_CDBGSYS_OR_USER - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Any, ScalarType::Any}, - // 26 = S_CBRANCH_CDBGSYS_AND_USER - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Any, ScalarType::Any}, -}}; - -constexpr std::array InstructionFormatSMRD = {{ - // 0 = S_LOAD_DWORD - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 1 = S_LOAD_DWORDX2 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 2 = S_LOAD_DWORDX4 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 3 = S_LOAD_DWORDX8 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 4 = S_LOAD_DWORDX16 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - // 8 = S_BUFFER_LOAD_DWORD - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 9 = S_BUFFER_LOAD_DWORDX2 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 10 = S_BUFFER_LOAD_DWORDX4 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 11 = S_BUFFER_LOAD_DWORDX8 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 12 = S_BUFFER_LOAD_DWORDX16 - {InstClass::ScalarMemRd, InstCategory::ScalarMemory, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 29 = S_DCACHE_INV_VOL - {InstClass::ScalarMemUt, InstCategory::ScalarMemory, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 30 = S_MEMTIME - {InstClass::ScalarMemUt, InstCategory::ScalarMemory, 0, 1, ScalarType::Any, ScalarType::Uint64}, - // 31 = S_DCACHE_INV - {InstClass::ScalarMemUt, InstCategory::ScalarMemory, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, -}}; - -constexpr std::array InstructionFormatVOP2 = {{ - // 0 = V_CNDMASK_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 1 = V_READLANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 2 = V_WRITELANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 3 = V_ADD_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 4 = V_SUB_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 5 = V_SUBREV_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 6 = V_MAC_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 7 = V_MUL_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 8 = V_MUL_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 9 = V_MUL_I32_I24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 10 = V_MUL_HI_I32_I24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 11 = V_MUL_U32_U24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 12 = V_MUL_HI_U32_U24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 13 = V_MIN_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 14 = V_MAX_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 15 = V_MIN_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 16 = V_MAX_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 17 = V_MIN_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 18 = V_MAX_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 19 = V_MIN_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 20 = V_MAX_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 21 = V_LSHR_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 22 = V_LSHRREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 23 = V_ASHR_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 24 = V_ASHRREV_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 25 = V_LSHL_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 26 = V_LSHLREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 27 = V_AND_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 28 = V_OR_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 29 = V_XOR_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 30 = V_BFM_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 31 = V_MAC_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 32 = V_MADMK_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 33 = V_MADAK_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 34 = V_BCNT_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 35 = V_MBCNT_LO_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 36 = V_MBCNT_HI_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 37 = V_ADD_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 38 = V_SUB_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 39 = V_SUBREV_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 40 = V_ADDC_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 41 = V_SUBB_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 42 = V_SUBBREV_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 43 = V_LDEXP_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 44 = V_CVT_PKACCUM_U8_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, ScalarType::Uint32}, - // 45 = V_CVT_PKNORM_I16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, ScalarType::Sint32}, - // 46 = V_CVT_PKNORM_U16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, ScalarType::Uint32}, - // 47 = V_CVT_PKRTZ_F16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, ScalarType::Uint32}, - // 48 = V_CVT_PK_U16_U32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 49 = V_CVT_PK_I16_I32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 50 = V_ADD_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 51 = V_SUB_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - // 53 = V_MUL_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - // 57 = V_MAX_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 58 = V_MIN_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, -}}; - -constexpr std::array InstructionFormatVOP3 = { - {// 0 = V_CMP_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 1 = V_CMP_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 2 = V_CMP_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 3 = V_CMP_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 4 = V_CMP_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 5 = V_CMP_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 6 = V_CMP_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 7 = V_CMP_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 8 = V_CMP_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 9 = V_CMP_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 10 = V_CMP_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 11 = V_CMP_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 12 = V_CMP_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 13 = V_CMP_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 14 = V_CMP_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 15 = V_CMP_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 16 = V_CMPX_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 17 = V_CMPX_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 18 = V_CMPX_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 19 = V_CMPX_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 20 = V_CMPX_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 21 = V_CMPX_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 22 = V_CMPX_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 23 = V_CMPX_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 24 = V_CMPX_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 25 = V_CMPX_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 26 = V_CMPX_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 27 = V_CMPX_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 28 = V_CMPX_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 29 = V_CMPX_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 30 = V_CMPX_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 31 = V_CMPX_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 32 = V_CMP_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 33 = V_CMP_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 34 = V_CMP_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 35 = V_CMP_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 36 = V_CMP_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 37 = V_CMP_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 38 = V_CMP_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 39 = V_CMP_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 40 = V_CMP_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 41 = V_CMP_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 42 = V_CMP_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 43 = V_CMP_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 44 = V_CMP_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 45 = V_CMP_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 46 = V_CMP_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 47 = V_CMP_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 48 = V_CMPX_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 49 = V_CMPX_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 50 = V_CMPX_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 51 = V_CMPX_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 52 = V_CMPX_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 53 = V_CMPX_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 54 = V_CMPX_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 55 = V_CMPX_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 56 = V_CMPX_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 57 = V_CMPX_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 58 = V_CMPX_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 59 = V_CMPX_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 60 = V_CMPX_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 61 = V_CMPX_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 62 = V_CMPX_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 63 = V_CMPX_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 64 = V_CMPS_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 65 = V_CMPS_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 66 = V_CMPS_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 67 = V_CMPS_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 68 = V_CMPS_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 69 = V_CMPS_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 70 = V_CMPS_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 71 = V_CMPS_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 72 = V_CMPS_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 73 = V_CMPS_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 74 = V_CMPS_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 75 = V_CMPS_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 76 = V_CMPS_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 77 = V_CMPS_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 78 = V_CMPS_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 79 = V_CMPS_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 80 = V_CMPSX_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 81 = V_CMPSX_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 82 = V_CMPSX_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 83 = V_CMPSX_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 84 = V_CMPSX_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 85 = V_CMPSX_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 86 = V_CMPSX_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 87 = V_CMPSX_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 88 = V_CMPSX_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 89 = V_CMPSX_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 90 = V_CMPSX_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 91 = V_CMPSX_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 92 = V_CMPSX_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 93 = V_CMPSX_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 94 = V_CMPSX_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 95 = V_CMPSX_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 96 = V_CMPS_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 97 = V_CMPS_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 98 = V_CMPS_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 99 = V_CMPS_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 100 = V_CMPS_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 101 = V_CMPS_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 102 = V_CMPS_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 103 = V_CMPS_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 104 = V_CMPS_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 105 = V_CMPS_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 106 = V_CMPS_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 107 = V_CMPS_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 108 = V_CMPS_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 109 = V_CMPS_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 110 = V_CMPS_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 111 = V_CMPS_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 112 = V_CMPSX_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 113 = V_CMPSX_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 114 = V_CMPSX_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 115 = V_CMPSX_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 116 = V_CMPSX_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 117 = V_CMPSX_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 118 = V_CMPSX_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 119 = V_CMPSX_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 120 = V_CMPSX_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 121 = V_CMPSX_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 122 = V_CMPSX_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 123 = V_CMPSX_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 124 = V_CMPSX_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 125 = V_CMPSX_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 126 = V_CMPSX_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 127 = V_CMPSX_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 128 = V_CMP_F_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 129 = V_CMP_LT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 130 = V_CMP_EQ_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 131 = V_CMP_LE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 132 = V_CMP_GT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 133 = V_CMP_NE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 134 = V_CMP_GE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 135 = V_CMP_T_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 136 = V_CMP_CLASS_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 137 = V_CMP_LT_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 138 = V_CMP_EQ_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 139 = V_CMP_LE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 140 = V_CMP_GT_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 141 = V_CMP_NE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 142 = V_CMP_GE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - {}, - // 144 = V_CMPX_F_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 145 = V_CMPX_LT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 146 = V_CMPX_EQ_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 147 = V_CMPX_LE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 148 = V_CMPX_GT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 149 = V_CMPX_NE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 150 = V_CMPX_GE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 151 = V_CMPX_T_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 152 = V_CMPX_CLASS_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 160 = V_CMP_F_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 161 = V_CMP_LT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 162 = V_CMP_EQ_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 163 = V_CMP_LE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 164 = V_CMP_GT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 165 = V_CMP_NE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 166 = V_CMP_GE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 167 = V_CMP_T_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 168 = V_CMP_CLASS_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 176 = V_CMPX_F_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 177 = V_CMPX_LT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 178 = V_CMPX_EQ_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 179 = V_CMPX_LE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 180 = V_CMPX_GT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 181 = V_CMPX_NE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 182 = V_CMPX_GE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 183 = V_CMPX_T_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 184 = V_CMPX_CLASS_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 192 = V_CMP_F_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 193 = V_CMP_LT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 194 = V_CMP_EQ_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 195 = V_CMP_LE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 196 = V_CMP_GT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 197 = V_CMP_NE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 198 = V_CMP_GE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 199 = V_CMP_T_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 200 = V_CMP_F_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 201 = V_CMP_LT_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 202 = V_CMP_EQ_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 203 = V_CMP_LE_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 204 = V_CMP_GT_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 205 = V_CMP_LG_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 206 = V_CMP_GE_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 207 = V_CMP_O_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 208 = V_CMPX_F_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 209 = V_CMPX_LT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 210 = V_CMPX_EQ_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 211 = V_CMPX_LE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 212 = V_CMPX_GT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 213 = V_CMPX_NE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 214 = V_CMPX_GE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 215 = V_CMPX_T_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 224 = V_CMP_F_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 225 = V_CMP_LT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 226 = V_CMP_EQ_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 227 = V_CMP_LE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 228 = V_CMP_GT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 229 = V_CMP_NE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 230 = V_CMP_GE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 231 = V_CMP_T_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 240 = V_CMPX_F_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 241 = V_CMPX_LT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 242 = V_CMPX_EQ_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 243 = V_CMPX_LE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 244 = V_CMPX_GT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 245 = V_CMPX_NE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 246 = V_CMPX_GE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 247 = V_CMPX_T_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 256 = V_CNDMASK_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 257 = V_READLANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 258 = V_WRITELANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 259 = V_ADD_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 260 = V_SUB_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 261 = V_SUBREV_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 262 = V_MAC_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 263 = V_MUL_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 264 = V_MUL_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 265 = V_MUL_I32_I24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 266 = V_MUL_HI_I32_I24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 267 = V_MUL_U32_U24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 268 = V_MUL_HI_U32_U24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 269 = V_MIN_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 270 = V_MAX_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 271 = V_MIN_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 272 = V_MAX_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 273 = V_MIN_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 274 = V_MAX_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 275 = V_MIN_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 276 = V_MAX_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 277 = V_LSHR_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 278 = V_LSHRREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 279 = V_ASHR_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 280 = V_ASHRREV_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 281 = V_LSHL_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 282 = V_LSHLREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 283 = V_AND_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 284 = V_OR_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 285 = V_XOR_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 286 = V_BFM_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 287 = V_MAC_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 288 = V_MADMK_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 289 = V_MADAK_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 290 = V_BCNT_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 291 = V_MBCNT_LO_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 292 = V_MBCNT_HI_U32_B32 - {InstClass::VectorThreadMask, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 293 = V_ADD_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 294 = V_SUB_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 295 = V_SUBREV_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 296 = V_ADDC_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 297 = V_SUBB_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 298 = V_SUBBREV_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 299 = V_LDEXP_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 300 = V_CVT_PKACCUM_U8_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Uint32}, - // 301 = V_CVT_PKNORM_I16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 302 = V_CVT_PKNORM_U16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Uint32}, - // 303 = V_CVT_PKRTZ_F16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Uint32}, - // 304 = V_CVT_PK_U16_U32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 305 = V_CVT_PK_I16_I32 - {InstClass::VectorConv, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 306 = V_ADD_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 307 = V_SUB_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 308 = V_SUBREV_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 309 = V_MUL_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - // 313 = V_MAX_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 314 = V_MIN_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 315 = V_LDEXP_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - {}, - // 320 = V_MAD_LEGACY_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 321 = V_MAD_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 322 = V_MAD_I32_I24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 323 = V_MAD_U32_U24 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 324 = V_CUBEID_F32 - {InstClass::VectorFpGraph32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 325 = V_CUBESC_F32 - {InstClass::VectorFpGraph32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 326 = V_CUBETC_F32 - {InstClass::VectorFpGraph32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 327 = V_CUBEMA_F32 - {InstClass::VectorFpGraph32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 328 = V_BFE_U32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 329 = V_BFE_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 330 = V_BFI_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 331 = V_FMA_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 332 = V_FMA_F64 - {InstClass::VectorFpArith64, InstCategory::VectorALU, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 333 = V_LERP_U8 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 334 = V_ALIGNBIT_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 335 = V_ALIGNBYTE_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 336 = V_MULLIT_F32 - {InstClass::VectorFpGraph32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 337 = V_MIN3_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 338 = V_MIN3_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 339 = V_MIN3_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 340 = V_MAX3_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 341 = V_MAX3_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 342 = V_MAX3_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 343 = V_MED3_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 344 = V_MED3_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 345 = V_MED3_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 346 = V_SAD_U8 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 347 = V_SAD_HI_U8 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 348 = V_SAD_U16 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 349 = V_SAD_U32 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 350 = V_CVT_PK_U8_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Uint32}, - // 351 = V_DIV_FIXUP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 352 = V_DIV_FIXUP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 353 = V_LSHL_B64 - {InstClass::VectorBitField64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 354 = V_LSHR_B64 - {InstClass::VectorBitField64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 355 = V_ASHR_I64 - {InstClass::VectorBitField64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 356 = V_ADD_F64 - {InstClass::VectorFpArith64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 357 = V_MUL_F64 - {InstClass::VectorFpArith64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 358 = V_MIN_F64 - {InstClass::VectorFpArith64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 359 = V_MAX_F64 - {InstClass::VectorFpArith64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 360 = V_LDEXP_F64 - {InstClass::VectorFpField64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 361 = V_MUL_LO_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 362 = V_MUL_HI_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 363 = V_MUL_LO_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 364 = V_MUL_HI_I32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 365 = V_DIV_SCALE_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 366 = V_DIV_SCALE_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 367 = V_DIV_FMAS_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 368 = V_DIV_FMAS_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 369 = V_MSAD_U8 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 370 = V_QSAD_U8 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 371 = V_MQSAD_U8 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 372 = V_TRIG_PREOP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 373 = V_MQSAD_U32_U8 - {InstClass::VectorIntGraph, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 374 = V_MAD_U64_U32 - {InstClass::VectorIntArith64, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint64}, - // 375 = V_MAD_I64_I32 - {InstClass::VectorIntArith64, InstCategory::VectorALU, 3, 1, ScalarType::Sint32, - ScalarType::Sint64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 384 = V_NOP - {InstClass::VectorMisc, InstCategory::VectorALU, 0, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 385 = V_MOV_B32 - {InstClass::VectorRegMov, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 386 = V_READFIRSTLANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 387 = V_CVT_I32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Sint32}, - // 388 = V_CVT_F64_I32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, - ScalarType::Float64}, - // 389 = V_CVT_F32_I32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, - ScalarType::Float32}, - // 390 = V_CVT_F32_U32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 391 = V_CVT_U32_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Uint32}, - // 392 = V_CVT_I32_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 393 = V_MOV_FED_B32 - {InstClass::Undefined, InstCategory::Undefined, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 394 = V_CVT_F16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float16}, - // 395 = V_CVT_F32_F16 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float32}, - // 396 = V_CVT_RPI_I32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 397 = V_CVT_FLR_I32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 398 = V_CVT_OFF_F32_I4 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, - ScalarType::Float32}, - // 399 = V_CVT_F32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float32}, - // 400 = V_CVT_F64_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float64}, - // 401 = V_CVT_F32_UBYTE0 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 402 = V_CVT_F32_UBYTE1 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 403 = V_CVT_F32_UBYTE2 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 404 = V_CVT_F32_UBYTE3 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 405 = V_CVT_U32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Uint32}, - // 406 = V_CVT_F64_U32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 416 = V_FRACT_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 417 = V_TRUNC_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 418 = V_CEIL_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 419 = V_RNDNE_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 420 = V_FLOOR_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 421 = V_EXP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 422 = V_LOG_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 423 = V_LOG_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 424 = V_RCP_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 425 = V_RCP_LEGACY_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 426 = V_RCP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 427 = V_RCP_IFLAG_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 428 = V_RSQ_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 429 = V_RSQ_LEGACY_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 430 = V_RSQ_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 431 = V_RCP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 432 = V_RCP_CLAMP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 433 = V_RSQ_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 434 = V_RSQ_CLAMP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 435 = V_SQRT_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 436 = V_SQRT_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 437 = V_SIN_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 438 = V_COS_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 439 = V_NOT_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 440 = V_BFREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 441 = V_FFBH_U32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 442 = V_FFBL_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 443 = V_FFBH_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 444 = V_FREXP_EXP_I32_F64 - {InstClass::VectorFpField64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Sint32}, - // 445 = V_FREXP_MANT_F64 - {InstClass::VectorFpField64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 446 = V_FRACT_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 447 = V_FREXP_EXP_I32_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 448 = V_FREXP_MANT_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 449 = V_CLREXCP - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 450 = V_MOVRELD_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 451 = V_MOVRELS_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 452 = V_MOVRELSD_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 84 = V_RCP_F16 - {InstClass::VectorFpTran16, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float16}, - // 85 = V_SQRT_F16 - {InstClass::VectorFpTran16, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 771 = V_ADD_NC_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - {}, - {}, - {}, - // 775 = V_LSHRREV_B16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 776 = V_ASHRREV_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - {}, - {}, - {}, - {}, - // 781 = V_ADD_NC_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 782 = V_SUB_NC_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - {}, - // 784 = V_SUB_CO_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - // 788 = V_LSHLREV_B16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 833 = V_MAD_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 3, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - {}, - // 838 = V_LSHL_ADD_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 839 = V_ADD_LSHL_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 849 = V_MIN3_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 3, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - // 852 = V_MAX3_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 3, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - // 855 = V_MED3_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 3, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - {}, - {}, - {}, - // 862 = V_MAD_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 3, 1, ScalarType::Sint16, - ScalarType::Sint16}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 877 = V_ADD3_U32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 879 = V_LSHL_OR_B32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 881 = V_AND_OR_B32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 882 = V_OR3_B32 - {InstClass::VectorIntArith32, InstCategory::VectorALU, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}}}; - -constexpr std::array InstructionFormatVOP3P = {{ - // 0 = V_PK_MAD_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 3, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 1 = V_PK_MUL_LO_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 2 = V_PK_ADD_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 3 = V_PK_SUB_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 4 = V_PK_LSHLREV_B16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 5 = V_PK_LSHRREV_B16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 6 = V_PK_ASHRREV_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Uint16}, - // 7 = V_PK_MAX_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 8 = V_PK_MIN_I16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 9 = V_PK_MAD_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 3, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 10 = V_PK_ADD_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 11 = V_PK_SUB_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 12 = V_PK_MAX_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 13 = V_PK_MIN_U16 - {InstClass::VectorIntArith16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 14 = V_PK_FMA_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 3, 1, ScalarType::Float16, - ScalarType::Float16}, - // 15 = V_PK_ADD_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 16 = V_PK_MUL_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 17 = V_PK_MIN_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 18 = V_PK_MAX_F16 - {InstClass::VectorFpArith16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 32 = V_MAD_MIX_F32 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 33 = V_MAD_MIXLO_F16 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 34 = V_MAD_MIXHI_F16 - {InstClass::VectorFpArith32, InstCategory::VectorALU, 3, 1, ScalarType::Float32, - ScalarType::Float32}, -}}; - -constexpr std::array InstructionFormatVOP1 = {{ - // 0 = V_NOP - {InstClass::VectorMisc, InstCategory::VectorALU, 0, 1, ScalarType::Any, ScalarType::Any}, - // 1 = V_MOV_B32 - {InstClass::VectorRegMov, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 2 = V_READFIRSTLANE_B32 - {InstClass::VectorLane, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 3 = V_CVT_I32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, ScalarType::Sint32}, - // 4 = V_CVT_F64_I32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, ScalarType::Float64}, - // 5 = V_CVT_F32_I32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, ScalarType::Float32}, - // 6 = V_CVT_F32_U32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float32}, - // 7 = V_CVT_U32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, ScalarType::Uint32}, - // 8 = V_CVT_I32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, ScalarType::Sint32}, - // 9 = V_MOV_FED_B32 - {InstClass::Undefined, InstCategory::Undefined, 1, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 10 = V_CVT_F16_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float16}, - // 11 = V_CVT_F32_F16 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float32}, - // 12 = V_CVT_RPI_I32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, ScalarType::Sint32}, - // 13 = V_CVT_FLR_I32_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, ScalarType::Sint32}, - // 14 = V_CVT_OFF_F32_I4 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, ScalarType::Float32}, - // 15 = V_CVT_F32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float32}, - // 16 = V_CVT_F64_F32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float64}, - // 17 = V_CVT_F32_UBYTE0 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float32}, - // 18 = V_CVT_F32_UBYTE1 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float32}, - // 19 = V_CVT_F32_UBYTE2 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float32}, - // 20 = V_CVT_F32_UBYTE3 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float32}, - // 21 = V_CVT_U32_F64 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Float64, ScalarType::Uint32}, - // 22 = V_CVT_F64_U32 - {InstClass::VectorConv, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, ScalarType::Float64}, - // 23 = V_TRUNC_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 24 = V_CEIL_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 25 = V_RNDNE_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 26 = V_FLOOR_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - // 32 = V_FRACT_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 33 = V_TRUNC_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 34 = V_CEIL_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 35 = V_RNDNE_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 36 = V_FLOOR_F32 - {InstClass::VectorFpRound32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 37 = V_EXP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 38 = V_LOG_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 39 = V_LOG_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 40 = V_RCP_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 41 = V_RCP_LEGACY_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 42 = V_RCP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 43 = V_RCP_IFLAG_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 44 = V_RSQ_CLAMP_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 45 = V_RSQ_LEGACY_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 46 = V_RSQ_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 47 = V_RCP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 48 = V_RCP_CLAMP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 49 = V_RSQ_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 50 = V_RSQ_CLAMP_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 51 = V_SQRT_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 52 = V_SQRT_F64 - {InstClass::VectorFpTran64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 53 = V_SIN_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 54 = V_COS_F32 - {InstClass::VectorFpTran32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 55 = V_NOT_B32 - {InstClass::VectorBitLogic, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 56 = V_BFREV_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 57 = V_FFBH_U32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 58 = V_FFBL_B32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 59 = V_FFBH_I32 - {InstClass::VectorBitField32, InstCategory::VectorALU, 1, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 60 = V_FREXP_EXP_I32_F64 - {InstClass::VectorFpField64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Sint32}, - // 61 = V_FREXP_MANT_F64 - {InstClass::VectorFpField64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 62 = V_FRACT_F64 - {InstClass::VectorFpRound64, InstCategory::VectorALU, 1, 1, ScalarType::Float64, - ScalarType::Float64}, - // 63 = V_FREXP_EXP_I32_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Sint32}, - // 64 = V_FREXP_MANT_F32 - {InstClass::VectorFpField32, InstCategory::VectorALU, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 65 = V_CLREXCP - {InstClass::Undefined, InstCategory::Undefined, 0, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 66 = V_MOVRELD_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 67 = V_MOVRELS_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 68 = V_MOVRELSD_B32 - {InstClass::VectorMovRel, InstCategory::VectorALU, 1, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 84 = V_RCP_F16 - {InstClass::VectorFpTran16, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float16}, - // 85 = V_SQRT_F16 - {InstClass::VectorFpTran16, InstCategory::VectorALU, 1, 1, ScalarType::Float16, - ScalarType::Float16}, -}}; - -constexpr std::array InstructionFormatVOPC = {{ - // 0 = V_CMP_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 1 = V_CMP_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 2 = V_CMP_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 3 = V_CMP_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 4 = V_CMP_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 5 = V_CMP_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 6 = V_CMP_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 7 = V_CMP_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 8 = V_CMP_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 9 = V_CMP_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 10 = V_CMP_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 11 = V_CMP_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 12 = V_CMP_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 13 = V_CMP_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 14 = V_CMP_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 15 = V_CMP_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 16 = V_CMPX_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 17 = V_CMPX_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 18 = V_CMPX_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 19 = V_CMPX_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 20 = V_CMPX_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 21 = V_CMPX_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 22 = V_CMPX_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 23 = V_CMPX_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 24 = V_CMPX_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 25 = V_CMPX_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 26 = V_CMPX_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 27 = V_CMPX_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 28 = V_CMPX_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 29 = V_CMPX_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 30 = V_CMPX_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 31 = V_CMPX_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 32 = V_CMP_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 33 = V_CMP_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 34 = V_CMP_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 35 = V_CMP_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 36 = V_CMP_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 37 = V_CMP_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 38 = V_CMP_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 39 = V_CMP_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 40 = V_CMP_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 41 = V_CMP_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 42 = V_CMP_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 43 = V_CMP_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 44 = V_CMP_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 45 = V_CMP_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 46 = V_CMP_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 47 = V_CMP_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 48 = V_CMPX_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 49 = V_CMPX_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 50 = V_CMPX_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 51 = V_CMPX_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 52 = V_CMPX_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 53 = V_CMPX_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 54 = V_CMPX_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 55 = V_CMPX_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 56 = V_CMPX_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 57 = V_CMPX_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 58 = V_CMPX_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 59 = V_CMPX_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 60 = V_CMPX_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 61 = V_CMPX_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 62 = V_CMPX_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 63 = V_CMPX_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 64 = V_CMPS_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 65 = V_CMPS_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 66 = V_CMPS_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 67 = V_CMPS_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 68 = V_CMPS_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 69 = V_CMPS_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 70 = V_CMPS_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 71 = V_CMPS_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 72 = V_CMPS_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 73 = V_CMPS_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 74 = V_CMPS_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 75 = V_CMPS_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 76 = V_CMPS_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 77 = V_CMPS_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 78 = V_CMPS_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 79 = V_CMPS_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 80 = V_CMPSX_F_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 81 = V_CMPSX_LT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 82 = V_CMPSX_EQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 83 = V_CMPSX_LE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 84 = V_CMPSX_GT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 85 = V_CMPSX_LG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 86 = V_CMPSX_GE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 87 = V_CMPSX_O_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 88 = V_CMPSX_U_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 89 = V_CMPSX_NGE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 90 = V_CMPSX_NLG_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 91 = V_CMPSX_NGT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 92 = V_CMPSX_NLE_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 93 = V_CMPSX_NEQ_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 94 = V_CMPSX_NLT_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 95 = V_CMPSX_TRU_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 96 = V_CMPS_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 97 = V_CMPS_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 98 = V_CMPS_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 99 = V_CMPS_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 100 = V_CMPS_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 101 = V_CMPS_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 102 = V_CMPS_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 103 = V_CMPS_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 104 = V_CMPS_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 105 = V_CMPS_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 106 = V_CMPS_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 107 = V_CMPS_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 108 = V_CMPS_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 109 = V_CMPS_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 110 = V_CMPS_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 111 = V_CMPS_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 112 = V_CMPSX_F_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 113 = V_CMPSX_LT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 114 = V_CMPSX_EQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 115 = V_CMPSX_LE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 116 = V_CMPSX_GT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 117 = V_CMPSX_LG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 118 = V_CMPSX_GE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 119 = V_CMPSX_O_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 120 = V_CMPSX_U_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 121 = V_CMPSX_NGE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 122 = V_CMPSX_NLG_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 123 = V_CMPSX_NGT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 124 = V_CMPSX_NLE_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 125 = V_CMPSX_NEQ_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 126 = V_CMPSX_NLT_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 127 = V_CMPSX_TRU_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - // 128 = V_CMP_F_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 129 = V_CMP_LT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 130 = V_CMP_EQ_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 131 = V_CMP_LE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 132 = V_CMP_GT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 133 = V_CMP_NE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 134 = V_CMP_GE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 135 = V_CMP_T_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 136 = V_CMP_CLASS_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - // 137 = V_CMP_LT_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 138 = V_CMP_EQ_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 139 = V_CMP_LE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 140 = V_CMP_GT_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 141 = V_CMP_NE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - // 142 = V_CMP_GE_I16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Sint16, - ScalarType::Sint16}, - {}, - // 144 = V_CMPX_F_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 145 = V_CMPX_LT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 146 = V_CMPX_EQ_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 147 = V_CMPX_LE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 148 = V_CMPX_GT_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 149 = V_CMPX_NE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 150 = V_CMPX_GE_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 151 = V_CMPX_T_I32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 152 = V_CMPX_CLASS_F32 - {InstClass::VectorFpCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 160 = V_CMP_F_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 161 = V_CMP_LT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 162 = V_CMP_EQ_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 163 = V_CMP_LE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 164 = V_CMP_GT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 165 = V_CMP_NE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 166 = V_CMP_GE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 167 = V_CMP_T_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 168 = V_CMP_CLASS_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - // 170 = V_CMP_EQ_U16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 171 = V_CMP_LE_U16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 172 = V_CMP_GT_U16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 173 = V_CMP_NE_U16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - // 174 = V_CMP_GE_U16 - {InstClass::VectorIntCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Uint16, - ScalarType::Uint16}, - {}, - // 176 = V_CMPX_F_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 177 = V_CMPX_LT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 178 = V_CMPX_EQ_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 179 = V_CMPX_LE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 180 = V_CMPX_GT_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 181 = V_CMPX_NE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 182 = V_CMPX_GE_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 183 = V_CMPX_T_I64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 184 = V_CMPX_CLASS_F64 - {InstClass::VectorFpCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 192 = V_CMP_F_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 193 = V_CMP_LT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 194 = V_CMP_EQ_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 195 = V_CMP_LE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 196 = V_CMP_GT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 197 = V_CMP_NE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 198 = V_CMP_GE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 199 = V_CMP_T_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 200 = V_CMP_F_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 201 = V_CMP_LT_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 202 = V_CMP_EQ_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 203 = V_CMP_LE_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 204 = V_CMP_GT_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 205 = V_CMP_LG_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 206 = V_CMP_GE_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 207 = V_CMP_O_F16 - {InstClass::VectorFpCmp16, InstCategory::VectorALU, 2, 1, ScalarType::Float16, - ScalarType::Float16}, - // 208 = V_CMPX_F_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 209 = V_CMPX_LT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 210 = V_CMPX_EQ_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 211 = V_CMPX_LE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 212 = V_CMPX_GT_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 213 = V_CMPX_NE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 214 = V_CMPX_GE_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 215 = V_CMPX_T_U32 - {InstClass::VectorIntCmp32, InstCategory::VectorALU, 2, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 224 = V_CMP_F_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 225 = V_CMP_LT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 226 = V_CMP_EQ_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 227 = V_CMP_LE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 228 = V_CMP_GT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 229 = V_CMP_NE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 230 = V_CMP_GE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 231 = V_CMP_T_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 240 = V_CMPX_F_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 241 = V_CMPX_LT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 242 = V_CMPX_EQ_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 243 = V_CMPX_LE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 244 = V_CMPX_GT_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 245 = V_CMPX_NE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 246 = V_CMPX_GE_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 247 = V_CMPX_T_U64 - {InstClass::VectorIntCmp64, InstCategory::VectorALU, 2, 1, ScalarType::Uint64, - ScalarType::Uint64}, -}}; - -constexpr std::array InstructionFormatVINTRP = {{ - // 0 = V_INTERP_P1_F32 - {InstClass::VectorInterpFpCache, InstCategory::VectorInterpolation, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 1 = V_INTERP_P2_F32 - {InstClass::VectorInterpFpCache, InstCategory::VectorInterpolation, 1, 1, ScalarType::Float32, - ScalarType::Float32}, - // 2 = V_INTERP_MOV_F32 - {InstClass::VectorInterpFpCache, InstCategory::VectorInterpolation, 1, 1, ScalarType::Float32, - ScalarType::Float32}, -}}; - -constexpr std::array InstructionFormatDS = {{ - // 0 = DS_ADD_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 1 = DS_SUB_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 2 = DS_RSUB_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 3 = DS_INC_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 4 = DS_DEC_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 5 = DS_MIN_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 6 = DS_MAX_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 7 = DS_MIN_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 8 = DS_MAX_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 9 = DS_AND_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 10 = DS_OR_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 11 = DS_XOR_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 12 = DS_MSKOR_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 13 = DS_WRITE_B32 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 14 = DS_WRITE2_B32 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 15 = DS_WRITE2ST64_B32 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 16 = DS_CMPST_B32 - {InstClass::DsAtomicCmpSt32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 17 = DS_CMPST_F32 - {InstClass::DsAtomicCmpSt32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 18 = DS_MIN_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 19 = DS_MAX_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 20 = DS_NOP - {InstClass::DsDataShareMisc, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - {}, - {}, - {}, - // 24 = DS_GWS_SEMA_RELEASE_ALL - {InstClass::GdsSync, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 25 = DS_GWS_INIT - {InstClass::GdsSync, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 26 = DS_GWS_SEMA_V - {InstClass::GdsSync, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 27 = DS_GWS_SEMA_BR - {InstClass::GdsSync, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 28 = DS_GWS_SEMA_P - {InstClass::GdsSync, InstCategory::DataShare, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 29 = DS_GWS_BARRIER - {InstClass::ScalarSync, InstCategory::FlowControl, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 30 = DS_WRITE_B8 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 31 = DS_WRITE_B16 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 32 = DS_ADD_RTN_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 33 = DS_SUB_RTN_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 34 = DS_RSUB_RTN_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 35 = DS_INC_RTN_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 36 = DS_DEC_RTN_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 37 = DS_MIN_RTN_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 38 = DS_MAX_RTN_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 39 = DS_MIN_RTN_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 40 = DS_MAX_RTN_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 41 = DS_AND_RTN_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 42 = DS_OR_RTN_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 43 = DS_XOR_RTN_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 44 = DS_MSKOR_RTN_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 45 = DS_WRXCHG_RTN_B32 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 46 = DS_WRXCHG2_RTN_B32 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 47 = DS_WRXCHG2ST64_RTN_B32 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 48 = DS_CMPST_RTN_B32 - {InstClass::DsAtomicCmpSt32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 49 = DS_CMPST_RTN_F32 - {InstClass::DsAtomicCmpSt32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 50 = DS_MIN_RTN_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 51 = DS_MAX_RTN_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 52 = DS_WRAP_RTN_B32 - {InstClass::DsIdxWrap, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 53 = DS_SWIZZLE_B32 - {InstClass::DsDataShareUt, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 54 = DS_READ_B32 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 55 = DS_READ2_B32 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 56 = DS_READ2ST64_B32 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 57 = DS_READ_I8 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 58 = DS_READ_U8 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 59 = DS_READ_I16 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Sint32, ScalarType::Sint32}, - // 60 = DS_READ_U16 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 61 = DS_CONSUME - {InstClass::DsAppendCon, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 62 = DS_APPEND - {InstClass::DsAppendCon, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 63 = DS_ORDERED_COUNT - {InstClass::GdsOrdCnt, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - // 64 = DS_ADD_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 65 = DS_SUB_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 66 = DS_RSUB_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 67 = DS_INC_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 68 = DS_DEC_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 69 = DS_MIN_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 70 = DS_MAX_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 71 = DS_MIN_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 72 = DS_MAX_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 73 = DS_AND_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 74 = DS_OR_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 75 = DS_XOR_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 76 = DS_MSKOR_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 77 = DS_WRITE_B64 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 78 = DS_WRITE2_B64 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 79 = DS_WRITE2ST64_B64 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 80 = DS_CMPST_B64 - {InstClass::DsAtomicCmpSt64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 81 = DS_CMPST_F64 - {InstClass::DsAtomicCmpSt64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 82 = DS_MIN_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 83 = DS_MAX_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 96 = DS_ADD_RTN_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 97 = DS_SUB_RTN_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 98 = DS_RSUB_RTN_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 99 = DS_INC_RTN_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 100 = DS_DEC_RTN_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 101 = DS_MIN_RTN_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 102 = DS_MAX_RTN_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 103 = DS_MIN_RTN_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 104 = DS_MAX_RTN_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 105 = DS_AND_RTN_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 106 = DS_OR_RTN_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 107 = DS_XOR_RTN_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 108 = DS_MSKOR_RTN_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 109 = DS_WRXCHG_RTN_B64 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 110 = DS_WRXCHG2_RTN_B64 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 111 = DS_WRXCHG2ST64_RTN_B64 - {InstClass::DsIdxWrXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 112 = DS_CMPST_RTN_B64 - {InstClass::DsAtomicCmpSt64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 113 = DS_CMPST_RTN_F64 - {InstClass::DsAtomicCmpSt64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 114 = DS_MIN_RTN_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 115 = DS_MAX_RTN_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - // 118 = DS_READ_B64 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 119 = DS_READ2_B64 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - // 120 = DS_READ2ST64_B64 - {InstClass::DsIdxRd, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - {}, - {}, - {}, - {}, - {}, - // 126 = DS_CONDXCHG32_RTN_B64 - {InstClass::DsIdxCondXchg, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - // 128 = DS_ADD_SRC2_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 129 = DS_SUB_SRC2_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 130 = DS_RSUB_SRC2_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 131 = DS_INC_SRC2_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 132 = DS_DEC_SRC2_U32 - {InstClass::DsAtomicArith32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 133 = DS_MIN_SRC2_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 134 = DS_MAX_SRC2_I32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 135 = DS_MIN_SRC2_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 136 = DS_MAX_SRC2_U32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 137 = DS_AND_SRC2_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 138 = DS_OR_SRC2_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 139 = DS_XOR_SRC2_B32 - {InstClass::DsAtomicLogic32, InstCategory::DataShare, 3, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 141 = DS_WRITE_SRC2_B32 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint32, ScalarType::Uint32}, - {}, - {}, - {}, - {}, - // 146 = DS_MIN_SRC2_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - // 147 = DS_MAX_SRC2_F32 - {InstClass::DsAtomicMinMax32, InstCategory::DataShare, 3, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 192 = DS_ADD_SRC2_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 193 = DS_SUB_SRC2_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 194 = DS_RSUB_SRC2_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 195 = DS_INC_SRC2_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 196 = DS_DEC_SRC2_U64 - {InstClass::DsAtomicArith64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 197 = DS_MIN_SRC2_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 198 = DS_MAX_SRC2_I64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Sint64, - ScalarType::Sint64}, - // 199 = DS_MIN_SRC2_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 200 = DS_MAX_SRC2_U64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 201 = DS_AND_SRC2_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 202 = DS_OR_SRC2_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - // 203 = DS_XOR_SRC2_B64 - {InstClass::DsAtomicLogic64, InstCategory::DataShare, 3, 1, ScalarType::Uint64, - ScalarType::Uint64}, - {}, - // 205 = DS_WRITE_SRC2_B64 - {InstClass::DsIdxWr, InstCategory::DataShare, 3, 1, ScalarType::Uint64, ScalarType::Uint64}, - {}, - {}, - {}, - {}, - // 210 = DS_MIN_SRC2_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - // 211 = DS_MAX_SRC2_F64 - {InstClass::DsAtomicMinMax64, InstCategory::DataShare, 3, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 222 = DS_WRITE_B96 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 223 = DS_WRITE_B128 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 253 = DS_CONDXCHG32_RTN_B128 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 254 = DS_READ_B96 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 255 = DS_READ_B128 - {InstClass::Undefined, InstCategory::Undefined, 3, 1, ScalarType::Undefined, - ScalarType::Undefined}, -}}; - -constexpr std::array InstructionFormatMUBUF = {{ - // 0 = BUFFER_LOAD_FORMAT_X - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 1 = BUFFER_LOAD_FORMAT_XY - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 2 = BUFFER_LOAD_FORMAT_XYZ - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 3 = BUFFER_LOAD_FORMAT_XYZW - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 4 = BUFFER_STORE_FORMAT_X - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 5 = BUFFER_STORE_FORMAT_XY - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 6 = BUFFER_STORE_FORMAT_XYZ - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 7 = BUFFER_STORE_FORMAT_XYZW - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 8 = BUFFER_LOAD_UBYTE - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 9 = BUFFER_LOAD_SBYTE - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 10 = BUFFER_LOAD_USHORT - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 11 = BUFFER_LOAD_SSHORT - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 12 = BUFFER_LOAD_DWORD - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 13 = BUFFER_LOAD_DWORDX2 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 14 = BUFFER_LOAD_DWORDX4 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 15 = BUFFER_LOAD_DWORDX3 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 24 = BUFFER_STORE_BYTE - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - // 26 = BUFFER_STORE_SHORT - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - // 28 = BUFFER_STORE_DWORD - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 29 = BUFFER_STORE_DWORDX2 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 30 = BUFFER_STORE_DWORDX4 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 31 = BUFFER_STORE_DWORDX3 - {InstClass::VectorMemBufNoFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 48 = BUFFER_ATOMIC_SWAP - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 49 = BUFFER_ATOMIC_CMPSWAP - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 50 = BUFFER_ATOMIC_ADD - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 51 = BUFFER_ATOMIC_SUB - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 53 = BUFFER_ATOMIC_SMIN - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 54 = BUFFER_ATOMIC_UMIN - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 55 = BUFFER_ATOMIC_SMAX - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 56 = BUFFER_ATOMIC_UMAX - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 57 = BUFFER_ATOMIC_AND - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 58 = BUFFER_ATOMIC_OR - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 59 = BUFFER_ATOMIC_XOR - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 60 = BUFFER_ATOMIC_INC - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 61 = BUFFER_ATOMIC_DEC - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 62 = BUFFER_ATOMIC_FCMPSWAP - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 63 = BUFFER_ATOMIC_FMIN - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 64 = BUFFER_ATOMIC_FMAX - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 80 = BUFFER_ATOMIC_SWAP_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 81 = BUFFER_ATOMIC_CMPSWAP_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 82 = BUFFER_ATOMIC_ADD_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 83 = BUFFER_ATOMIC_SUB_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - {}, - // 85 = BUFFER_ATOMIC_SMIN_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 86 = BUFFER_ATOMIC_UMIN_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 87 = BUFFER_ATOMIC_SMAX_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 88 = BUFFER_ATOMIC_UMAX_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 89 = BUFFER_ATOMIC_AND_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 90 = BUFFER_ATOMIC_OR_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 91 = BUFFER_ATOMIC_XOR_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 92 = BUFFER_ATOMIC_INC_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 93 = BUFFER_ATOMIC_DEC_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Uint64, - ScalarType::Uint32}, - // 94 = BUFFER_ATOMIC_FCMPSWAP_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float64, - ScalarType::Float64}, - // 95 = BUFFER_ATOMIC_FMIN_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float64, - ScalarType::Float64}, - // 96 = BUFFER_ATOMIC_FMAX_X2 - {InstClass::VectorMemBufAtomic, InstCategory::VectorMemory, 4, 1, ScalarType::Float64, - ScalarType::Float64}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 112 = BUFFER_WBINVL1_SC - {InstClass::VectorMemL1Cache, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 113 = BUFFER_WBINVL1 - {InstClass::VectorMemL1Cache, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, -}}; - -constexpr std::array InstructionFormatMTBUF = {{ - // 0 = TBUFFER_LOAD_FORMAT_X - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 1 = TBUFFER_LOAD_FORMAT_XY - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 2 = TBUFFER_LOAD_FORMAT_XYZ - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 3 = TBUFFER_LOAD_FORMAT_XYZW - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 4 = TBUFFER_STORE_FORMAT_X - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 5 = TBUFFER_STORE_FORMAT_XY - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 6 = TBUFFER_STORE_FORMAT_XYZ - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 7 = TBUFFER_STORE_FORMAT_XYZW - {InstClass::VectorMemBufFmt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, -}}; - -constexpr std::array InstructionFormatMIMG = {{ - // 0 = IMAGE_LOAD - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 1 = IMAGE_LOAD_MIP - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 2 = IMAGE_LOAD_PCK - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 3 = IMAGE_LOAD_PCK_SGN - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 4 = IMAGE_LOAD_MIP_PCK - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 5 = IMAGE_LOAD_MIP_PCK_SGN - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 8 = IMAGE_STORE - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 9 = IMAGE_STORE_MIP - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 10 = IMAGE_STORE_PCK - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 11 = IMAGE_STORE_MIP_PCK - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 14 = IMAGE_GET_RESINFO - {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 15 = IMAGE_ATOMIC_SWAP - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 16 = IMAGE_ATOMIC_CMPSWAP - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 17 = IMAGE_ATOMIC_ADD - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 18 = IMAGE_ATOMIC_SUB - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - {}, - // 20 = IMAGE_ATOMIC_SMIN - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 21 = IMAGE_ATOMIC_UMIN - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 22 = IMAGE_ATOMIC_SMAX - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Sint32, - ScalarType::Sint32}, - // 23 = IMAGE_ATOMIC_UMAX - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 24 = IMAGE_ATOMIC_AND - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 25 = IMAGE_ATOMIC_OR - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 26 = IMAGE_ATOMIC_XOR - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 27 = IMAGE_ATOMIC_INC - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 28 = IMAGE_ATOMIC_DEC - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Uint32}, - // 29 = IMAGE_ATOMIC_FCMPSWAP - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 30 = IMAGE_ATOMIC_FMIN - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 31 = IMAGE_ATOMIC_FMAX - {InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 32 = IMAGE_SAMPLE - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 33 = IMAGE_SAMPLE_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 34 = IMAGE_SAMPLE_D - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 35 = IMAGE_SAMPLE_D_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 36 = IMAGE_SAMPLE_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 37 = IMAGE_SAMPLE_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 38 = IMAGE_SAMPLE_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 39 = IMAGE_SAMPLE_LZ - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 40 = IMAGE_SAMPLE_C - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 41 = IMAGE_SAMPLE_C_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 42 = IMAGE_SAMPLE_C_D - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 43 = IMAGE_SAMPLE_C_D_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 44 = IMAGE_SAMPLE_C_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 45 = IMAGE_SAMPLE_C_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 46 = IMAGE_SAMPLE_C_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 47 = IMAGE_SAMPLE_C_LZ - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 48 = IMAGE_SAMPLE_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 49 = IMAGE_SAMPLE_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 50 = IMAGE_SAMPLE_D_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 51 = IMAGE_SAMPLE_D_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 52 = IMAGE_SAMPLE_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 53 = IMAGE_SAMPLE_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 54 = IMAGE_SAMPLE_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 55 = IMAGE_SAMPLE_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 56 = IMAGE_SAMPLE_C_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 57 = IMAGE_SAMPLE_C_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 58 = IMAGE_SAMPLE_C_D_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 59 = IMAGE_SAMPLE_C_D_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 60 = IMAGE_SAMPLE_C_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 61 = IMAGE_SAMPLE_C_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 62 = IMAGE_SAMPLE_C_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 63 = IMAGE_SAMPLE_C_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 64 = IMAGE_GATHER4 - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 65 = IMAGE_GATHER4_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 68 = IMAGE_GATHER4_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 69 = IMAGE_GATHER4_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 70 = IMAGE_GATHER4_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 71 = IMAGE_GATHER4_LZ - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 72 = IMAGE_GATHER4_C - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 73 = IMAGE_GATHER4_C_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 76 = IMAGE_GATHER4_C_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 77 = IMAGE_GATHER4_C_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 78 = IMAGE_GATHER4_C_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 79 = IMAGE_GATHER4_C_LZ - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 80 = IMAGE_GATHER4_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 81 = IMAGE_GATHER4_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 84 = IMAGE_GATHER4_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 85 = IMAGE_GATHER4_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 86 = IMAGE_GATHER4_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 87 = IMAGE_GATHER4_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 88 = IMAGE_GATHER4_C_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 89 = IMAGE_GATHER4_C_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - {}, - {}, - // 92 = IMAGE_GATHER4_C_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 93 = IMAGE_GATHER4_C_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 94 = IMAGE_GATHER4_C_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 95 = IMAGE_GATHER4_C_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, - ScalarType::Float32}, - // 96 = IMAGE_GET_LOD - {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - // 104 = IMAGE_SAMPLE_CD - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, - ScalarType::Float32}, - // 105 = IMAGE_SAMPLE_CD_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 106 = IMAGE_SAMPLE_C_CD - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 107 = IMAGE_SAMPLE_C_CD_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 108 = IMAGE_SAMPLE_CD_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 109 = IMAGE_SAMPLE_CD_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 110 = IMAGE_SAMPLE_C_CD_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, - // 111 = IMAGE_SAMPLE_C_CD_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, -}}; - -constexpr std::array InstructionFormatEXP = {{ - {InstClass::Exp, InstCategory::Export, 4, 1, ScalarType::Float32, ScalarType::Any}, -}}; - -InstFormat InstructionFormat(InstEncoding encoding, uint32_t opcode) { - switch (encoding) { - case InstEncoding::SOP1: - return InstructionFormatSOP1[opcode]; - case InstEncoding::SOPP: - return InstructionFormatSOPP[opcode]; - case InstEncoding::SOPC: - return InstructionFormatSOPC[opcode]; - case InstEncoding::VOP1: - return InstructionFormatVOP1[opcode]; - case InstEncoding::VOPC: - return InstructionFormatVOPC[opcode]; - case InstEncoding::VOP3: - return InstructionFormatVOP3[opcode]; - case InstEncoding::VOP3P: - return InstructionFormatVOP3P[opcode]; - case InstEncoding::EXP: - return InstructionFormatEXP[opcode]; - case InstEncoding::VINTRP: - return InstructionFormatVINTRP[opcode]; - case InstEncoding::DS: - return InstructionFormatDS[opcode]; - case InstEncoding::MUBUF: - return InstructionFormatMUBUF[opcode]; - case InstEncoding::MTBUF: - return InstructionFormatMTBUF[opcode]; - case InstEncoding::MIMG: - return InstructionFormatMIMG[opcode]; - case InstEncoding::SMRD: - return InstructionFormatSMRD[opcode]; - case InstEncoding::SOPK: - return InstructionFormatSOPK[opcode]; - case InstEncoding::SOP2: - return InstructionFormatSOP2[opcode]; - case InstEncoding::VOP2: - return InstructionFormatVOP2[opcode]; - default: - UNREACHABLE(); - } - return {}; -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp deleted file mode 100644 index c638972..0000000 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ /dev/null @@ -1,353 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "shader_recompiler/frontend/translate/translate.h" -#include "shader_recompiler/ir/reg.h" -#include "shader_recompiler/runtime_info.h" - -namespace Shader::Gcn { - -void Translator::EmitDataShare(const GcnInst& inst) { - switch (inst.opcode) { - // DS - case Opcode::DS_ADD_U32: - return DS_OP(inst, AtomicOp::Add, false); - case Opcode::DS_ADD_U64: - return DS_OP(inst, AtomicOp::Add, false); - case Opcode::DS_SUB_U32: - return DS_OP(inst, AtomicOp::Sub, false); - case Opcode::DS_INC_U32: - return DS_OP(inst, AtomicOp::Inc, false); - case Opcode::DS_DEC_U32: - return DS_OP(inst, AtomicOp::Dec, false); - case Opcode::DS_MIN_I32: - return DS_OP(inst, AtomicOp::Smin, false); - case Opcode::DS_MAX_I32: - return DS_OP(inst, AtomicOp::Smax, false); - case Opcode::DS_MIN_U32: - return DS_OP(inst, AtomicOp::Umin, false); - case Opcode::DS_MAX_U32: - return DS_OP(inst, AtomicOp::Umax, false); - case Opcode::DS_AND_B32: - return DS_OP(inst, AtomicOp::And, false); - case Opcode::DS_OR_B32: - return DS_OP(inst, AtomicOp::Or, false); - case Opcode::DS_XOR_B32: - return DS_OP(inst, AtomicOp::Xor, false); - case Opcode::DS_WRITE_B32: - return DS_WRITE(32, false, false, false, inst); - case Opcode::DS_WRITE2_B32: - return DS_WRITE(32, false, true, false, inst); - case Opcode::DS_WRITE2ST64_B32: - return DS_WRITE(32, false, true, true, inst); - case Opcode::DS_ADD_RTN_U32: - return DS_OP(inst, AtomicOp::Add, true); - case Opcode::DS_SUB_RTN_U32: - return DS_OP(inst, AtomicOp::Sub, true); - case Opcode::DS_MIN_RTN_U32: - return DS_OP(inst, AtomicOp::Umin, true); - case Opcode::DS_MAX_RTN_U32: - return DS_OP(inst, AtomicOp::Umax, true); - case Opcode::DS_AND_RTN_B32: - return DS_OP(inst, AtomicOp::And, true); - case Opcode::DS_OR_RTN_B32: - return DS_OP(inst, AtomicOp::Or, true); - case Opcode::DS_XOR_RTN_B32: - return DS_OP(inst, AtomicOp::Xor, true); - case Opcode::DS_CMPST_B32: - return DS_CMPST(32, false, inst); - case Opcode::DS_CMPST_RTN_B32: - return DS_CMPST(32, true, inst); - case Opcode::DS_CMPST_B64: - return DS_CMPST(64, false, inst); - case Opcode::DS_CMPST_RTN_B64: - return DS_CMPST(64, true, inst); - case Opcode::DS_SWIZZLE_B32: - return DS_SWIZZLE_B32(inst); - case Opcode::DS_READ_B32: - return DS_READ(32, false, false, false, inst); - case Opcode::DS_READ2_B32: - return DS_READ(32, false, true, false, inst); - case Opcode::DS_READ2ST64_B32: - return DS_READ(32, false, true, true, inst); - case Opcode::DS_READ_U16: - return DS_READ(16, false, false, false, inst); - case Opcode::DS_CONSUME: - return DS_CONSUME(inst); - case Opcode::DS_APPEND: - return DS_APPEND(inst); - case Opcode::DS_WRITE_B16: - return DS_WRITE(16, false, false, false, inst); - case Opcode::DS_WRITE_B64: - return DS_WRITE(64, false, false, false, inst); - case Opcode::DS_WRITE2_B64: - return DS_WRITE(64, false, true, false, inst); - case Opcode::DS_WRITE2ST64_B64: - return DS_WRITE(64, false, true, true, inst); - case Opcode::DS_READ_B64: - return DS_READ(64, false, false, false, inst); - case Opcode::DS_READ2_B64: - return DS_READ(64, false, true, false, inst); - case Opcode::DS_READ2ST64_B64: - return DS_READ(64, false, true, true, inst); - default: - LogMissingOpcode(inst); - } -} - -// VOP2 - -void Translator::V_READFIRSTLANE_B32(const GcnInst& inst) { - const IR::U32 value{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ReadFirstLane(value, ir.GetExec())); -} - -void Translator::V_READLANE_B32(const GcnInst& inst) { - ASSERT(inst.src[0].field == OperandField::VectorGPR); - const IR::U32 value{GetSrc(inst.src[0])}; - const IR::U32 lane{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ReadLane(value, lane)); -} - -void Translator::V_WRITELANE_B32(const GcnInst& inst) { - const IR::VectorReg dst{inst.dst[0].code}; - const IR::U32 value{GetSrc(inst.src[0])}; - const IR::U32 lane{GetSrc(inst.src[1])}; - const IR::U32 old_value{GetSrc(inst.dst[0])}; - ir.SetVectorReg(dst, ir.WriteLane(old_value, value, lane)); -} - -// DS - -template -void Translator::DS_OP(const GcnInst& inst, AtomicOp op, bool rtn) { - const bool is_gds = inst.control.ds.gds; - const IR::U32 addr{GetSrc(inst.src[0])}; - const T data = [&] { - if (op == AtomicOp::Inc || op == AtomicOp::Dec) { - return T{}; - } - if constexpr (std::is_same_v) { - return GetSrc(inst.src[1]); - } else { - return GetSrc64(inst.src[1]); - } - }(); - const IR::U32 offset = - ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)); - const IR::U32 addr_offset = ir.IAdd(addr, offset); - const T original_val = [&] -> T { - switch (op) { - case AtomicOp::Add: - return ir.SharedAtomicIAdd(addr_offset, data, is_gds); - case AtomicOp::Umin: - return ir.SharedAtomicIMin(addr_offset, data, false, is_gds); - case AtomicOp::Smin: - return ir.SharedAtomicIMin(addr_offset, data, true, is_gds); - case AtomicOp::Umax: - return ir.SharedAtomicIMax(addr_offset, data, false, is_gds); - case AtomicOp::Smax: - return ir.SharedAtomicIMax(addr_offset, data, true, is_gds); - case AtomicOp::And: - return ir.SharedAtomicAnd(addr_offset, data, is_gds); - case AtomicOp::Or: - return ir.SharedAtomicOr(addr_offset, data, is_gds); - case AtomicOp::Xor: - return ir.SharedAtomicXor(addr_offset, data, is_gds); - case AtomicOp::Sub: - return ir.SharedAtomicISub(addr_offset, data, is_gds); - case AtomicOp::Inc: - return ir.SharedAtomicInc(addr_offset, is_gds); - case AtomicOp::Dec: - return ir.SharedAtomicDec(addr_offset, is_gds); - default: - UNREACHABLE(); - } - }(); - if (rtn) { - if constexpr (std::is_same_v) { - SetDst(inst.dst[0], original_val); - } else { - SetDst64(inst.dst[0], original_val); - } - } -} - -void Translator::DS_CMPST(int bit_size, bool rtn, const GcnInst& inst) { - const bool is_gds = inst.control.ds.gds; - const IR::U32 addr{GetSrc(inst.src[0])}; - const IR::U32 offset = - ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)); - const IR::U32 addr_offset = ir.IAdd(addr, offset); - if (bit_size == 64) { - const IR::U64 cmp_value{GetSrc64(inst.src[1])}; - const IR::U64 write_value{GetSrc64(inst.src[2])}; - const IR::U64 original_val = - ir.SharedAtomicCmpSwap(addr_offset, write_value, cmp_value, is_gds); - if (rtn) { - SetDst64(inst.dst[0], original_val); - } - } else { - const IR::U32 cmp_value{GetSrc(inst.src[1])}; - const IR::U32 write_value{GetSrc(inst.src[2])}; - const IR::U32 original_val = - ir.SharedAtomicCmpSwap(addr_offset, write_value, cmp_value, is_gds); - if (rtn) { - SetDst(inst.dst[0], original_val); - } - } -} - -void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, - const GcnInst& inst) { - const bool is_gds = inst.control.ds.gds; - const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; - const IR::VectorReg data0{inst.src[1].code}; - const IR::VectorReg data1{inst.src[2].code}; - const u32 offset = (inst.control.ds.offset1 << 8u) + inst.control.ds.offset0; - if (info.hw_stage == HwStage::Fragment) { - ASSERT_MSG(!is_pair && bit_size == 32 && offset % 256 == 0, - "Unexpected shared memory offset alignment: {}", offset); - ir.SetVectorReg(GetScratchVgpr(offset), ir.GetVectorReg(data0)); - return; - } - if (is_pair) { - const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); - if (bit_size == 64) { - ir.WriteShared(64, - ir.PackUint2x32(ir.CompositeConstruct(ir.GetVectorReg(data0), - ir.GetVectorReg(data0 + 1))), - addr0, is_gds); - } else if (bit_size == 32) { - ir.WriteShared(32, ir.GetVectorReg(data0), addr0, is_gds); - } else if (bit_size == 16) { - ir.WriteShared(16, ir.UConvert(16, ir.GetVectorReg(data0)), addr0, is_gds); - } - const IR::U32 addr1 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset1 * adj))); - if (bit_size == 64) { - ir.WriteShared(64, - ir.PackUint2x32(ir.CompositeConstruct(ir.GetVectorReg(data1), - ir.GetVectorReg(data1 + 1))), - addr1, is_gds); - } else if (bit_size == 32) { - ir.WriteShared(32, ir.GetVectorReg(data1), addr1, is_gds); - } else if (bit_size == 16) { - ir.WriteShared(16, ir.UConvert(16, ir.GetVectorReg(data1)), addr1, is_gds); - } - } else { - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); - if (bit_size == 64) { - const IR::Value data = - ir.CompositeConstruct(ir.GetVectorReg(data0), ir.GetVectorReg(data0 + 1)); - ir.WriteShared(bit_size, ir.PackUint2x32(data), addr0, is_gds); - } else if (bit_size == 32) { - ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0, is_gds); - } else if (bit_size == 16) { - ir.WriteShared(bit_size, ir.UConvert(16, ir.GetVectorReg(data0)), addr0, is_gds); - } - } -} - -void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, - const GcnInst& inst) { - const bool is_gds = inst.control.ds.gds; - const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; - IR::VectorReg dst_reg{inst.dst[0].code}; - const u32 offset = (inst.control.ds.offset1 << 8u) + inst.control.ds.offset0; - if (info.hw_stage == HwStage::Fragment) { - ASSERT_MSG(!is_pair && bit_size == 32 && offset % 256 == 0, - "Unexpected shared memory offset alignment: {}", offset); - ir.SetVectorReg(dst_reg, ir.GetVectorReg(GetScratchVgpr(offset))); - return; - } - if (is_pair) { - // Pair loads are either 32 or 64-bit - const u32 adj = (bit_size == 32 ? 4 : 8) * (stride64 ? 64 : 1); - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset0 * adj))); - const IR::Value data0 = ir.LoadShared(bit_size, is_signed, addr0, is_gds); - if (bit_size == 64) { - const auto vector = ir.UnpackUint2x32(IR::U64{data0}); - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(vector, 0)}); - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(vector, 1)}); - } else if (bit_size == 32) { - ir.SetVectorReg(dst_reg++, IR::U32{data0}); - } else if (bit_size == 16) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.UConvert(32, IR::U16{data0})}); - } - const IR::U32 addr1 = ir.IAdd(addr, ir.Imm32(u32(inst.control.ds.offset1 * adj))); - const IR::Value data1 = ir.LoadShared(bit_size, is_signed, addr1, is_gds); - if (bit_size == 64) { - const auto vector = ir.UnpackUint2x32(IR::U64{data1}); - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(vector, 0)}); - ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(vector, 1)}); - } else if (bit_size == 32) { - ir.SetVectorReg(dst_reg++, IR::U32{data1}); - } else if (bit_size == 16) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.UConvert(32, IR::U16{data1})}); - } - } else { - const IR::U32 addr0 = ir.IAdd(addr, ir.Imm32(offset)); - const IR::Value data = ir.LoadShared(bit_size, is_signed, addr0, is_gds); - if (bit_size == 64) { - const auto vector = ir.UnpackUint2x32(IR::U64{data}); - ir.SetVectorReg(dst_reg, IR::U32{ir.CompositeExtract(vector, 0)}); - ir.SetVectorReg(dst_reg + 1, IR::U32{ir.CompositeExtract(vector, 1)}); - } else if (bit_size == 32) { - ir.SetVectorReg(dst_reg, IR::U32{data}); - } else if (bit_size == 16) { - ir.SetVectorReg(dst_reg++, IR::U32{ir.UConvert(32, IR::U16{data})}); - } - } -} - -void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { - const u8 offset0 = inst.control.ds.offset0; - const u8 offset1 = inst.control.ds.offset1; - const IR::U32 src{GetSrc(inst.src[0])}; - if (offset1 & 0x80) { - if (offset0 == 0x0 || offset0 == 0x55 || offset0 == 0xAA || offset0 == 0xFF) { - SetDst(inst.dst[0], ir.QuadBroadcast(src, ir.Imm32(offset0 & 3))); - } else { - const IR::U32 lane_id = ir.LaneId(); - const IR::U32 id_in_quad = ir.BitwiseAnd(lane_id, ir.Imm32(3)); - const IR::U32 base = ir.ShiftLeftLogical(id_in_quad, ir.Imm32(1)); - const IR::U32 sel = ir.BitFieldExtract(ir.Imm32(offset0), base, ir.Imm32(2)); - const IR::U32 quad_base = ir.BitwiseAnd(lane_id, ir.Imm32(~3u)); - SetDst(inst.dst[0], ir.Shuffle(src, ir.BitwiseOr(quad_base, sel))); - } - } else { - const u8 and_mask = (offset0 & 0x1f) | (~u8{0} << 5); - const u8 or_mask = (offset0 >> 5) | ((offset1 & 0x3) << 3); - const u8 xor_mask = offset1 >> 2; - if (or_mask == 0u && and_mask == 255u) { - SetDst(inst.dst[0], ir.ShuffleXor(src, ir.Imm32(xor_mask))); - } else { - const IR::U32 lane_id = ir.LaneId(); - const IR::U32 local = ir.BitwiseAnd(lane_id, ir.Imm32(31u)); - const IR::U32 half = ir.BitwiseAnd(lane_id, ir.Imm32(~31u)); - const IR::U32 index = ir.BitwiseXor( - ir.BitwiseOr(ir.BitwiseAnd(local, ir.Imm32(and_mask)), ir.Imm32(or_mask)), - ir.Imm32(xor_mask)); - SetDst(inst.dst[0], ir.Shuffle(src, ir.BitwiseOr(index, half))); - } - } -} - -void Translator::DS_APPEND(const GcnInst& inst) { - const u32 inst_offset = (u32(inst.control.ds.offset1) << 8u) + inst.control.ds.offset0; - const IR::U32 base = ir.BitFieldExtract(ir.GetM0(), ir.Imm32(16), ir.Imm32(16)); - const IR::U32 gds_offset = ir.IAdd(base, ir.Imm32(inst_offset)); - const IR::U32 prev = ir.DataAppend(ir.ShiftRightLogical(gds_offset, ir.Imm32(2u))); - SetDst(inst.dst[0], prev); -} - -void Translator::DS_CONSUME(const GcnInst& inst) { - const u32 inst_offset = (u32(inst.control.ds.offset1) << 8u) + inst.control.ds.offset0; - const IR::U32 base = ir.BitFieldExtract(ir.GetM0(), ir.Imm32(16), ir.Imm32(16)); - const IR::U32 gds_offset = ir.IAdd(base, ir.Imm32(inst_offset)); - const IR::U32 prev = ir.DataConsume(ir.ShiftRightLogical(gds_offset, ir.Imm32(2u))); - SetDst(inst.dst[0], prev); -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp deleted file mode 100644 index 270052f..0000000 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ /dev/null @@ -1,696 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/assert.h" -#include "shader_recompiler/frontend/translate/translate.h" - -namespace Shader::Gcn { - -void Translator::EmitScalarAlu(const GcnInst& inst) { - switch (inst.encoding) { - case InstEncoding::SOPC: { - EmitSOPC(inst); - break; - } - case InstEncoding::SOPK: { - EmitSOPK(inst); - break; - } - default: - switch (inst.opcode) { - // SOP2 - case Opcode::S_ADD_U32: - return S_ADD_U32(inst); - case Opcode::S_SUB_U32: - return S_SUB_U32(inst); - case Opcode::S_ADD_I32: - return S_ADD_I32(inst); - case Opcode::S_SUB_I32: - return S_SUB_I32(inst); - case Opcode::S_ADDC_U32: - return S_ADDC_U32(inst); - case Opcode::S_SUBB_U32: - return S_SUBB_U32(inst); - case Opcode::S_MIN_I32: - return S_MIN_U32(true, inst); - case Opcode::S_MIN_U32: - return S_MIN_U32(false, inst); - case Opcode::S_MAX_I32: - return S_MAX_U32(true, inst); - case Opcode::S_MAX_U32: - return S_MAX_U32(false, inst); - case Opcode::S_CSELECT_B32: - return S_CSELECT_B32(inst); - case Opcode::S_CSELECT_B64: - return S_CSELECT_B64(inst); - case Opcode::S_AND_B32: - return S_AND_B32(NegateMode::None, inst); - case Opcode::S_AND_B64: - return S_AND_B64(NegateMode::None, inst); - case Opcode::S_OR_B32: - return S_OR_B32(inst); - case Opcode::S_OR_B64: - return S_OR_B64(NegateMode::None, false, inst); - case Opcode::S_XOR_B32: - return S_XOR_B32(inst); - case Opcode::S_NOT_B32: - return S_NOT_B32(inst); - case Opcode::S_XOR_B64: - return S_OR_B64(NegateMode::None, true, inst); - case Opcode::S_ANDN2_B32: - return S_AND_B32(NegateMode::Src1, inst); - case Opcode::S_ANDN2_B64: - return S_AND_B64(NegateMode::Src1, inst); - case Opcode::S_ORN2_B64: - return S_OR_B64(NegateMode::Src1, false, inst); - case Opcode::S_NAND_B32: - return S_AND_B32(NegateMode::Result, inst); - case Opcode::S_NAND_B64: - return S_AND_B64(NegateMode::Result, inst); - case Opcode::S_NOR_B64: - return S_OR_B64(NegateMode::Result, false, inst); - case Opcode::S_XNOR_B64: - return S_OR_B64(NegateMode::Result, true, inst); - case Opcode::S_LSHL_B32: - return S_LSHL_B32(inst); - case Opcode::S_LSHL_B64: - return S_LSHL_B64(inst); - case Opcode::S_LSHR_B32: - return S_LSHR_B32(inst); - case Opcode::S_ASHR_I32: - return S_ASHR_I32(inst); - case Opcode::S_ASHR_I64: - return S_ASHR_I64(inst); - case Opcode::S_BFM_B32: - return S_BFM_B32(inst); - case Opcode::S_BFM_B64: - return S_BFM_B64(inst); - case Opcode::S_MUL_I32: - return S_MUL_I32(inst); - case Opcode::S_BFE_I32: - return S_BFE(inst, true); - case Opcode::S_BFE_U32: - return S_BFE(inst, false); - case Opcode::S_ABSDIFF_I32: - return S_ABSDIFF_I32(inst); - - // SOP1 - case Opcode::S_MOV_B32: - return S_MOV(inst); - case Opcode::S_MOV_B64: - return S_MOV_B64(inst); - case Opcode::S_NOT_B64: - return S_NOT_B64(inst); - case Opcode::S_WQM_B64: - break; - case Opcode::S_BREV_B32: - return S_BREV_B32(inst); - case Opcode::S_BCNT1_I32_B32: - return S_BCNT1_I32_B32(inst); - case Opcode::S_BCNT1_I32_B64: - return S_BCNT1_I32_B64(inst); - case Opcode::S_FF1_I32_B32: - return S_FF1_I32_B32(inst); - case Opcode::S_FF1_I32_B64: - return S_FF1_I32_B64(inst); - case Opcode::S_FLBIT_I32_B32: - return S_FLBIT_I32_B32(inst); - case Opcode::S_FLBIT_I32_B64: - return S_FLBIT_I32_B64(inst); - case Opcode::S_BITSET0_B32: - return S_BITSET_B32(inst, 0); - case Opcode::S_BITSET1_B32: - return S_BITSET_B32(inst, 1); - case Opcode::S_BITSET0_B64: - return S_BITSET_B64(inst, 0); - case Opcode::S_BITSET1_B64: - return S_BITSET_B64(inst, 1); - case Opcode::S_AND_SAVEEXEC_B64: - return S_SAVEEXEC_B64(NegateMode::None, false, inst); - case Opcode::S_ORN2_SAVEEXEC_B64: - return S_SAVEEXEC_B64(NegateMode::Src1, true, inst); - case Opcode::S_ABS_I32: - return S_ABS_I32(inst); - default: - LogMissingOpcode(inst); - } - break; - } -} - -void Translator::EmitSOPC(const GcnInst& inst) { - switch (inst.opcode) { - case Opcode::S_CMP_EQ_I32: - return S_CMP(ConditionOp::EQ, true, inst); - case Opcode::S_CMP_LG_I32: - return S_CMP(ConditionOp::LG, true, inst); - case Opcode::S_CMP_GT_I32: - return S_CMP(ConditionOp::GT, true, inst); - case Opcode::S_CMP_GE_I32: - return S_CMP(ConditionOp::GE, true, inst); - case Opcode::S_CMP_LT_I32: - return S_CMP(ConditionOp::LT, true, inst); - case Opcode::S_CMP_LE_I32: - return S_CMP(ConditionOp::LE, true, inst); - - case Opcode::S_CMP_EQ_U32: - return S_CMP(ConditionOp::EQ, false, inst); - case Opcode::S_CMP_LG_U32: - return S_CMP(ConditionOp::LG, false, inst); - case Opcode::S_CMP_GT_U32: - return S_CMP(ConditionOp::GT, false, inst); - case Opcode::S_CMP_GE_U32: - return S_CMP(ConditionOp::GE, false, inst); - case Opcode::S_CMP_LT_U32: - return S_CMP(ConditionOp::LT, false, inst); - case Opcode::S_CMP_LE_U32: - return S_CMP(ConditionOp::LE, false, inst); - - case Opcode::S_BITCMP0_B32: - return S_BITCMP(false, 32, inst); - case Opcode::S_BITCMP1_B32: - return S_BITCMP(true, 32, inst); - case Opcode::S_BITCMP0_B64: - return S_BITCMP(false, 64, inst); - case Opcode::S_BITCMP1_B64: - return S_BITCMP(true, 64, inst); - - default: - LogMissingOpcode(inst); - } -} - -void Translator::EmitSOPK(const GcnInst& inst) { - switch (inst.opcode) { - // SOPK - case Opcode::S_MOVK_I32: - return S_MOVK(inst, false); - case Opcode::S_CMOVK_I32: - return S_MOVK(inst, true); - case Opcode::S_CMPK_EQ_I32: - return S_CMPK(ConditionOp::EQ, true, inst); - case Opcode::S_CMPK_LG_I32: - return S_CMPK(ConditionOp::LG, true, inst); - case Opcode::S_CMPK_GT_I32: - return S_CMPK(ConditionOp::GT, true, inst); - case Opcode::S_CMPK_GE_I32: - return S_CMPK(ConditionOp::GE, true, inst); - case Opcode::S_CMPK_LT_I32: - return S_CMPK(ConditionOp::LT, true, inst); - case Opcode::S_CMPK_LE_I32: - return S_CMPK(ConditionOp::LE, true, inst); - - case Opcode::S_CMPK_EQ_U32: - return S_CMPK(ConditionOp::EQ, false, inst); - case Opcode::S_CMPK_LG_U32: - return S_CMPK(ConditionOp::LG, false, inst); - case Opcode::S_CMPK_GT_U32: - return S_CMPK(ConditionOp::GT, false, inst); - case Opcode::S_CMPK_GE_U32: - return S_CMPK(ConditionOp::GE, false, inst); - case Opcode::S_CMPK_LT_U32: - return S_CMPK(ConditionOp::LT, false, inst); - case Opcode::S_CMPK_LE_U32: - return S_CMPK(ConditionOp::LE, false, inst); - - case Opcode::S_ADDK_I32: - return S_ADDK_I32(inst); - case Opcode::S_MULK_I32: - return S_MULK_I32(inst); - default: - LogMissingOpcode(inst); - } -} - -// SOP2 - -void Translator::S_ADD_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.IAdd(src0, src1)}; - SetDst(inst.dst[0], result); - - // SCC = tmp >= 0x100000000ULL ? 1'1U : 1'0U; - // The above assumes tmp is a 64-bit value. - // It should be enough however to test that the truncated result is less than at least one - // of the operands. In unsigned addition the result is always bigger than both the operands, - // except in the case of overflow where the truncated result is less than both. - ir.SetScc(ir.ILessThan(result, src0, false)); -} - -void Translator::S_SUB_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ISub(src0, src1)); - - // SCC = S1.u > S0.u ? 1'1U : 1'0U; - ir.SetScc(ir.IGreaterThan(src1, src0, false)); -} - -void Translator::S_SUBB_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 borrow{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))}; - const IR::U32 difference{ir.ISub(src0, src1)}; - const IR::U32 result{ir.ISub(difference, borrow)}; - SetDst(inst.dst[0], result); - - // SCC = (S1.u + SCC > S0.u) as a 33-bit compare. - const IR::U1 underflow{ir.IGreaterThan(src1, src0, false)}; - const IR::U1 borrow_underflow{ir.IGreaterThan(borrow, difference, false)}; - ir.SetScc(ir.LogicalOr(underflow, borrow_underflow)); -} - -void Translator::S_ADD_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.IAdd(src0, src1)}; - SetDst(inst.dst[0], result); - - // SCC = ((S0.u[31] == S1.u[31]) && (S0.u[31] != Result.u[31])); - const IR::U32 shift{ir.Imm32(31)}; - const IR::U32 sign0{ir.ShiftRightLogical(src0, shift)}; - const IR::U32 sign1{ir.ShiftRightLogical(src1, shift)}; - const IR::U32 signr{ir.ShiftRightLogical(result, shift)}; - ir.SetScc(ir.LogicalAnd(ir.IEqual(sign0, sign1), ir.INotEqual(sign0, signr))); -} - -void Translator::S_SUB_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ISub(src0, src1)}; - SetDst(inst.dst[0], result); - - // SCC = ((S0.u[31] != S1.u[31]) && (S0.u[31] != tmp.u[31])); - const IR::U32 shift{ir.Imm32(31)}; - const IR::U32 sign0{ir.ShiftRightLogical(src0, shift)}; - const IR::U32 sign1{ir.ShiftRightLogical(src1, shift)}; - const IR::U32 signr{ir.ShiftRightLogical(result, shift)}; - ir.SetScc(ir.LogicalAnd(ir.INotEqual(sign0, sign1), ir.INotEqual(sign0, signr))); -} - -void Translator::S_ADDC_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 carry{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))}; - const IR::U32 result1{ir.IAdd(src0, src1)}; - const IR::U32 result2{ir.IAdd(result1, carry)}; - const IR::U1 carry_out1{ir.ILessThan(result1, src0, false)}; - const IR::U1 carry_out2{ir.ILessThan(result2, result1, false)}; - SetDst(inst.dst[0], result2); - ir.SetScc(ir.LogicalOr(carry_out1, carry_out2)); -} - -void Translator::S_MIN_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result = ir.IMin(src0, src1, is_signed); - SetDst(inst.dst[0], result); - // SCC is set only when S0 is strictly smaller, equal operands clear it. - ir.SetScc(ir.ILessThan(src0, src1, is_signed)); -} - -void Translator::S_MAX_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result = ir.IMax(src0, src1, is_signed); - SetDst(inst.dst[0], result); - // SCC is set only when S0 is strictly greater, equal operands clear it. - ir.SetScc(ir.IGreaterThan(src0, src1, is_signed)); -} - -void Translator::S_CSELECT_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], IR::U32{ir.Select(ir.GetScc(), src0, src1)}); -} - -void Translator::S_CSELECT_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - const IR::U64 result{ir.Select(ir.GetScc(), src0, src1)}; - SetDst64(inst.dst[0], result); -} - -void Translator::S_AND_B32(NegateMode negate, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - IR::U32 src1{GetSrc(inst.src[1])}; - if (negate == NegateMode::Src1) { - src1 = ir.BitwiseNot(src1); - } - IR::U32 result{ir.BitwiseAnd(src0, src1)}; - if (negate == NegateMode::Result) { - result = ir.BitwiseNot(result); - } - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_AND_B64(NegateMode negate, const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - IR::U64 src1{GetSrc64(inst.src[1])}; - if (negate == NegateMode::Src1) { - src1 = ir.BitwiseNot(src1); - } - IR::U64 result = ir.BitwiseAnd(src0, src1); - if (negate == NegateMode::Result) { - result = ir.BitwiseNot(result); - } - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); - SetDst64(inst.dst[0], result); -} - -void Translator::S_OR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.BitwiseOr(src0, src1)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - IR::U64 src1{GetSrc64(inst.src[1])}; - if (negate == NegateMode::Src1) { - src1 = ir.BitwiseNot(src1); - } - IR::U64 result = is_xor ? ir.BitwiseXor(src0, src1) : ir.BitwiseOr(src0, src1); - if (negate == NegateMode::Result) { - result = ir.BitwiseNot(result); - } - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); - SetDst64(inst.dst[0], result); -} - -void Translator::S_XOR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.BitwiseXor(src0, src1)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_NOT_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 result{ir.BitwiseNot(src0)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_LSHL_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result = ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F))); - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_LSHL_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - const IR::U64 result = ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F)))); - SetDst64(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); -} - -void Translator::S_LSHR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 shift_amt = ir.BitwiseAnd(src1, ir.Imm32(0x1F)); - const IR::U32 result = ir.ShiftRightLogical(src0, shift_amt); - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_ASHR_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_ASHR_I64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - const IR::U64 result{ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))}; - SetDst64(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); -} - -void Translator::S_BFM_B32(const GcnInst& inst) { - const IR::U32 src0{ir.BitwiseAnd(GetSrc(inst.src[0]), ir.Imm32(0x1F))}; - const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x1F))}; - const IR::U32 mask{ir.ISub(ir.ShiftLeftLogical(ir.Imm32(1u), src0), ir.Imm32(1))}; - SetDst(inst.dst[0], ir.ShiftLeftLogical(mask, src1)); -} - -void Translator::S_BFM_B64(const GcnInst& inst) { - // 32-bit sources, 6-bit width and offset; SCC is not written. - const IR::U32 src0{ir.BitwiseAnd(GetSrc(inst.src[0]), ir.Imm32(0x3F))}; - const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x3F))}; - const IR::U64 mask{ir.ISub(ir.ShiftLeftLogical(ir.Imm64(u64(1)), src0), ir.Imm64(u64(1)))}; - SetDst64(inst.dst[0], ir.ShiftLeftLogical(mask, src1)); -} - -void Translator::S_MUL_I32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.IMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); -} - -void Translator::S_BFE(const GcnInst& inst, bool is_signed) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 offset{ir.BitwiseAnd(src1, ir.Imm32(0x1F))}; - const IR::U32 count{ir.BitFieldExtract(src1, ir.Imm32(16), ir.Imm32(7))}; - const IR::U32 result{ir.BitFieldExtract(src0, offset, count, is_signed)}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_ABSDIFF_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.IAbs(ir.ISub(src0, src1))}; - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -// SOPK - -void Translator::S_MOVK(const GcnInst& inst, bool is_conditional) { - const s16 simm16 = inst.control.sopk.simm; - // do the sign extension - const s32 simm32 = static_cast(simm16); - IR::U32 val = ir.Imm32(simm32); - if (is_conditional) { - // if !SCC its a NOP - val = IR::U32{ir.Select(ir.GetScc(), val, GetSrc(inst.dst[0]))}; - } - SetDst(inst.dst[0], val); -} - -void Translator::S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - const IR::U32 lhs = GetSrc(inst.dst[0]); - const IR::U32 rhs = ir.Imm32(simm16); - const IR::U1 result = [&] { - switch (cond) { - case ConditionOp::EQ: - return ir.IEqual(lhs, rhs); - case ConditionOp::LG: - return ir.INotEqual(lhs, rhs); - case ConditionOp::GT: - return ir.IGreaterThan(lhs, rhs, is_signed); - case ConditionOp::GE: - return ir.IGreaterThanEqual(lhs, rhs, is_signed); - case ConditionOp::LT: - return ir.ILessThan(lhs, rhs, is_signed); - case ConditionOp::LE: - return ir.ILessThanEqual(lhs, rhs, is_signed); - default: - UNREACHABLE(); - } - }(); - ir.SetScc(result); -} - -void Translator::S_ADDK_I32(const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - const IR::U32 src0{GetSrc(inst.dst[0])}; - const IR::U32 src1{ir.Imm32(simm16)}; - const IR::U32 result{ir.IAdd(src0, src1)}; - SetDst(inst.dst[0], result); - - const IR::U32 shift{ir.Imm32(31)}; - const IR::U32 sign0{ir.ShiftRightLogical(src0, shift)}; - const IR::U32 sign1{ir.ShiftRightLogical(src1, shift)}; - const IR::U32 signr{ir.ShiftRightLogical(result, shift)}; - ir.SetScc(ir.LogicalAnd(ir.IEqual(sign0, sign1), ir.INotEqual(sign0, signr))); -} - -void Translator::S_MULK_I32(const GcnInst& inst) { - const s32 simm16 = inst.control.sopk.simm; - SetDst(inst.dst[0], ir.IMul(GetSrc(inst.dst[0]), ir.Imm32(simm16))); -} - -// SOP1 - -void Translator::S_MOV(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::S_MOV_B64(const GcnInst& inst) { - SetDst64(inst.dst[0], GetSrc64(inst.src[0])); -} - -void Translator::S_NOT_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 result = ir.BitwiseNot(src0); - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); - SetDst64(inst.dst[0], result); -} - -void Translator::S_BREV_B32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.BitReverse(GetSrc(inst.src[0]))); -} - -void Translator::S_BCNT1_I32_B32(const GcnInst& inst) { - const IR::U32 result = ir.BitCount(GetSrc(inst.src[0])); - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_BCNT1_I32_B64(const GcnInst& inst) { - const IR::U32 result = ir.BitCount(GetSrc64(inst.src[0])); - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -void Translator::S_FF1_I32_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 result{ir.FindILsb(src0)}; - SetDst(inst.dst[0], result); -} - -void Translator::S_FF1_I32_B64(const GcnInst& inst) { - // Integer find-first-one over all 64 bits, -1 when none is set. - const IR::U64 src0{GetSrc64(inst.src[0])}; - SetDst(inst.dst[0], ir.FindILsb(src0)); -} - -void Translator::S_FLBIT_I32_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) - // position - const IR::U32 msb_pos = ir.FindUMsb(src0); - const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); - // Select 0xFFFFFFFF if src0 was 0 - const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); - SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); -} - -void Translator::S_FLBIT_I32_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) - // position - const IR::U32 msb_pos = ir.FindUMsb(src0); - const IR::U32 pos_from_left = ir.ISub(ir.Imm32(63), msb_pos); - // Select 0xFFFFFFFF if src0 was 0 - const IR::U1 cond = ir.INotEqual(src0, ir.Imm64(u64(0u))); - SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); -} - -void Translator::S_BITSET_B32(const GcnInst& inst, u32 bit_value) { - const IR::U32 old_value{GetSrc(inst.dst[0])}; - const IR::U32 offset{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0U), ir.Imm32(5U))}; - const IR::U32 result{ir.BitFieldInsert(old_value, ir.Imm32(bit_value), offset, ir.Imm32(1U))}; - SetDst(inst.dst[0], result); -} - -void Translator::S_BITSET_B64(const GcnInst& inst, u32 bit_value) { - const IR::U64 old_value{GetSrc64(inst.dst[0])}; - const IR::U32 offset{ir.BitwiseAnd(GetSrc(inst.src[0]), ir.Imm32(0x3F))}; - const IR::U64 result{ - ir.BitFieldInsert(old_value, ir.Imm64(u64(bit_value)), offset, ir.Imm32(1U))}; - SetDst64(inst.dst[0], result); -} - -void Translator::S_SAVEEXEC_B64(NegateMode negate, bool is_or, const GcnInst& inst) { - IR::U64 exec{ir.Ballot(ir.GetExec())}; - const IR::U64 src{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], exec); - - // Update EXEC. - if (negate == NegateMode::Src1) { - exec = ir.BitwiseNot(exec); - } - IR::U64 result = is_or ? ir.BitwiseOr(exec, src) : ir.BitwiseAnd(exec, src); - if (negate == NegateMode::Result) { - result = ir.BitwiseNot(result); - } - ir.SetExec(ir.InverseBallot(result)); - ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0)))); -} - -void Translator::S_ABS_I32(const GcnInst& inst) { - const auto result = ir.IAbs(GetSrc(inst.src[0])); - SetDst(inst.dst[0], result); - ir.SetScc(ir.INotEqual(result, ir.Imm32(0))); -} - -// SOPC - -void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) { - const IR::U32 lhs = GetSrc(inst.src[0]); - const IR::U32 rhs = GetSrc(inst.src[1]); - const IR::U1 result = [&] { - switch (cond) { - case ConditionOp::EQ: - return ir.IEqual(lhs, rhs); - case ConditionOp::LG: - return ir.INotEqual(lhs, rhs); - case ConditionOp::GT: - return ir.IGreaterThan(lhs, rhs, is_signed); - case ConditionOp::GE: - return ir.IGreaterThanEqual(lhs, rhs, is_signed); - case ConditionOp::LT: - return ir.ILessThan(lhs, rhs, is_signed); - case ConditionOp::LE: - return ir.ILessThanEqual(lhs, rhs, is_signed); - default: - UNREACHABLE(); - } - }(); - ir.SetScc(result); -} - -void Translator::S_BITCMP(bool compare_mode, u32 bits, const GcnInst& inst) { - const IR::U1 result = [&] { - const IR::U32 src1 = GetSrc(inst.src[1]); - const IR::U32 mask = ir.Imm32(bits == 64 ? 0x3f : 0x1f); - const IR::U32 bitpos{ir.BitwiseAnd(src1, mask)}; - const IR::U32 bittest = [&]() -> IR::U32 { - if (bits == 64) { - const IR::U64 src0 = GetSrc64(inst.src[0]); - const IR::U64 bit{ - ir.BitwiseAnd(ir.ShiftRightLogical(src0, bitpos), ir.Imm64(u64(1)))}; - return IR::U32{ir.CompositeExtract(ir.UnpackUint2x32(bit), 0)}; - } - if (bits != 32) { - UNREACHABLE(); - } - const IR::U32 src0 = GetSrc(inst.src[0]); - return ir.BitwiseAnd(ir.ShiftRightLogical(src0, bitpos), ir.Imm32(1)); - }(); - - if (!compare_mode) { - return ir.IEqual(bittest, ir.Imm32(0)); - } else { - return ir.IEqual(bittest, ir.Imm32(1)); - } - }(); - ir.SetScc(result); -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp deleted file mode 100644 index 921dcda..0000000 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ /dev/null @@ -1,1259 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/io_file.h" -#include "common/path_util.h" -#include "core/emulator_settings.h" -#include "shader_recompiler/frontend/decode.h" -#include "shader_recompiler/frontend/fetch_shader.h" -#include "shader_recompiler/frontend/translate/translate.h" -#include "shader_recompiler/info.h" -#include "shader_recompiler/ir/attribute.h" -#include "shader_recompiler/ir/condition.h" -#include "shader_recompiler/ir/reg.h" -#include "shader_recompiler/ir/reinterpret.h" -#include "shader_recompiler/profile.h" -#include "shader_recompiler/runtime_info.h" -#include "video_core/amdgpu/resource.h" - -#include -#include -#include - -namespace Shader::Gcn { - -static IR::VectorReg IterateBarycentrics(const RuntimeInfo& runtime_info, auto&& set_attribute) { - if (runtime_info.hw_stage != HwStage::Fragment) { - return IR::VectorReg::V0; - } - u32 dst_vreg{}; - const auto addr_flags = runtime_info.hw.fs.addr_flags; - if (addr_flags.persp_sample_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmoothSample, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmoothSample, 1); // J - } - if (addr_flags.persp_center_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmooth, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmooth, 1); // J - } - if (addr_flags.persp_centroid_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmoothCentroid, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordSmoothCentroid, 1); // J - } - if (addr_flags.persp_pull_model_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordPullModel, 0); // I/W - set_attribute(dst_vreg++, IR::Attribute::BaryCoordPullModel, 1); // J/W - set_attribute(dst_vreg++, IR::Attribute::BaryCoordPullModel, 2); // 1/W - } - if (addr_flags.linear_sample_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPerspSample, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPerspSample, 1); // J - } - if (addr_flags.linear_center_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPersp, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPersp, 1); // J - } - if (addr_flags.linear_centroid_ena) { - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPerspCentroid, 0); // I - set_attribute(dst_vreg++, IR::Attribute::BaryCoordNoPerspCentroid, 1); // J - } - if (addr_flags.line_stipple_tex_ena) { - ++dst_vreg; - } - return IR::VectorReg(dst_vreg); -} - -static s8 UdRegFromShOffset(u16 sgpr_offset, HwStage hw_stage) { - static constexpr std::array indirect_sgpr_offsets{0u, 0x4cu, 0u, 0xccu, 0u, 0x14cu}; - if (sgpr_offset) { - const u32 ud_reg = sgpr_offset - indirect_sgpr_offsets[u32(hw_stage)]; - ASSERT_MSG(ud_reg < 16, "Out of bounds indirect SGPR copy"); - return ud_reg; - } - return -1; -} - -Translator::Translator(Info& info_, const RuntimeInfo& runtime_info_, const Profile& profile_) - : info{info_}, runtime_info{runtime_info_}, profile{profile_}, - next_vgpr_num{runtime_info.props.num_allocated_vgprs} { - IterateBarycentrics(runtime_info, [this](u32 vreg, IR::Attribute attrib, u32) { - vgpr_to_interp[vreg] = attrib; - }); -} - -void Translator::EmitPrologue(IR::Block* first_block) { - ir = IR::IREmitter(*first_block, first_block->begin()); - - ir.Prologue(); - ir.SetExec(ir.Imm1(true)); - - // Initialize user data. - IR::ScalarReg dst_sreg = IR::ScalarReg::S0; - for (u32 i = 0; i < runtime_info.props.num_user_data; i++) { - ir.SetScalarReg(dst_sreg, ir.GetUserData(dst_sreg)); - ++dst_sreg; - } - - IR::VectorReg dst_vreg = IR::VectorReg::V0; - switch (info.sw_stage) { - case SwStage::Vertex: { - const s8 base_vertex_sgpr = - UdRegFromShOffset(runtime_info.sw.vs.vertex_sgpr_offset, info.hw_stage); - if (base_vertex_sgpr != -1) { - ir.SetScalarReg(IR::ScalarReg(base_vertex_sgpr), - ir.GetAttributeU32(IR::Attribute::BaseVertex)); - } - const s8 base_instance_sgpr = - UdRegFromShOffset(runtime_info.sw.vs.instance_sgpr_offset, info.hw_stage); - if (base_instance_sgpr != -1) { - ir.SetScalarReg(IR::ScalarReg(base_instance_sgpr), - ir.GetAttributeU32(IR::Attribute::BaseInstance)); - } - - // v0: vertex ID, always present - IR::U32 vertex_id = ir.GetAttributeU32(IR::Attribute::VertexId); - if (base_vertex_sgpr != -1) { - if (!fetch_data.Empty() || fetch_data.vertex_offset_sgpr == -1) { - vertex_id = ir.ISub(vertex_id, ir.GetAttributeU32(IR::Attribute::BaseVertex)); - } else { - ASSERT_MSG(fetch_data.vertex_offset_sgpr == base_vertex_sgpr, - "Fetch shader in indirect draw uses wrong base vertex"); - } - } - ir.SetVectorReg(dst_vreg++, vertex_id); - - if (info.hw_stage == HwStage::Local) { - // v1: rel patch ID - if (runtime_info.props.num_input_vgprs > 0) { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - // v2: unknown - if (runtime_info.props.num_input_vgprs > 1) { - ++dst_vreg; - } - } else { - // v1: instance ID, step rate 0 - if (runtime_info.props.num_input_vgprs > 0) { - if (runtime_info.sw.vs.step_rate_0 != 0) { - ir.SetVectorReg(dst_vreg++, - ir.IDiv(ir.GetAttributeU32(IR::Attribute::InstanceId), - ir.Imm32(runtime_info.sw.vs.step_rate_0))); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - } - // v2: instance ID, step rate 1 - if (runtime_info.props.num_input_vgprs > 1) { - if (runtime_info.sw.vs.step_rate_1 != 0) { - ir.SetVectorReg(dst_vreg++, - ir.IDiv(ir.GetAttributeU32(IR::Attribute::InstanceId), - ir.Imm32(runtime_info.sw.vs.step_rate_1))); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - } - } - - // v3: instance ID, plain - if (runtime_info.props.num_input_vgprs > 2) { - IR::U32 instance_id = ir.GetAttributeU32(IR::Attribute::InstanceId); - if (base_instance_sgpr != -1) { - if (!fetch_data.Empty() || fetch_data.instance_offset_sgpr == -1) { - instance_id = - ir.ISub(instance_id, ir.GetAttributeU32(IR::Attribute::BaseInstance)); - } else { - ASSERT_MSG(fetch_data.instance_offset_sgpr == base_instance_sgpr, - "Fetch shader in indirect draw uses wrong base instance"); - } - } - ir.SetVectorReg(dst_vreg++, instance_id); - } - break; - } - case SwStage::Fragment: { - dst_vreg = - IterateBarycentrics(runtime_info, [this](u32 vreg, IR::Attribute attrib, u32 comp) { - if (profile.supports_amd_shader_explicit_vertex_parameter || - profile.supports_fragment_shader_barycentric) { - ir.SetVectorReg(IR::VectorReg(vreg), ir.GetAttribute(attrib, comp)); - } - }); - const auto addr_flags = runtime_info.hw.fs.addr_flags; - const auto en_flags = runtime_info.hw.fs.en_flags; - if (addr_flags.pos_x_float_ena) { - if (en_flags.pos_x_float_ena) { - ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 0)); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); - } - } - if (addr_flags.pos_y_float_ena) { - if (en_flags.pos_y_float_ena) { - ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 1)); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); - } - } - if (addr_flags.pos_z_float_ena) { - if (en_flags.pos_z_float_ena) { - ir.SetVectorReg(dst_vreg++, ir.GetAttribute(IR::Attribute::FragCoord, 2)); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); - } - } - if (addr_flags.pos_w_float_ena) { - if (en_flags.pos_w_float_ena) { - ir.SetVectorReg(dst_vreg++, - ir.FPRecip(ir.GetAttribute(IR::Attribute::FragCoord, 3))); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0.0f)); - } - } - if (addr_flags.front_face_ena) { - if (en_flags.front_face_ena) { - const IR::U1 front_face = ir.GetAttributeU1(IR::Attribute::IsFrontFace); - if (runtime_info.hw.fs.front_face_all_bits) { - ir.SetVectorReg(dst_vreg++, - IR::U32{ir.Select(front_face, ir.Imm32(1), ir.Imm32(0))}); - } else { - ir.SetVectorReg(dst_vreg++, IR::F32{ir.Select(front_face, ir.Imm32(1.0f), - ir.Imm32(-1.0f))}); - } - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - } - if (addr_flags.ancillary_ena) { - if (en_flags.ancillary_ena) { - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::PackedAncillary)); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - } - if (addr_flags.sample_coverage_ena) { - if (en_flags.sample_coverage_ena) { - const u32 num_samples = std::clamp(runtime_info.hw.fs.num_samples, 1U, 16U); - IR::U32 coverage = ir.Imm32(1U); - if (num_samples > 1) { - const u32 valid_samples = (1U << num_samples) - 1U; - coverage = ir.BitwiseAnd(ir.GetAttributeU32(IR::Attribute::SampleMask), - ir.Imm32(valid_samples)); - } - const IR::U1 is_helper = ir.GetAttributeU1(IR::Attribute::IsHelperInvocation); - ir.SetVectorReg(dst_vreg++, IR::U32{ir.Select(is_helper, ir.Imm32(0U), coverage)}); - } else { - ir.SetVectorReg(dst_vreg++, ir.Imm32(0)); - } - } - break; - } - case SwStage::TessellationControl: { - ir.SetVectorReg(IR::VectorReg::V0, ir.GetAttributeU32(IR::Attribute::PrimitiveId)); - // Should be laid out like: - // [0:8]: patch id within VGT - // [8:12]: output control point id - ir.SetVectorReg(IR::VectorReg::V1, - ir.GetAttributeU32(IR::Attribute::PackedHullInvocationInfo)); - - if (runtime_info.sw.tcs.offchip_lds_enable) { - // No off-chip tessellation has been observed yet. If this survives dead code elim, - // revisit - ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::OffChipLdsBase)); - } - ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::TessFactorsBufferBase)); - - break; - } - case SwStage::TessellationEval: - ir.SetVectorReg(IR::VectorReg::V0, - ir.GetAttribute(IR::Attribute::TessellationEvaluationPointU)); - ir.SetVectorReg(IR::VectorReg::V1, - ir.GetAttribute(IR::Attribute::TessellationEvaluationPointV)); - // V2 is similar to PrimitiveID but not the same. It seems to only be used in - // compiler-generated address calculations. Its probably the patch id within the - // patches running locally on a given VGT (or CU, whichever is the granularity of LDS - // memory) - // Set to 0. See explanation in comment describing hull/domain passes - ir.SetVectorReg(IR::VectorReg::V2, ir.Imm32(0u)); - // V3 is the actual PrimitiveID as intended by the shader author. - ir.SetVectorReg(IR::VectorReg::V3, ir.GetAttributeU32(IR::Attribute::PrimitiveId)); - break; - case SwStage::Compute: - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 0)); - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 1)); - ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::LocalInvocationId, 2)); - - if (runtime_info.hw.cs.tgid_enable[0]) { - ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 0)); - } - if (runtime_info.hw.cs.tgid_enable[1]) { - ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 1)); - } - if (runtime_info.hw.cs.tgid_enable[2]) { - ir.SetScalarReg(dst_sreg++, ir.GetAttributeU32(IR::Attribute::WorkgroupId, 2)); - } - break; - case SwStage::Geometry: - // The GS wave receives one ES vertex offset per input primitive vertex in V0-V6, with - // the primitive id in V2. The offset count is a property of the input primitive type; - // adjacency primitives carry up to 6 vertices. - switch (runtime_info.hw.gs.in_primitive) { - case AmdGpu::PrimitiveType::AdjTriangleList: - case AmdGpu::PrimitiveType::AdjTriangleStrip: - ir.SetVectorReg(IR::VectorReg::V6, ir.Imm32(5u)); // vertex 5 - ir.SetVectorReg(IR::VectorReg::V5, ir.Imm32(4u)); // vertex 4 - [[fallthrough]]; - case AmdGpu::PrimitiveType::AdjLineList: - case AmdGpu::PrimitiveType::AdjLineStrip: - ir.SetVectorReg(IR::VectorReg::V4, ir.Imm32(3u)); // vertex 3 - [[fallthrough]]; - case AmdGpu::PrimitiveType::TriangleList: - case AmdGpu::PrimitiveType::TriangleStrip: - case AmdGpu::PrimitiveType::RectList: - ir.SetVectorReg(IR::VectorReg::V3, ir.Imm32(2u)); // vertex 2 - [[fallthrough]]; - case AmdGpu::PrimitiveType::LineList: - case AmdGpu::PrimitiveType::LineStrip: - ir.SetVectorReg(IR::VectorReg::V1, ir.Imm32(1u)); // vertex 1 - [[fallthrough]]; - default: - ir.SetVectorReg(IR::VectorReg::V0, ir.Imm32(0u)); // vertex 0 - break; - } - ir.SetVectorReg(IR::VectorReg::V2, ir.GetAttributeU32(IR::Attribute::PrimitiveId)); - break; - default: - UNREACHABLE_MSG("Unknown shader stage"); - } -} - -IR::VectorReg Translator::GetScratchVgpr(u32 offset) { - const auto [it, is_new] = vgpr_map.try_emplace(offset); - if (is_new) { - ASSERT_MSG(next_vgpr_num < 256, "Out of VGPRs"); - const auto new_vgpr = static_cast(next_vgpr_num++); - it->second = new_vgpr; - } - return it->second; -} - -template -T Translator::GetSrc(const InstOperand& operand) { - constexpr bool is_float = std::is_same_v; - - const auto get_imm = [&](auto value) -> T { - if constexpr (is_float) { - return ir.Imm32(std::bit_cast(value)); - } else { - return ir.Imm32(std::bit_cast(value)); - } - }; - - T value{}; - switch (operand.field) { - case OperandField::ScalarGPR: - value = ir.GetScalarReg(IR::ScalarReg(operand.code)); - break; - case OperandField::VectorGPR: - value = ir.GetVectorReg(IR::VectorReg(operand.code)); - break; - case OperandField::ConstZero: - value = get_imm(0U); - break; - case OperandField::SignedConstIntPos: - value = get_imm(operand.code - SignedConstIntPosMin + 1); - break; - case OperandField::SignedConstIntNeg: - value = get_imm(-s32(operand.code) + SignedConstIntNegMin - 1); - break; - case OperandField::LiteralConst: - value = get_imm(operand.code); - break; - case OperandField::ConstFloatPos_1_0: - value = get_imm(1.f); - break; - case OperandField::ConstFloatPos_0_5: - value = get_imm(0.5f); - break; - case OperandField::ConstFloatPos_2_0: - value = get_imm(2.0f); - break; - case OperandField::ConstFloatPos_4_0: - value = get_imm(4.0f); - break; - case OperandField::ConstFloatNeg_0_5: - value = get_imm(-0.5f); - break; - case OperandField::ConstFloatNeg_1_0: - value = get_imm(-1.0f); - break; - case OperandField::ConstFloatNeg_2_0: - value = get_imm(-2.0f); - break; - case OperandField::ConstFloatNeg_4_0: - value = get_imm(-4.0f); - break; - case OperandField::Inv2Pi: - value = get_imm(static_cast(1.0f / (2.0f * std::numbers::pi))); - break; - case OperandField::Sdwa: - UNREACHABLE_MSG("unhandled SDWA"); - case OperandField::Dpp: - UNREACHABLE_MSG("unhandled DPP"); - case OperandField::VccLo: - if constexpr (is_float) { - value = ir.BitCast(ir.GetVccLo()); - } else { - value = ir.GetVccLo(); - } - break; - case OperandField::VccHi: - if constexpr (is_float) { - value = ir.BitCast(ir.GetVccHi()); - } else { - value = ir.GetVccHi(); - } - break; - case OperandField::M0: - if constexpr (is_float) { - value = ir.BitCast(ir.GetM0()); - } else { - value = ir.GetM0(); - } - break; - case OperandField::Scc: - if constexpr (is_float) { - UNREACHABLE(); - } else { - value = IR::U32{ir.Select(ir.GetScc(), ir.Imm32(1u), ir.Imm32(0u))}; - } - break; - case OperandField::ExecLo: - if constexpr (is_float) { - value = ir.BitCast( - IR::U32{ir.CompositeExtract(ir.UnpackUint2x32(ir.Ballot(ir.GetExec())), 0)}); - } else { - value = IR::U32{ir.CompositeExtract(ir.UnpackUint2x32(ir.Ballot(ir.GetExec())), 0)}; - } - break; - case OperandField::ExecHi: - if constexpr (is_float) { - value = ir.BitCast( - IR::U32{ir.CompositeExtract(ir.UnpackUint2x32(ir.Ballot(ir.GetExec())), 1)}); - } else { - value = IR::U32{ir.CompositeExtract(ir.UnpackUint2x32(ir.Ballot(ir.GetExec())), 1)}; - } - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } - - if constexpr (is_float) { - if (operand.input_modifier.abs) { - value = ir.FPAbs(value); - } - if (operand.input_modifier.neg) { - value = ir.FPNeg(value); - } - } else { - if (operand.input_modifier.abs) { - value = ir.BitwiseAnd(value, ir.Imm32(0x7FFFFFFFu)); - } - if (operand.input_modifier.neg) { - value = ir.BitwiseXor(value, ir.Imm32(0x80000000u)); - } - } - return value; -} - -template IR::U32 Translator::GetSrc(const InstOperand&); -template IR::F32 Translator::GetSrc(const InstOperand&); - -template -T Translator::GetSrc16(const InstOperand& operand) { - constexpr bool is_float = std::is_same_v; - - const auto get_imm = [&](auto value) -> T { - if constexpr (is_float) { - return ir.Imm32(std::bit_cast(value)); - } else { - return ir.Imm32(std::bit_cast(value)); - } - }; - - const auto number_format = []() -> AmdGpu::NumberFormat { - if constexpr (is_float) { - return AmdGpu::NumberFormat::Float; - } else { - return AmdGpu::NumberFormat::Uint; - } - }(); - - const auto bitcast_to_u = [&](auto value) -> IR::U32 { - if constexpr (is_float) { - return ir.BitCast(value); - } else { - return value; - } - }; - - const auto cast = [&](auto value) -> T { - if constexpr (is_float) { - return value; - } else { - return ir.BitFieldExtract(ir.BitCast(value), ir.Imm32(0), ir.Imm32(16), - is_signed); - } - }; - - const auto op_sel = operand.op_sel.op_sel; - - T value{}; - switch (operand.field) { - case OperandField::ScalarGPR: { - const auto f = ir.GetScalarReg(IR::ScalarReg(operand.code)); - value = cast(IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(number_format, bitcast_to_u(f)), op_sel ? 1 : 0)}); - break; - } - case OperandField::VectorGPR: { - const auto v = ir.GetVectorReg(IR::VectorReg(operand.code)); - value = cast(IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(number_format, bitcast_to_u(v)), op_sel ? 1 : 0)}); - break; - } - case OperandField::ConstZero: - value = get_imm(0U); - break; - case OperandField::SignedConstIntPos: - value = get_imm(operand.code - SignedConstIntPosMin + 1); - break; - case OperandField::SignedConstIntNeg: - value = get_imm(-s32(operand.code) + SignedConstIntNegMin - 1); - break; - case OperandField::LiteralConst: - value = get_imm(operand.code); - break; - case OperandField::ConstFloatPos_1_0: - value = get_imm(1.f); - break; - case OperandField::ConstFloatPos_0_5: - value = get_imm(0.5f); - break; - case OperandField::ConstFloatPos_2_0: - value = get_imm(2.0f); - break; - case OperandField::ConstFloatPos_4_0: - value = get_imm(4.0f); - break; - case OperandField::ConstFloatNeg_0_5: - value = get_imm(-0.5f); - break; - case OperandField::ConstFloatNeg_1_0: - value = get_imm(-1.0f); - break; - case OperandField::ConstFloatNeg_2_0: - value = get_imm(-2.0f); - break; - case OperandField::ConstFloatNeg_4_0: - value = get_imm(-4.0f); - break; - case OperandField::Inv2Pi: - value = get_imm(static_cast(1.0f / (2.0f * std::numbers::pi))); - break; - case OperandField::Sdwa: - LOG_ERROR(Render_Recompiler, "unhandled SDWA"); - value = get_imm(0U); - break; - case OperandField::Dpp: - LOG_ERROR(Render_Recompiler, "unhandled DPP"); - value = get_imm(0U); - break; - case OperandField::VccLo: - if constexpr (is_float) { - value = IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(number_format, ir.GetVccLo()), op_sel ? 1 : 0)}; - } else { - value = cast(IR::F32{ir.CompositeExtract( - ir.Unpack2x16(number_format, bitcast_to_u(ir.GetVccLo())), op_sel ? 1 : 0)}); - } - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } - - if constexpr (is_float) { - if (operand.input_modifier.abs) { - value = ir.FPAbs(value); - } - if (operand.input_modifier.neg) { - value = ir.FPNeg(value); - } - } else { - if (operand.input_modifier.abs) { - value = ir.BitwiseAnd(value, ir.Imm32(0x7FFFFFFFu)); - } - if (operand.input_modifier.neg) { - value = ir.BitwiseXor(value, ir.Imm32(0x80000000u)); - } - } - return value; -} - -template IR::U32 Translator::GetSrc16(const InstOperand&); -template IR::U32 Translator::GetSrc16(const InstOperand&); -template IR::F32 Translator::GetSrc16(const InstOperand&); - -IR::F32 Translator::GetSrcMix(const InstOperand& operand) { - const auto get_imm = [&](auto value) -> IR::F32 { - return ir.Imm32(std::bit_cast(value)); - }; - - const auto extract = [&](auto value) -> IR::F32 { - const auto getter_u = [&]() { - if constexpr (std::same_as) { - return ir.GetScalarReg(value); - } else { - return ir.GetVectorReg(value); - } - }(); - if (!operand.op_sel.op_sel_hi) { - if constexpr (std::same_as) { - return ir.GetScalarReg(value); - } else { - return ir.GetVectorReg(value); - } - } else if (operand.op_sel.op_sel) { - return IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(AmdGpu::NumberFormat::Float, getter_u), 1)}; - } else { - return IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(AmdGpu::NumberFormat::Float, getter_u), 0)}; - } - }; - - IR::F32 value{}; - switch (operand.field) { - case OperandField::ScalarGPR: - value = extract(IR::ScalarReg(operand.code)); - break; - case OperandField::VectorGPR: - value = extract(IR::VectorReg(operand.code)); - break; - case OperandField::ConstZero: - value = get_imm(0U); - break; - case OperandField::SignedConstIntPos: - value = get_imm(operand.code - SignedConstIntPosMin + 1); - break; - case OperandField::SignedConstIntNeg: - value = get_imm(-s32(operand.code) + SignedConstIntNegMin - 1); - break; - case OperandField::LiteralConst: - value = get_imm(operand.code); - break; - case OperandField::ConstFloatPos_1_0: - value = get_imm(1.f); - break; - case OperandField::ConstFloatPos_0_5: - value = get_imm(0.5f); - break; - case OperandField::ConstFloatPos_2_0: - value = get_imm(2.0f); - break; - case OperandField::ConstFloatPos_4_0: - value = get_imm(4.0f); - break; - case OperandField::ConstFloatNeg_0_5: - value = get_imm(-0.5f); - break; - case OperandField::ConstFloatNeg_1_0: - value = get_imm(-1.0f); - break; - case OperandField::ConstFloatNeg_2_0: - value = get_imm(-2.0f); - break; - case OperandField::ConstFloatNeg_4_0: - value = get_imm(-4.0f); - break; - case OperandField::VccLo: { - if (!operand.op_sel.op_sel_hi) { - value = ir.BitCast(ir.GetVccLo()); - } else if (operand.op_sel.op_sel) { - value = IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(AmdGpu::NumberFormat::Float, ir.GetVccLo()), 1)}; - } else { - value = IR::F32{ - ir.CompositeExtract(ir.Unpack2x16(AmdGpu::NumberFormat::Float, ir.GetVccLo()), 0)}; - } - break; - } - case OperandField::VccHi: - UNREACHABLE(); - break; - case OperandField::M0: - UNREACHABLE(); - break; - case OperandField::Scc: - UNREACHABLE(); - break; - case OperandField::Inv2Pi: - value = get_imm(static_cast(1.0f / (2.0f * std::numbers::pi))); - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } - - if (operand.input_modifier.neg_hi) { - value = ir.FPAbs(value); - } - if (operand.input_modifier.neg) { - value = ir.FPNeg(value); - } - return value; -} - -template -T Translator::GetSrc64(const InstOperand& operand) { - constexpr bool is_float = std::is_same_v; - - const auto get_imm = [&](auto value) -> T { - if constexpr (is_float) { - return ir.Imm64(std::bit_cast(value)); - } else { - return ir.Imm64(std::bit_cast(value)); - } - }; - - T value{}; - switch (operand.field) { - case OperandField::ScalarGPR: { - const auto value_lo = ir.GetScalarReg(IR::ScalarReg(operand.code)); - const auto value_hi = ir.GetScalarReg(IR::ScalarReg(operand.code + 1)); - if constexpr (is_float) { - value = ir.PackDouble2x32(ir.CompositeConstruct(value_lo, value_hi)); - } else { - value = ir.PackUint2x32(ir.CompositeConstruct(value_lo, value_hi)); - } - break; - } - case OperandField::VectorGPR: { - const auto value_lo = ir.GetVectorReg(IR::VectorReg(operand.code)); - const auto value_hi = ir.GetVectorReg(IR::VectorReg(operand.code + 1)); - if constexpr (is_float) { - value = ir.PackDouble2x32(ir.CompositeConstruct(value_lo, value_hi)); - } else { - value = ir.PackUint2x32(ir.CompositeConstruct(value_lo, value_hi)); - } - break; - } - case OperandField::ConstZero: - value = get_imm(0ULL); - break; - case OperandField::SignedConstIntPos: - value = get_imm(s64(operand.code) - SignedConstIntPosMin + 1); - break; - case OperandField::SignedConstIntNeg: - value = get_imm(-s64(operand.code) + SignedConstIntNegMin - 1); - break; - case OperandField::LiteralConst: - if constexpr (is_float) { - value = get_imm(u64(operand.code) << 32); - } else { - value = get_imm(u64(operand.code)); - } - break; - case OperandField::ConstFloatPos_1_0: - value = get_imm(1.0); - break; - case OperandField::ConstFloatPos_0_5: - value = get_imm(0.5); - break; - case OperandField::ConstFloatPos_2_0: - value = get_imm(2.0); - break; - case OperandField::ConstFloatPos_4_0: - value = get_imm(4.0); - break; - case OperandField::ConstFloatNeg_0_5: - value = get_imm(-0.5); - break; - case OperandField::ConstFloatNeg_1_0: - value = get_imm(-1.0); - break; - case OperandField::ConstFloatNeg_2_0: - value = get_imm(-2.0); - break; - case OperandField::ConstFloatNeg_4_0: - value = get_imm(-4.0); - break; - case OperandField::VccLo: - if constexpr (is_float) { - value = ir.PackDouble2x32(ir.CompositeConstruct(ir.GetVccLo(), ir.GetVccHi())); - } else { - value = ir.PackUint2x32(ir.CompositeConstruct(ir.GetVccLo(), ir.GetVccHi())); - } - break; - case OperandField::ExecLo: - if constexpr (is_float) { - UNREACHABLE(); - } else { - value = ir.Ballot(ir.GetExec()); - } - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } - - if constexpr (is_float) { - if (operand.input_modifier.abs) { - value = ir.FPAbs(value); - } - if (operand.input_modifier.neg) { - value = ir.FPNeg(value); - } - } else { - // GCN VOP3 abs/neg modifier bits operate on the sign bit (bit 63 for - // 64-bit values). Unpack, modify the high dword's bit 31, repack. - if (operand.input_modifier.abs) { - const auto unpacked = ir.UnpackUint2x32(value); - const auto lo = IR::U32{ir.CompositeExtract(unpacked, 0)}; - const auto hi = IR::U32{ir.CompositeExtract(unpacked, 1)}; - const auto hi_abs = ir.BitwiseAnd(hi, ir.Imm32(0x7FFFFFFFu)); - value = ir.PackUint2x32(ir.CompositeConstruct(lo, hi_abs)); - } - if (operand.input_modifier.neg) { - const auto unpacked = ir.UnpackUint2x32(value); - const auto lo = IR::U32{ir.CompositeExtract(unpacked, 0)}; - const auto hi = IR::U32{ir.CompositeExtract(unpacked, 1)}; - const auto hi_neg = ir.BitwiseXor(hi, ir.Imm32(0x80000000u)); - value = ir.PackUint2x32(ir.CompositeConstruct(lo, hi_neg)); - } - } - return value; -} - -template IR::U64 Translator::GetSrc64(const InstOperand&); -template IR::F64 Translator::GetSrc64(const InstOperand&); - -template -pk_type Translator::GetSrcPk(const InstOperand& operand) { - constexpr bool is_float = std::is_same_v; - - const auto get_imm = [&](auto value) -> pk_type { - if constexpr (is_float) { - auto imm = ir.Imm32(std::bit_cast(value)); - return {operand.op_sel.op_sel ? ir.Imm32(0.f) : imm, - operand.op_sel.op_sel_hi ? ir.Imm32(0.f) : imm}; - } else { - auto imm = ir.Imm32(std::bit_cast(value)); - return {operand.op_sel.op_sel ? ir.Imm32(0U) : imm, - operand.op_sel.op_sel_hi ? ir.Imm32(0U) : imm}; - } - }; - - constexpr auto number_format = [&]() { - if constexpr (is_float) { - return AmdGpu::NumberFormat::Float; - } else { - return AmdGpu::NumberFormat::Uint; - } - }(); - - const auto cast = [&](auto value) -> T { - if constexpr (is_float) { - return value; - } else { - return ir.BitFieldExtract(ir.BitCast(value), ir.Imm32(0), ir.Imm32(16), - is_signed); - } - }; - - const auto extract = [&](auto value) -> pk_type { - auto v_unpacked = ir.Unpack2x16(number_format, value); - return {cast(IR::F32{ir.CompositeExtract(v_unpacked, operand.op_sel.op_sel)}), - cast(IR::F32{ir.CompositeExtract(v_unpacked, operand.op_sel.op_sel_hi)})}; - }; - - pk_type value{}; - switch (operand.field) { - case OperandField::ScalarGPR: { - value = extract(ir.GetScalarReg(IR::ScalarReg(operand.code))); - break; - } - case OperandField::VectorGPR: { - value = extract(ir.GetVectorReg(IR::VectorReg(operand.code))); - break; - } - case OperandField::ConstZero: { - value = get_imm(0U); - break; - } - case OperandField::SignedConstIntPos: { - value = get_imm(operand.code - SignedConstIntPosMin + 1); - break; - } - case OperandField::SignedConstIntNeg: { - value = get_imm(-s32(operand.code) + SignedConstIntNegMin - 1); - break; - } - case OperandField::LiteralConst: { - value = get_imm(operand.code); - break; - } - case OperandField::ConstFloatPos_1_0: { - value = get_imm(1.f); - break; - } - case OperandField::ConstFloatPos_0_5: { - value = get_imm(0.5f); - break; - } - case OperandField::ConstFloatPos_2_0: { - value = get_imm(2.0f); - break; - } - case OperandField::ConstFloatPos_4_0: { - value = get_imm(4.0f); - break; - } - case OperandField::ConstFloatNeg_0_5: { - value = get_imm(-0.5f); - break; - } - case OperandField::ConstFloatNeg_1_0: { - value = get_imm(-1.0f); - break; - } - case OperandField::ConstFloatNeg_2_0: { - value = get_imm(-2.0f); - break; - } - case OperandField::ConstFloatNeg_4_0: { - value = get_imm(-4.0f); - break; - } - case OperandField::Inv2Pi: { - value = get_imm(1.0f / (2.0f * std::numbers::pi_v)); - break; - } - case OperandField::VccLo: - value = extract(ir.GetVccLo()); - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } - - if constexpr (is_float) { - if (operand.input_modifier.neg) { - value.first = ir.FPNeg(value.first); - } - if (operand.input_modifier.neg_hi) { - value.second = ir.FPNeg(value.second); - } - } else { - if (operand.input_modifier.neg) { - value.first = ir.INeg(value.first); - } - if (operand.input_modifier.neg_hi) { - value.second = ir.INeg(value.second); - } - } - return value; -} - -template pk_type Translator::GetSrcPk(const InstOperand&); -template pk_type Translator::GetSrcPk(const InstOperand&); -template pk_type Translator::GetSrcPk(const InstOperand&); - -void Translator::SetDst(const InstOperand& operand, const IR::U32F32& value) { - IR::U32F32 result = value; - if (value.Type() == IR::Type::F32) { - if (operand.output_modifier.multiplier != 0.f) { - result = ir.FPMul(result, ir.Imm32(operand.output_modifier.multiplier)); - } - if (operand.output_modifier.clamp) { - result = ir.FPSaturate(result); - } - } - - switch (operand.field) { - case OperandField::ScalarGPR: - return ir.SetScalarReg(IR::ScalarReg(operand.code), result); - case OperandField::VectorGPR: - return ir.SetVectorReg(IR::VectorReg(operand.code), result); - case OperandField::VccLo: - return ir.SetVccLo(result); - case OperandField::VccHi: - return ir.SetVccHi(result); - case OperandField::M0: - return ir.SetM0(result); - default: - UNREACHABLE_MSG("Unknown field {}", u32(operand.field)); - } -} - -template -void Translator::SetDst16(const InstOperand& operand, const IR::U32F32& value) { - IR::U32F32 result = value; - if (value.Type() == IR::Type::F32) { - if (operand.output_modifier.multiplier != 0.f) { - result = ir.FPMul(result, ir.Imm32(operand.output_modifier.multiplier)); - } - if (operand.output_modifier.clamp) { - result = ir.FPSaturate(result); - } - } else { - if (operand.output_modifier.clamp) { - if constexpr (is_signed) { - result = ir.SClamp(result, ir.Imm32(-32768), ir.Imm32(32767)); - } else { - result = ir.UMin(result, ir.Imm32(0xFFFF)); - } - } - } - - const auto cast = [&](auto value) -> IR::U32 { - if (value.Type() == IR::Type::F32) { - return ir.UConvert(32, ir.BitCast(IR::F16{ir.FPConvert(16, value)})); - } else if (value.Type() == IR::Type::U32) { - return value; - } else { - UNREACHABLE(); - } - }; - - const auto op_sel = operand.op_sel.op_sel; - - switch (operand.field) { - case OperandField::ScalarGPR: { - const auto prev_dst = ir.GetScalarReg(IR::ScalarReg(operand.code)); - const auto result_16 = cast(result); - const auto new_dst = - ir.BitFieldInsert(prev_dst, result_16, ir.Imm32(op_sel ? 16 : 0), ir.Imm32(16)); - return ir.SetScalarReg(IR::ScalarReg(operand.code), new_dst); - } - case OperandField::VectorGPR: { - const auto prev_dst = ir.GetVectorReg(IR::VectorReg(operand.code)); - const auto result_16 = cast(result); - const auto new_dst = - ir.BitFieldInsert(prev_dst, result_16, ir.Imm32(op_sel ? 16 : 0), ir.Imm32(16)); - return ir.SetVectorReg(IR::VectorReg(operand.code), new_dst); - } - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } -} - -template void Translator::SetDst16(const InstOperand&, const IR::U32F32& value); -template void Translator::SetDst16(const InstOperand&, const IR::U32F32& value); - -void Translator::SetDst64(const InstOperand& operand, const IR::U64F64& value_raw) { - IR::U64F64 value_untyped = value_raw; - - const bool is_float = value_raw.Type() == IR::Type::F64 || value_raw.Type() == IR::Type::F32; - if (is_float) { - if (operand.output_modifier.multiplier != 0.f) { - value_untyped = - ir.FPMul(value_untyped, ir.Imm64(f64(operand.output_modifier.multiplier))); - } - if (operand.output_modifier.clamp) { - value_untyped = ir.FPSaturate(value_untyped); - } - } - - const auto split = [&] -> std::pair { - const IR::Value unpacked{is_float ? ir.UnpackDouble2x32(IR::F64{value_untyped}) - : ir.UnpackUint2x32(IR::U64{value_untyped})}; - const IR::U32 lo{ir.CompositeExtract(unpacked, 0U)}; - const IR::U32 hi{ir.CompositeExtract(unpacked, 1U)}; - return {lo, hi}; - }; - switch (operand.field) { - case OperandField::ScalarGPR: { - const auto [lo, hi] = split(); - ir.SetScalarReg(IR::ScalarReg(operand.code + 1), hi); - ir.SetScalarReg(IR::ScalarReg(operand.code), lo); - break; - } - case OperandField::VectorGPR: { - const auto [lo, hi] = split(); - ir.SetVectorReg(IR::VectorReg(operand.code + 1), hi); - ir.SetVectorReg(IR::VectorReg(operand.code), lo); - break; - } - case OperandField::VccLo: { - const auto [lo, hi] = split(); - ir.SetVccLo(lo); - ir.SetVccHi(hi); - break; - } - case OperandField::ExecLo: - ir.SetExec(ir.InverseBallot(value_untyped)); - break; - default: - UNREACHABLE_MSG("Unexpected operand: {}", std::to_underlying(operand.field)); - } -} - -template -void Translator::SetDstPk(const InstOperand& operand, const pk_type& value) { - pk_type v = value; - - if constexpr (std::is_same_v) { - if (operand.output_modifier.clamp) { - v = {ir.FPSaturate(v.first), ir.FPSaturate(v.second)}; - } - } else { - if (operand.output_modifier.clamp) { - if constexpr (is_signed) { - auto lower = ir.Imm32(-32768); - auto upper = ir.Imm32(32767); - v = {ir.SClamp(v.first, lower, upper), ir.SClamp(v.second, lower, upper)}; - } else { - auto imm = ir.Imm32(0xFFFF); - v = {ir.UMin(v.first, imm), ir.UMin(v.second, imm)}; - } - } - } - - IR::U32 value_raw{}; - if constexpr (std::is_same_v) { - value_raw = - ir.Pack2x16(AmdGpu::NumberFormat::Float, ir.CompositeConstruct(v.first, v.second)); - } else { - value_raw = ir.Pack2x16(AmdGpu::NumberFormat::Uint, - ir.CompositeConstruct(ir.BitCast(v.first), - ir.BitCast(v.second))); - } - SetDst(operand, value_raw); -} - -template void Translator::SetDstPk(const InstOperand& operand, - const pk_type& value); -template void Translator::SetDstPk(const InstOperand& operand, - const pk_type& value); -template void Translator::SetDstPk(const InstOperand& operand, - const pk_type& value); - -void Translator::EmitFetch(const GcnInst& inst) { - const auto code_sgpr_base = inst.src[0].code; - - if (EmulatorSettings.IsInlineFetchShader()) { - // Translate fetch shader inline using regular buffer bindings; useful for debugging. - const auto* code = GetFetchShaderCode(info, code_sgpr_base); - GcnCodeSlice slice(code, code + std::numeric_limits::max()); - GcnDecodeContext decoder; - - // Decode and save instructions - while (!slice.atEnd()) { - const auto sub_inst = decoder.decodeInstruction(slice); - if (sub_inst.opcode == Opcode::S_SETPC_B64) { - // Assume we're swapping back to the main shader. - break; - } - TranslateInstruction(sub_inst); - } - return; - } - - info.has_fetch_shader = true; - info.fetch_shader_sgpr_base = code_sgpr_base; - ASSERT(ParseFetchShader(info, fetch_data)); - - if (EmulatorSettings.IsDumpShaders()) { - using namespace Common::FS; - const auto dump_dir = GetUserPath(PathType::ShaderDir) / "dumps"; - if (!std::filesystem::exists(dump_dir)) { - std::filesystem::create_directories(dump_dir); - } - const auto filename = fmt::format("vs_{:#018x}.fetch.bin", info.pgm_hash); - const auto file = IOFile{dump_dir / filename, FileAccessMode::Create}; - const auto* code = GetFetchShaderCode(info, code_sgpr_base); - file.WriteRaw(code, fetch_data.size); - } - - for (u32 semantic = 0; semantic < fetch_data.attributes.size(); ++semantic) { - const auto& attrib = fetch_data.attributes[semantic]; - const IR::Attribute attr{IR::Attribute::Param0 + semantic}; - IR::VectorReg dst_reg{attrib.dest_vgpr}; - - // Read the V# of the attribute to figure out component number and type. - const auto buffer = attrib.GetSharp(info); - const auto values = - ir.CompositeConstruct(ir.GetAttribute(attr, 0), ir.GetAttribute(attr, 1), - ir.GetAttribute(attr, 2), ir.GetAttribute(attr, 3)); - const auto converted = - IR::ApplyReadNumberConversionVec4(ir, values, buffer.GetNumberConversion()); - const auto swizzled = ApplySwizzle(ir, converted, buffer.DstSelect()); - for (u32 i = 0; i < attrib.num_elements; i++) { - ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(swizzled, i)}); - } - } -} - -void Translator::LogMissingOpcode(const GcnInst& inst) { - LOG_ERROR(Render_Recompiler, "Unknown opcode {} ({}, category = {})", - magic_enum::enum_name(inst.opcode), u32(inst.opcode), - magic_enum::enum_name(inst.category)); - info.translation_failed = true; -} - -void Translator::Translate(IR::Block* block, u32 start_pc, IR::Condition cond, - std::span inst_list) { - // A block can be empty when it only enters an EXEC scope; it still needs its condition. - ir = IR::IREmitter{*block, block->begin()}; - pc = start_pc; - for (const auto& inst : inst_list) { - pc += inst.length; - - // Special case for emitting fetch shader. - if (inst.opcode == Opcode::S_SWAPPC_B64) { - ASSERT(info.hw_stage == HwStage::Vertex || info.hw_stage == HwStage::Export || - info.hw_stage == HwStage::Local); - EmitFetch(inst); - continue; - } - - TranslateInstruction(inst); - } - if (cond != IR::Condition::True && cond != IR::Condition::False) { - block->branch_cond = ir.ConditionRef(ir.Condition(cond)); - } -} - -void Translator::TranslateInstruction(const GcnInst& inst) { - // Emit instructions for each category. - switch (inst.category) { - case InstCategory::DataShare: - EmitDataShare(inst); - break; - case InstCategory::VectorInterpolation: - EmitVectorInterpolation(inst); - break; - case InstCategory::ScalarMemory: - EmitScalarMemory(inst); - break; - case InstCategory::VectorMemory: - EmitVectorMemory(inst); - break; - case InstCategory::Export: - EmitExport(inst); - break; - case InstCategory::FlowControl: - EmitFlowControl(inst); - break; - case InstCategory::ScalarALU: - EmitScalarAlu(inst); - break; - case InstCategory::VectorALU: - EmitVectorAlu(inst); - break; - case InstCategory::DebugProfile: - break; - default: - UNREACHABLE(); - } -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h deleted file mode 100644 index 15536da..0000000 --- a/src/shader_recompiler/frontend/translate/translate.h +++ /dev/null @@ -1,401 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include "shader_recompiler/frontend/fetch_shader.h" -#include "shader_recompiler/frontend/instruction.h" -#include "shader_recompiler/info.h" -#include "shader_recompiler/ir/basic_block.h" -#include "shader_recompiler/ir/condition.h" -#include "shader_recompiler/ir/ir_emitter.h" - -namespace Shader { -struct Info; -struct Profile; -} // namespace Shader - -namespace Shader::Gcn { - -enum class ConditionOp : u32 { - F, - EQ, - LG, // NE - GT, - GE, - LT, - LE, - TRU, - U, -}; - -enum class AtomicOp : u32 { - Swap, - CmpSwap, - Add, - Sub, - Smin, - Umin, - Smax, - Umax, - And, - Or, - Xor, - Inc, - Dec, - FCmpSwap, - Fmin, - Fmax, -}; - -enum class NegateMode : u32 { - None, - Src1, - Result, -}; - -template -using pk_type = std::pair; - -static constexpr size_t MaxInterpVgpr = 16; - -class Translator { -public: - explicit Translator(Info& info, const RuntimeInfo& runtime_info, const Profile& profile); - - void Translate(IR::Block* block, u32 pc, IR::Condition cond, - std::span inst_list); - void TranslateInstruction(const GcnInst& inst); - - // Instruction categories - void EmitPrologue(IR::Block* first_block); - void EmitFetch(const GcnInst& inst); - void EmitExport(const GcnInst& inst); - void EmitFlowControl(const GcnInst& inst); - void EmitScalarAlu(const GcnInst& inst); - void EmitScalarMemory(const GcnInst& inst); - void EmitVectorAlu(const GcnInst& inst); - void EmitVectorInterpolation(const GcnInst& inst); - void EmitDataShare(const GcnInst& inst); - void EmitVectorMemory(const GcnInst& inst); - - // Instruction encodings - void EmitSOPC(const GcnInst& inst); - void EmitSOPK(const GcnInst& inst); - - // Scalar ALU - // SOP2 - void S_ADD_U32(const GcnInst& inst); - void S_SUB_U32(const GcnInst& inst); - void S_SUBB_U32(const GcnInst& inst); - void S_ADD_I32(const GcnInst& inst); - void S_SUB_I32(const GcnInst& inst); - void S_ADDC_U32(const GcnInst& inst); - void S_MIN_U32(bool is_signed, const GcnInst& inst); - void S_MAX_U32(bool is_signed, const GcnInst& inst); - void S_CSELECT_B32(const GcnInst& inst); - void S_CSELECT_B64(const GcnInst& inst); - void S_AND_B32(NegateMode negate, const GcnInst& inst); - void S_AND_B64(NegateMode negate, const GcnInst& inst); - void S_OR_B32(const GcnInst& inst); - void S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst); - void S_XOR_B32(const GcnInst& inst); - void S_LSHL_B32(const GcnInst& inst); - void S_LSHL_B64(const GcnInst& inst); - void S_LSHR_B32(const GcnInst& inst); - void S_ASHR_I32(const GcnInst& inst); - void S_ASHR_I64(const GcnInst& inst); - void S_BFM_B32(const GcnInst& inst); - void S_BFM_B64(const GcnInst& inst); - void S_MUL_I32(const GcnInst& inst); - void S_BFE(const GcnInst& inst, bool is_signed); - void S_BFE_I32(const GcnInst& inst); - void S_ABSDIFF_I32(const GcnInst& inst); - void S_NOT_B32(const GcnInst& inst); - - // SOPK - void S_MOVK(const GcnInst& inst, bool is_conditional); - void S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst); - void S_ADDK_I32(const GcnInst& inst); - void S_MULK_I32(const GcnInst& inst); - - // SOP1 - void S_MOV(const GcnInst& inst); - void S_MOV_B64(const GcnInst& inst); - void S_NOT_B64(const GcnInst& inst); - void S_BREV_B32(const GcnInst& inst); - void S_BCNT1_I32_B32(const GcnInst& inst); - void S_BCNT1_I32_B64(const GcnInst& inst); - void S_FF1_I32_B32(const GcnInst& inst); - void S_FF1_I32_B64(const GcnInst& inst); - void S_FLBIT_I32_B32(const GcnInst& inst); - void S_FLBIT_I32_B64(const GcnInst& inst); - void S_BITSET_B32(const GcnInst& inst, u32 bit_value); - void S_BITSET_B64(const GcnInst& inst, u32 bit_value); - void S_GETPC_B64(const GcnInst& inst); - void S_SAVEEXEC_B64(NegateMode negate, bool is_or, const GcnInst& inst); - void S_ABS_I32(const GcnInst& inst); - - // SOPC - void S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst); - void S_BITCMP(bool compare_mode, u32 bits, const GcnInst& inst); - - // SOPP - void S_BARRIER(); - void S_SENDMSG(const GcnInst& inst); - - // Scalar Memory - // SMRD - void S_LOAD_DWORD(int num_dwords, const GcnInst& inst); - void S_BUFFER_LOAD_DWORD(int num_dwords, const GcnInst& inst); - void S_MEMTIME(const GcnInst& inst); - - // Vector ALU - // VOP2 - void V_CNDMASK_B32(const GcnInst& inst); - void V_READLANE_B32(const GcnInst& inst); - void V_WRITELANE_B32(const GcnInst& inst); - void V_ADD_F32(const GcnInst& inst); - void V_ADD_F64(const GcnInst& inst); - void V_SUB_F32(const GcnInst& inst); - void V_SUBREV_F32(const GcnInst& inst); - void V_MUL_F32(const GcnInst& inst); - void V_MUL_LEGACY_F32(const GcnInst& inst); - void V_MUL_I32_I24(const GcnInst& inst, bool is_signed); - void V_MIN_F32(const GcnInst& inst, bool is_legacy = false); - void V_MAX_F32(const GcnInst& inst, bool is_legacy = false); - void V_MIN_I32(const GcnInst& inst); - void V_MIN_U32(const GcnInst& inst); - void V_MAX_U32(bool is_signed, const GcnInst& inst); - void V_LSHR_B32(const GcnInst& inst); - void V_LSHRREV_B32(const GcnInst& inst); - void V_ASHR_I32(const GcnInst& inst); - void V_ASHRREV_I32(const GcnInst& inst); - void V_LSHL_B32(const GcnInst& inst); - void V_LSHLREV_B32(const GcnInst& inst); - void V_AND_B32(const GcnInst& inst); - void V_OR_B32(bool is_xor, const GcnInst& inst); - void V_BFM_B32(const GcnInst& inst); - void V_MAC_F32(const GcnInst& inst); - void V_MADMK_F32(const GcnInst& inst); - void V_BCNT_U32_B32(const GcnInst& inst); - void V_MBCNT_U32_B32(bool hi, const GcnInst& inst); - void V_ADD_I32(const GcnInst& inst); - void V_SUB_I32(const GcnInst& inst); - void V_SUBREV_I32(const GcnInst& inst); - void V_ADDC_U32(const GcnInst& inst); - void V_SUBB_U32(const GcnInst& inst); - void V_SUBBREV_U32(const GcnInst& inst); - void V_LDEXP_F32(const GcnInst& inst); - void V_CVT_PKNORM_U16_F32(const GcnInst& inst); - void V_CVT_PKNORM_I16_F32(const GcnInst& inst); - void V_CVT_PKRTZ_F16_F32(const GcnInst& inst); - void V_ADD_F16(const GcnInst& inst); - void V_SUB_F16(const GcnInst& inst); - void V_MUL_F16(const GcnInst& inst); - void V_MAX_F16(const GcnInst& inst); - void V_MIN_F16(const GcnInst& inst); - - // VOP1 - void V_MOV(const GcnInst& inst); - void V_READFIRSTLANE_B32(const GcnInst& inst); - void V_CVT_I32_F64(const GcnInst& inst); - void V_CVT_F64_I32(const GcnInst& inst); - void V_CVT_F64_U32(const GcnInst& inst); - void V_CVT_F32_I32(const GcnInst& inst); - void V_CVT_F32_U32(const GcnInst& inst); - void V_CVT_U32_F32(const GcnInst& inst); - void V_CVT_I32_F32(const GcnInst& inst); - void V_CVT_F16_F32(const GcnInst& inst); - void V_CVT_F32_F16(const GcnInst& inst); - void V_CVT_RPI_I32_F32(const GcnInst& inst); - void V_CVT_FLR_I32_F32(const GcnInst& inst); - void V_CVT_OFF_F32_I4(const GcnInst& inst); - void V_CVT_F32_F64(const GcnInst& inst); - void V_CVT_F64_F32(const GcnInst& inst); - void V_CVT_F32_UBYTE(u32 index, const GcnInst& inst); - void V_TRUNC_F64(const GcnInst& inst); - void V_FLOOR_F64(const GcnInst& inst); - void V_FRACT_F32(const GcnInst& inst); - void V_TRUNC_F32(const GcnInst& inst); - void V_CEIL_F32(const GcnInst& inst); - void V_RNDNE_F32(const GcnInst& inst); - void V_FLOOR_F32(const GcnInst& inst); - void V_EXP_F32(const GcnInst& inst); - void V_LOG_F32(const GcnInst& inst); - void V_RCP_F32(const GcnInst& inst); - void V_RCP_LEGACY_F32(const GcnInst& inst); - void V_RCP_F64(const GcnInst& inst); - void V_RSQ_F32(const GcnInst& inst); - void V_SQRT_F32(const GcnInst& inst); - void V_SIN_F32(const GcnInst& inst); - void V_COS_F32(const GcnInst& inst); - void V_NOT_B32(const GcnInst& inst); - void V_BFREV_B32(const GcnInst& inst); - void V_FFBH_U32(const GcnInst& inst); - void V_FFBH_I32(const GcnInst& inst); - void V_FFBL_B32(const GcnInst& inst); - void V_FREXP_EXP_I32_F64(const GcnInst& inst); - void V_FREXP_MANT_F64(const GcnInst& inst); - void V_FRACT_F64(const GcnInst& inst); - void V_FREXP_EXP_I32_F32(const GcnInst& inst); - void V_FREXP_MANT_F32(const GcnInst& inst); - void V_MOVRELD_B32(const GcnInst& inst); - void V_MOVRELS_B32(const GcnInst& inst); - void V_MOVRELSD_B32(const GcnInst& inst); - - // VOPC - void V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst); - void V_CMP_F64(ConditionOp op, bool set_exec, const GcnInst& inst); - void V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); - void V_CMP_U64(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst); - void V_CMP_CLASS_F32(const GcnInst& inst); - - // VOP3a - void V_MAD_F32(const GcnInst& inst); - void V_MAD_I32_I24(const GcnInst& inst, bool is_signed = true); - void V_MAD_U32_U24(const GcnInst& inst); - void V_CUBEID_F32(const GcnInst& inst); - void V_CUBESC_F32(const GcnInst& inst); - void V_CUBETC_F32(const GcnInst& inst); - void V_CUBEMA_F32(const GcnInst& inst); - void V_BFE_U32(bool is_signed, const GcnInst& inst); - void V_BFI_B32(const GcnInst& inst); - void V_FMA_F32(const GcnInst& inst); - void V_FMA_F64(const GcnInst& inst); - void V_MIN3_F32(const GcnInst& inst); - void V_MIN3_U32(bool is_signed, const GcnInst& inst); - void V_MAX3_F32(const GcnInst& inst); - void V_MAX3_U32(bool is_signed, const GcnInst& inst); - void V_MED3_F32(const GcnInst& inst); - void V_MED3_U32(bool is_signed, const GcnInst& inst); - void V_SAD(const GcnInst& inst); - void V_SAD_U32(const GcnInst& inst); - void V_CVT_PK_U16_U32(const GcnInst& inst); - void V_CVT_PK_I16_I32(const GcnInst& inst); - void V_CVT_PK_U8_F32(const GcnInst& inst); - void V_LSHL_B64(const GcnInst& inst); - void V_LSHR_B64(const GcnInst& inst); - void V_ASHR_I64(const GcnInst& inst); - void V_ALIGNBIT_B32(const GcnInst& inst); - void V_ALIGNBYTE_B32(const GcnInst& inst); - void V_MUL_F64(const GcnInst& inst); - void V_MIN_F64(const GcnInst& inst); - void V_MAX_F64(const GcnInst& inst); - void V_MUL_LO_U32(const GcnInst& inst); - void V_MUL_HI_U32(bool is_signed, const GcnInst& inst); - void V_MAD_U64_U32(const GcnInst& inst); - void V_LSHRREV_B16(const GcnInst& inst); - void V_ASHRREV_I16(const GcnInst& inst); - void V_LSHLREV_B16(const GcnInst& inst); - void V_LSHL_ADD_U32(const GcnInst& inst); - void V_ADD_LSHL_U32(const GcnInst& inst); - void V_MIN3_F16(const GcnInst& inst); - void V_MAX3_F16(const GcnInst& inst); - void V_MED3_F16(const GcnInst& inst); - void V_ADD3_U32(const GcnInst& inst); - void V_LSHL_OR_B32(const GcnInst& inst); - void V_AND_OR_B32(const GcnInst& inst); - void V_OR3_B32(const GcnInst& inst); - - // VOP3P - void V_PK_MUL_LO_U16(const GcnInst& inst); - void V_PK_ADD_I16(const GcnInst& inst); - void V_PK_SUB_I16(const GcnInst& inst); - void V_PK_LSHLREV_B16(const GcnInst& inst); - void V_PK_LSHRREV_B16(const GcnInst& inst); - void V_PK_MAD_U16(const GcnInst& inst); - void V_PK_ADD_U16(const GcnInst& inst); - void V_PK_SUB_U16(const GcnInst& inst); - void V_PK_MAX_U16(const GcnInst& inst); - void V_PK_MIN_U16(const GcnInst& inst); - void V_PK_FMA_F16(const GcnInst& inst); - void V_PK_ADD_F16(const GcnInst& inst); - void V_PK_MUL_F16(const GcnInst& inst); - void V_PK_MIN_F16(const GcnInst& inst); - void V_PK_MAX_F16(const GcnInst& inst); - void V_MAD_MIX_F32(const GcnInst& inst); - void V_MAD_MIXLO_F16(const GcnInst& inst); - void V_MAD_MIXHI_F16(const GcnInst& inst); - - // Vector interpolation - // VINTRP - void V_INTERP_P1_F32(const GcnInst& inst); - void V_INTERP_P2_F32(const GcnInst& inst); - void V_INTERP_MOV_F32(const GcnInst& inst); - - // Data share - // DS - template - void DS_OP(const GcnInst& inst, AtomicOp op, bool rtn); - void DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); - void DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); - void DS_SWIZZLE_B32(const GcnInst& inst); - void DS_APPEND(const GcnInst& inst); - void DS_CONSUME(const GcnInst& inst); - void DS_CMPST(int bit_size, bool rtn, const GcnInst& inst); - - // Buffer Memory - // MUBUF / MTBUF - void BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, const GcnInst& inst, - u32 scalar_width = 32, bool is_signed = false); - void BUFFER_STORE(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, const GcnInst& inst, - u32 scalar_width = 32); - template - void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); - - // Image Memory - // MIMG - void IMAGE_LOAD(bool has_mip, const GcnInst& inst); - void IMAGE_STORE(bool has_mip, const GcnInst& inst); - void IMAGE_GET_RESINFO(const GcnInst& inst); - void IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst); - void IMAGE_SAMPLE(const GcnInst& inst); - void IMAGE_GATHER(const GcnInst& inst); - void IMAGE_GET_LOD(const GcnInst& inst); - -private: - template - [[nodiscard]] T GetSrc(const InstOperand& operand); - template - [[nodiscard]] T GetSrc16(const InstOperand& operand); - template - [[nodiscard]] T GetSrc64(const InstOperand& operand); - [[nodiscard]] IR::F32 GetSrcMix(const InstOperand& operand); - template - [[nodiscard]] pk_type GetSrcPk(const InstOperand& operand); - void SetDst(const InstOperand& operand, const IR::U32F32& value); - template - void SetDst16(const InstOperand& operand, const IR::U32F32& value); - void SetDst64(const InstOperand& operand, const IR::U64F64& value_raw); - template - void SetDstPk(const InstOperand& operand, const pk_type& value); - - // Vector ALU Helpers - IR::U32 GetCarryIn(const GcnInst& inst); - void SetCarryOut(const GcnInst& inst, const IR::U1& carry); - IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0); - void VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0); - - void ExportRenderTarget(const GcnInst& inst); - void ExportDepth(const GcnInst& inst); - void LogMissingOpcode(const GcnInst& inst); - - IR::VectorReg GetScratchVgpr(u32 offset); - -private: - IR::IREmitter ir; - Info& info; - const RuntimeInfo& runtime_info; - const Profile& profile; - u32 next_vgpr_num; - std::unordered_map vgpr_map; - std::array vgpr_to_interp{}; - FetchShaderData fetch_data{}; - bool opcode_missing = false; - u32 pc{}; -}; - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp deleted file mode 100644 index 2f57965..0000000 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ /dev/null @@ -1,1981 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "shader_recompiler/frontend/opcodes.h" -#include "shader_recompiler/frontend/translate/translate.h" -#include "shader_recompiler/ir/attribute.h" -#include "shader_recompiler/profile.h" - -namespace Shader::Gcn { - -void Translator::EmitVectorAlu(const GcnInst& inst) { - switch (inst.opcode) { - // VOP2 - case Opcode::V_CNDMASK_B32: - return V_CNDMASK_B32(inst); - case Opcode::V_READLANE_B32: - return V_READLANE_B32(inst); - case Opcode::V_WRITELANE_B32: - return V_WRITELANE_B32(inst); - case Opcode::V_ADD_F32: - return V_ADD_F32(inst); - case Opcode::V_SUB_F32: - return V_SUB_F32(inst); - case Opcode::V_SUBREV_F32: - return V_SUBREV_F32(inst); - case Opcode::V_MAC_LEGACY_F32: - return V_MAC_F32(inst); - case Opcode::V_MUL_LEGACY_F32: - return V_MUL_LEGACY_F32(inst); - case Opcode::V_MUL_F32: - return V_MUL_F32(inst); - case Opcode::V_MUL_I32_I24: - return V_MUL_I32_I24(inst, true); - case Opcode::V_MUL_U32_U24: - return V_MUL_I32_I24(inst, false); - case Opcode::V_MIN_LEGACY_F32: - return V_MIN_F32(inst, true); - case Opcode::V_MAX_LEGACY_F32: - return V_MAX_F32(inst, true); - case Opcode::V_MIN_F32: - return V_MIN_F32(inst, false); - case Opcode::V_MAX_F32: - return V_MAX_F32(inst); - case Opcode::V_MIN_I32: - return V_MIN_I32(inst); - case Opcode::V_MAX_I32: - return V_MAX_U32(true, inst); - case Opcode::V_MIN_U32: - return V_MIN_U32(inst); - case Opcode::V_MAX_U32: - return V_MAX_U32(false, inst); - case Opcode::V_LSHR_B32: - return V_LSHR_B32(inst); - case Opcode::V_LSHRREV_B32: - return V_LSHRREV_B32(inst); - case Opcode::V_ASHR_I32: - return V_ASHR_I32(inst); - case Opcode::V_ASHRREV_I32: - return V_ASHRREV_I32(inst); - case Opcode::V_LSHL_B32: - return V_LSHL_B32(inst); - case Opcode::V_LSHLREV_B32: - return V_LSHLREV_B32(inst); - case Opcode::V_AND_B32: - return V_AND_B32(inst); - case Opcode::V_OR_B32: - return V_OR_B32(false, inst); - case Opcode::V_XOR_B32: - return V_OR_B32(true, inst); - case Opcode::V_BFM_B32: - return V_BFM_B32(inst); - case Opcode::V_MAC_F32: - return V_MAC_F32(inst); - case Opcode::V_MADMK_F32: - return V_MADMK_F32(inst); - case Opcode::V_MADAK_F32: - return V_FMA_F32(inst); - case Opcode::V_BCNT_U32_B32: - return V_BCNT_U32_B32(inst); - case Opcode::V_MBCNT_LO_U32_B32: - return V_MBCNT_U32_B32(false, inst); - case Opcode::V_MBCNT_HI_U32_B32: - return V_MBCNT_U32_B32(true, inst); - case Opcode::V_ADD_I32: - return V_ADD_I32(inst); - case Opcode::V_SUB_I32: - return V_SUB_I32(inst); - case Opcode::V_SUBREV_I32: - return V_SUBREV_I32(inst); - case Opcode::V_ADDC_U32: - return V_ADDC_U32(inst); - case Opcode::V_SUBB_U32: - return V_SUBB_U32(inst); - case Opcode::V_SUBBREV_U32: - return V_SUBBREV_U32(inst); - case Opcode::V_LDEXP_F32: - return V_LDEXP_F32(inst); - case Opcode::V_CVT_PKNORM_U16_F32: - return V_CVT_PKNORM_U16_F32(inst); - case Opcode::V_CVT_PKNORM_I16_F32: - return V_CVT_PKNORM_I16_F32(inst); - case Opcode::V_CVT_PKRTZ_F16_F32: - return V_CVT_PKRTZ_F16_F32(inst); - case Opcode::V_ADD_F16: - return V_ADD_F16(inst); - case Opcode::V_SUB_F16: - return V_SUB_F16(inst); - case Opcode::V_MUL_F16: - return V_MUL_F16(inst); - case Opcode::V_MAX_F16: - return V_MAX_F16(inst); - case Opcode::V_MIN_F16: - return V_MIN_F16(inst); - - // VOP1 - case Opcode::V_MOV_B32: - return V_MOV(inst); - case Opcode::V_READFIRSTLANE_B32: - return V_READFIRSTLANE_B32(inst); - case Opcode::V_CVT_I32_F64: - return V_CVT_I32_F64(inst); - case Opcode::V_CVT_F64_I32: - return V_CVT_F64_I32(inst); - case Opcode::V_CVT_F64_U32: - return V_CVT_F64_U32(inst); - case Opcode::V_CVT_F32_I32: - return V_CVT_F32_I32(inst); - case Opcode::V_CVT_F32_U32: - return V_CVT_F32_U32(inst); - case Opcode::V_CVT_U32_F32: - return V_CVT_U32_F32(inst); - case Opcode::V_CVT_I32_F32: - return V_CVT_I32_F32(inst); - case Opcode::V_CVT_F16_F32: - return V_CVT_F16_F32(inst); - case Opcode::V_CVT_F32_F16: - return V_CVT_F32_F16(inst); - case Opcode::V_CVT_FLR_I32_F32: - return V_CVT_FLR_I32_F32(inst); - case Opcode::V_CVT_F32_F64: - return V_CVT_F32_F64(inst); - case Opcode::V_CVT_F64_F32: - return V_CVT_F64_F32(inst); - case Opcode::V_CVT_RPI_I32_F32: - return V_CVT_RPI_I32_F32(inst); - case Opcode::V_CVT_OFF_F32_I4: - return V_CVT_OFF_F32_I4(inst); - case Opcode::V_CVT_F32_UBYTE0: - return V_CVT_F32_UBYTE(0, inst); - case Opcode::V_CVT_F32_UBYTE1: - return V_CVT_F32_UBYTE(1, inst); - case Opcode::V_CVT_F32_UBYTE2: - return V_CVT_F32_UBYTE(2, inst); - case Opcode::V_CVT_F32_UBYTE3: - return V_CVT_F32_UBYTE(3, inst); - case Opcode::V_TRUNC_F64: - return V_TRUNC_F64(inst); - case Opcode::V_FLOOR_F64: - return V_FLOOR_F64(inst); - case Opcode::V_FRACT_F32: - return V_FRACT_F32(inst); - case Opcode::V_TRUNC_F32: - return V_TRUNC_F32(inst); - case Opcode::V_CEIL_F32: - return V_CEIL_F32(inst); - case Opcode::V_RNDNE_F32: - return V_RNDNE_F32(inst); - case Opcode::V_FLOOR_F32: - return V_FLOOR_F32(inst); - case Opcode::V_EXP_F32: - return V_EXP_F32(inst); - case Opcode::V_LOG_CLAMP_F32: - return V_LOG_F32(inst); - case Opcode::V_LOG_F32: - return V_LOG_F32(inst); - case Opcode::V_RCP_F32: - return V_RCP_F32(inst); - case Opcode::V_RCP_LEGACY_F32: - return V_RCP_LEGACY_F32(inst); - case Opcode::V_RCP_F64: - return V_RCP_F64(inst); - case Opcode::V_RCP_IFLAG_F32: - return V_RCP_F32(inst); - case Opcode::V_RCP_CLAMP_F32: - return V_RCP_F32(inst); - case Opcode::V_RSQ_CLAMP_F32: - return V_RSQ_F32(inst); - case Opcode::V_RSQ_LEGACY_F32: - return V_RSQ_F32(inst); - case Opcode::V_RSQ_F32: - return V_RSQ_F32(inst); - case Opcode::V_SQRT_F32: - return V_SQRT_F32(inst); - case Opcode::V_SIN_F32: - return V_SIN_F32(inst); - case Opcode::V_COS_F32: - return V_COS_F32(inst); - case Opcode::V_NOT_B32: - return V_NOT_B32(inst); - case Opcode::V_BFREV_B32: - return V_BFREV_B32(inst); - case Opcode::V_FFBH_U32: - return V_FFBH_U32(inst); - case Opcode::V_FFBL_B32: - return V_FFBL_B32(inst); - case Opcode::V_FFBH_I32: - return V_FFBH_I32(inst); - case Opcode::V_FREXP_EXP_I32_F64: - return V_FREXP_EXP_I32_F64(inst); - case Opcode::V_FREXP_MANT_F64: - return V_FREXP_MANT_F64(inst); - case Opcode::V_FRACT_F64: - return V_FRACT_F64(inst); - case Opcode::V_FREXP_EXP_I32_F32: - return V_FREXP_EXP_I32_F32(inst); - case Opcode::V_FREXP_MANT_F32: - return V_FREXP_MANT_F32(inst); - case Opcode::V_MOVRELD_B32: - return V_MOVRELD_B32(inst); - case Opcode::V_MOVRELS_B32: - return V_MOVRELS_B32(inst); - case Opcode::V_MOVRELSD_B32: - return V_MOVRELSD_B32(inst); - - // VOPC - // V_CMP_{OP16}_F32 - case Opcode::V_CMP_F_F32: - return V_CMP_F32(ConditionOp::F, false, inst); - case Opcode::V_CMP_LT_F32: - return V_CMP_F32(ConditionOp::LT, false, inst); - case Opcode::V_CMP_EQ_F32: - return V_CMP_F32(ConditionOp::EQ, false, inst); - case Opcode::V_CMP_LE_F32: - return V_CMP_F32(ConditionOp::LE, false, inst); - case Opcode::V_CMP_GT_F32: - return V_CMP_F32(ConditionOp::GT, false, inst); - case Opcode::V_CMP_LG_F32: - return V_CMP_F32(ConditionOp::LG, false, inst); - case Opcode::V_CMP_GE_F32: - return V_CMP_F32(ConditionOp::GE, false, inst); - case Opcode::V_CMP_U_F32: - return V_CMP_F32(ConditionOp::U, false, inst); - case Opcode::V_CMP_NGE_F32: - return V_CMP_F32(ConditionOp::LT, false, inst); - case Opcode::V_CMP_NGT_F32: - return V_CMP_F32(ConditionOp::LE, false, inst); - case Opcode::V_CMP_NLE_F32: - return V_CMP_F32(ConditionOp::GT, false, inst); - case Opcode::V_CMP_NEQ_F32: - return V_CMP_F32(ConditionOp::LG, false, inst); - case Opcode::V_CMP_NLT_F32: - return V_CMP_F32(ConditionOp::GE, false, inst); - - // V_CMPX_{OP16}_F32 - case Opcode::V_CMPX_F_F32: - return V_CMP_F32(ConditionOp::F, true, inst); - case Opcode::V_CMPX_LT_F32: - return V_CMP_F32(ConditionOp::LT, true, inst); - case Opcode::V_CMPX_EQ_F32: - return V_CMP_F32(ConditionOp::EQ, true, inst); - case Opcode::V_CMPX_LE_F32: - return V_CMP_F32(ConditionOp::LE, true, inst); - case Opcode::V_CMPX_GT_F32: - return V_CMP_F32(ConditionOp::GT, true, inst); - case Opcode::V_CMPX_LG_F32: - return V_CMP_F32(ConditionOp::LG, true, inst); - case Opcode::V_CMPX_GE_F32: - return V_CMP_F32(ConditionOp::GE, true, inst); - case Opcode::V_CMPX_NGE_F32: - return V_CMP_F32(ConditionOp::LT, true, inst); - case Opcode::V_CMPX_NLG_F32: - return V_CMP_F32(ConditionOp::EQ, true, inst); - case Opcode::V_CMPX_NGT_F32: - return V_CMP_F32(ConditionOp::LE, true, inst); - case Opcode::V_CMPX_NLE_F32: - return V_CMP_F32(ConditionOp::GT, true, inst); - case Opcode::V_CMPX_NEQ_F32: - return V_CMP_F32(ConditionOp::LG, true, inst); - case Opcode::V_CMPX_NLT_F32: - return V_CMP_F32(ConditionOp::GE, true, inst); - case Opcode::V_CMPX_TRU_F32: - return V_CMP_F32(ConditionOp::TRU, true, inst); - - // V_CMP_{OP16}_F64 - case Opcode::V_CMP_F_F64: - return V_CMP_F64(ConditionOp::F, false, inst); - case Opcode::V_CMP_LT_F64: - return V_CMP_F64(ConditionOp::LT, false, inst); - case Opcode::V_CMP_EQ_F64: - return V_CMP_F64(ConditionOp::EQ, false, inst); - case Opcode::V_CMP_LE_F64: - return V_CMP_F64(ConditionOp::LE, false, inst); - case Opcode::V_CMP_GT_F64: - return V_CMP_F64(ConditionOp::GT, false, inst); - case Opcode::V_CMP_LG_F64: - return V_CMP_F64(ConditionOp::LG, false, inst); - case Opcode::V_CMP_GE_F64: - return V_CMP_F64(ConditionOp::GE, false, inst); - case Opcode::V_CMP_U_F64: - return V_CMP_F64(ConditionOp::U, false, inst); - case Opcode::V_CMP_NGE_F64: - return V_CMP_F64(ConditionOp::LT, false, inst); - case Opcode::V_CMP_NGT_F64: - return V_CMP_F64(ConditionOp::LE, false, inst); - case Opcode::V_CMP_NLE_F64: - return V_CMP_F64(ConditionOp::GT, false, inst); - case Opcode::V_CMP_NEQ_F64: - return V_CMP_F64(ConditionOp::LG, false, inst); - case Opcode::V_CMP_NLT_F64: - return V_CMP_F64(ConditionOp::GE, false, inst); - - // V_CMP_{OP8}_I32 - case Opcode::V_CMP_LT_I32: - return V_CMP_U32(ConditionOp::LT, true, false, inst); - case Opcode::V_CMP_EQ_I32: - return V_CMP_U32(ConditionOp::EQ, true, false, inst); - case Opcode::V_CMP_LE_I32: - return V_CMP_U32(ConditionOp::LE, true, false, inst); - case Opcode::V_CMP_GT_I32: - return V_CMP_U32(ConditionOp::GT, true, false, inst); - case Opcode::V_CMP_NE_I32: - return V_CMP_U32(ConditionOp::LG, true, false, inst); - case Opcode::V_CMP_GE_I32: - return V_CMP_U32(ConditionOp::GE, true, false, inst); - case Opcode::V_CMPX_LE_I32: - return V_CMP_U32(ConditionOp::LE, true, true, inst); - - // V_CMPX_{OP8}_I32 - case Opcode::V_CMPX_LT_I32: - return V_CMP_U32(ConditionOp::LT, true, true, inst); - case Opcode::V_CMPX_EQ_I32: - return V_CMP_U32(ConditionOp::EQ, true, true, inst); - case Opcode::V_CMPX_GT_I32: - return V_CMP_U32(ConditionOp::GT, true, true, inst); - case Opcode::V_CMPX_LG_I32: - return V_CMP_U32(ConditionOp::LG, true, true, inst); - case Opcode::V_CMPX_GE_I32: - return V_CMP_U32(ConditionOp::GE, true, true, inst); - - // V_CMP_{OP8}_U32 - case Opcode::V_CMP_F_U32: - return V_CMP_U32(ConditionOp::F, false, false, inst); - case Opcode::V_CMP_LT_U32: - return V_CMP_U32(ConditionOp::LT, false, false, inst); - case Opcode::V_CMP_EQ_U32: - return V_CMP_U32(ConditionOp::EQ, false, false, inst); - case Opcode::V_CMP_LE_U32: - return V_CMP_U32(ConditionOp::LE, false, false, inst); - case Opcode::V_CMP_GT_U32: - return V_CMP_U32(ConditionOp::GT, false, false, inst); - case Opcode::V_CMP_NE_U32: - return V_CMP_U32(ConditionOp::LG, false, false, inst); - case Opcode::V_CMP_GE_U32: - return V_CMP_U32(ConditionOp::GE, false, false, inst); - case Opcode::V_CMP_TRU_U32: - return V_CMP_U32(ConditionOp::TRU, false, false, inst); - - // V_CMPX_{OP8}_U32 - case Opcode::V_CMPX_F_U32: - return V_CMP_U32(ConditionOp::F, false, true, inst); - case Opcode::V_CMPX_LT_U32: - return V_CMP_U32(ConditionOp::LT, false, true, inst); - case Opcode::V_CMPX_EQ_U32: - return V_CMP_U32(ConditionOp::EQ, false, true, inst); - case Opcode::V_CMPX_LE_U32: - return V_CMP_U32(ConditionOp::LE, false, true, inst); - case Opcode::V_CMPX_GT_U32: - return V_CMP_U32(ConditionOp::GT, false, true, inst); - case Opcode::V_CMPX_NE_U32: - return V_CMP_U32(ConditionOp::LG, false, true, inst); - case Opcode::V_CMPX_GE_U32: - return V_CMP_U32(ConditionOp::GE, false, true, inst); - case Opcode::V_CMPX_TRU_U32: - return V_CMP_U32(ConditionOp::TRU, false, true, inst); - - // V_CMP_{OP8}_I64 - case Opcode::V_CMP_F_I64: - return V_CMP_U64(ConditionOp::F, true, false, inst); - case Opcode::V_CMP_LT_I64: - return V_CMP_U64(ConditionOp::LT, true, false, inst); - case Opcode::V_CMP_EQ_I64: - return V_CMP_U64(ConditionOp::EQ, true, false, inst); - case Opcode::V_CMP_LE_I64: - return V_CMP_U64(ConditionOp::LE, true, false, inst); - case Opcode::V_CMP_GT_I64: - return V_CMP_U64(ConditionOp::GT, true, false, inst); - case Opcode::V_CMP_NE_I64: - return V_CMP_U64(ConditionOp::LG, true, false, inst); - case Opcode::V_CMP_GE_I64: - return V_CMP_U64(ConditionOp::GE, true, false, inst); - case Opcode::V_CMP_TRU_I64: - return V_CMP_U64(ConditionOp::TRU, true, false, inst); - - // V_CMPX_{OP8}_I64 - case Opcode::V_CMPX_EQ_I64: - return V_CMP_U64(ConditionOp::EQ, true, true, inst); - - // V_CMP_{OP8}_U64 - case Opcode::V_CMP_EQ_U64: - return V_CMP_U64(ConditionOp::EQ, false, false, inst); - case Opcode::V_CMP_NE_U64: - return V_CMP_U64(ConditionOp::LG, false, false, inst); - case Opcode::V_CMP_GT_U64: - return V_CMP_U64(ConditionOp::GT, false, false, inst); - case Opcode::V_CMP_LT_U64: - return V_CMP_U64(ConditionOp::LT, false, false, inst); - - // V_CMPX_{OP8}_U64 - case Opcode::V_CMPX_EQ_U64: - return V_CMP_U64(ConditionOp::EQ, false, true, inst); - case Opcode::V_CMPX_LG_U64: - return V_CMP_U64(ConditionOp::LG, false, true, inst); - - case Opcode::V_CMP_CLASS_F32: - return V_CMP_CLASS_F32(inst); - - // VOP3a - case Opcode::V_MAD_LEGACY_F32: - return V_MAD_F32(inst); - case Opcode::V_MAD_F32: - return V_MAD_F32(inst); - case Opcode::V_MAD_I32_I24: - return V_MAD_I32_I24(inst); - case Opcode::V_MAD_U32_U24: - return V_MAD_U32_U24(inst); - case Opcode::V_CUBEID_F32: - return V_CUBEID_F32(inst); - case Opcode::V_CUBESC_F32: - return V_CUBESC_F32(inst); - case Opcode::V_CUBETC_F32: - return V_CUBETC_F32(inst); - case Opcode::V_CUBEMA_F32: - return V_CUBEMA_F32(inst); - case Opcode::V_BFE_U32: - return V_BFE_U32(false, inst); - case Opcode::V_BFE_I32: - return V_BFE_U32(true, inst); - case Opcode::V_BFI_B32: - return V_BFI_B32(inst); - case Opcode::V_FMA_F32: - return V_FMA_F32(inst); - case Opcode::V_FMA_F64: - return V_FMA_F64(inst); - case Opcode::V_MIN3_F32: - return V_MIN3_F32(inst); - case Opcode::V_MIN3_I32: - return V_MIN3_U32(true, inst); - case Opcode::V_MIN3_U32: - return V_MIN3_U32(false, inst); - case Opcode::V_MAX3_F32: - return V_MAX3_F32(inst); - case Opcode::V_MAX3_I32: - return V_MAX3_U32(true, inst); - case Opcode::V_MAX3_U32: - return V_MAX3_U32(false, inst); - case Opcode::V_MED3_F32: - return V_MED3_F32(inst); - case Opcode::V_MED3_I32: - return V_MED3_U32(true, inst); - case Opcode::V_MED3_U32: - return V_MED3_U32(false, inst); - case Opcode::V_SAD_U32: - return V_SAD_U32(inst); - case Opcode::V_CVT_PK_U16_U32: - return V_CVT_PK_U16_U32(inst); - case Opcode::V_CVT_PK_I16_I32: - return V_CVT_PK_I16_I32(inst); - case Opcode::V_CVT_PK_U8_F32: - return V_CVT_PK_U8_F32(inst); - case Opcode::V_LSHL_B64: - return V_LSHL_B64(inst); - case Opcode::V_LSHR_B64: - return V_LSHR_B64(inst); - case Opcode::V_ASHR_I64: - return V_ASHR_I64(inst); - case Opcode::V_ADD_F64: - return V_ADD_F64(inst); - case Opcode::V_ALIGNBIT_B32: - return V_ALIGNBIT_B32(inst); - case Opcode::V_ALIGNBYTE_B32: - return V_ALIGNBYTE_B32(inst); - case Opcode::V_MUL_F64: - return V_MUL_F64(inst); - case Opcode::V_MIN_F64: - return V_MIN_F64(inst); - case Opcode::V_MAX_F64: - return V_MAX_F64(inst); - case Opcode::V_MUL_LO_U32: - return V_MUL_LO_U32(inst); - case Opcode::V_MUL_HI_U32: - return V_MUL_HI_U32(false, inst); - case Opcode::V_MUL_LO_I32: - return V_MUL_LO_U32(inst); - case Opcode::V_MUL_HI_I32: - return V_MUL_HI_U32(true, inst); - case Opcode::V_MAD_U64_U32: - return V_MAD_U64_U32(inst); - case Opcode::V_LSHRREV_B16: - return V_LSHRREV_B16(inst); - case Opcode::V_ASHRREV_I16: - return V_ASHRREV_I16(inst); - case Opcode::V_LSHLREV_B16: - return V_LSHLREV_B16(inst); - case Opcode::V_ADD_LSHL_U32: - return V_ADD_LSHL_U32(inst); - case Opcode::V_LSHL_ADD_U32: - return V_LSHL_ADD_U32(inst); - case Opcode::V_MIN3_F16: - return V_MIN3_F16(inst); - case Opcode::V_MAX3_F16: - return V_MAX3_F16(inst); - case Opcode::V_MED3_F16: - return V_MED3_F16(inst); - case Opcode::V_ADD3_U32: - return V_ADD3_U32(inst); - case Opcode::V_LSHL_OR_B32: - return V_LSHL_OR_B32(inst); - case Opcode::V_AND_OR_B32: - return V_AND_OR_B32(inst); - case Opcode::V_OR3_B32: - return V_OR3_B32(inst); - case Opcode::V_NOP: - return; - - // VOP3P - case Opcode::V_PK_MUL_LO_U16: - return V_PK_MUL_LO_U16(inst); - case Opcode::V_PK_ADD_I16: - return V_PK_ADD_I16(inst); - case Opcode::V_PK_SUB_I16: - return V_PK_SUB_I16(inst); - case Opcode::V_PK_LSHRREV_B16: - return V_PK_LSHRREV_B16(inst); - case Opcode::V_PK_LSHLREV_B16: - return V_PK_LSHLREV_B16(inst); - case Opcode::V_PK_MAD_U16: - return V_PK_MAD_U16(inst); - case Opcode::V_PK_ADD_U16: - return V_PK_ADD_U16(inst); - case Opcode::V_PK_SUB_U16: - return V_PK_SUB_U16(inst); - case Opcode::V_PK_MAX_U16: - return V_PK_MAX_U16(inst); - case Opcode::V_PK_MIN_U16: - return V_PK_MIN_U16(inst); - case Opcode::V_PK_FMA_F16: - return V_PK_FMA_F16(inst); - case Opcode::V_PK_ADD_F16: - return V_PK_ADD_F16(inst); - case Opcode::V_PK_MUL_F16: - return V_PK_MUL_F16(inst); - case Opcode::V_PK_MIN_F16: - return V_PK_MIN_F16(inst); - case Opcode::V_PK_MAX_F16: - return V_PK_MAX_F16(inst); - case Opcode::V_MAD_MIX_F32: - return V_MAD_MIX_F32(inst); - case Opcode::V_MAD_MIXLO_F16: - return V_MAD_MIXLO_F16(inst); - case Opcode::V_MAD_MIXHI_F16: - return V_MAD_MIXHI_F16(inst); - - default: - LogMissingOpcode(inst); - } -} - -// VOP2 - -void Translator::V_CNDMASK_B32(const GcnInst& inst) { - IR::U64 mask; - if (inst.src[2].field == OperandField::Undefined) { - mask = ir.PackUint2x32(ir.CompositeConstruct(ir.GetVccLo(), ir.GetVccHi())); - } else { - mask = GetSrc64(inst.src[2]); - } - const IR::Value result = ir.Select(ir.InverseBallot(mask), GetSrc(inst.src[1]), - GetSrc(inst.src[0])); - SetDst(inst.dst[0], IR::U32F32{result}); -} - -void Translator::V_ADD_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPAdd(src0, src1)); -} - -void Translator::V_ADD_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.FPAdd(src0, src1)); -} - -void Translator::V_SUB_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPSub(src0, src1)); -} - -void Translator::V_SUBREV_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPSub(src1, src0)); -} - -void Translator::V_MUL_F32(const GcnInst& inst) { - SetDst(inst.dst[0], ir.FPMul(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); -} - -void Translator::V_MUL_LEGACY_F32(const GcnInst& inst) { - // GCN V_MUL_LEGACY_F32: if either source is zero, the result is +0.0 - // regardless of the other operand (even if NaN or Inf). - // Standard IEEE multiply would produce NaN for 0 * Inf. - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 zero{ir.Imm32(0.0f)}; - const IR::U1 src0_zero{ir.FPEqual(src0, zero)}; - const IR::U1 src1_zero{ir.FPEqual(src1, zero)}; - const IR::U1 either_zero{ir.LogicalOr(src0_zero, src1_zero)}; - SetDst(inst.dst[0], IR::F32{ir.Select(either_zero, zero, ir.FPMul(src0, src1))}); -} - -void Translator::V_MUL_I32_I24(const GcnInst& inst, bool is_signed) { - const IR::U32 src0{ - ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - const IR::U32 src1{ - ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - SetDst(inst.dst[0], ir.IMul(src0, src1)); -} - -void Translator::V_MIN_F32(const GcnInst& inst, bool is_legacy) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - - const IR::F32 fpmin = ir.FPMin(src0, src1); - const IR::F32 result = - is_legacy - ? IR::F32{ir.Select(ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)), src1, fpmin)} - : fpmin; - SetDst(inst.dst[0], result); -} - -void Translator::V_MAX_F32(const GcnInst& inst, bool is_legacy) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - - const IR::F32 fpmax = ir.FPMax(src0, src1); - const IR::F32 result = - is_legacy - ? IR::F32{ir.Select(ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)), src1, fpmax)} - : fpmax; - SetDst(inst.dst[0], result); -} - -void Translator::V_MIN_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.SMin(src0, src1)); -} - -void Translator::V_MIN_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMin(src0, src1, false)); -} - -void Translator::V_MAX_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMax(src0, src1, is_signed)); -} - -void Translator::V_LSHR_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_LSHRREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_ASHR_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_ASHRREV_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftRightArithmetic(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_LSHL_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))); -} - -void Translator::V_LSHLREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.ShiftLeftLogical(src1, ir.BitwiseAnd(src0, ir.Imm32(0x1F)))); -} - -void Translator::V_AND_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.BitwiseAnd(src0, src1)); -} - -void Translator::V_OR_B32(bool is_xor, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], - is_xor ? IR::U32{ir.BitwiseXor(src0, src1)} : IR::U32{ir.BitwiseOr(src0, src1)}); -} - -void Translator::V_BFM_B32(const GcnInst& inst) { - // bitmask width, S0[4:0] - const IR::U32 src0{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(5))}; - // bitmask offset, S1[4:0] - const IR::U32 src1{ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(5))}; - const IR::U32 ones = ir.ISub(ir.ShiftLeftLogical(ir.Imm32(1), src0), ir.Imm32(1)); - SetDst(inst.dst[0], ir.ShiftLeftLogical(ones, src1)); -} - -void Translator::V_MAC_F32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto dst0 = GetSrc(inst.dst[0]); - SetDst(inst.dst[0], ir.FPAdd(ir.FPMul(src0, src1), dst0)); -} - -void Translator::V_MADMK_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 k{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPAdd(ir.FPMul(src0, k), src1)); -} - -void Translator::V_BCNT_U32_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IAdd(ir.BitCount(src0), src1)); -} - -void Translator::V_MBCNT_U32_B32(bool hi, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.MaskedBitCount(src0, src1, hi)); -} - -void Translator::V_ADD_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.IAdd(src0, src1)}; - SetDst(inst.dst[0], result); - - SetCarryOut(inst, ir.ILessThan(result, src0, false)); -} - -void Translator::V_SUB_I32(const GcnInst& inst) { - // Unsigned components - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ISub(src0, src1)}; - SetDst(inst.dst[0], result); - - const IR::U1 did_underflow{ir.IGreaterThan(src1, src0, false)}; - SetCarryOut(inst, did_underflow); -} - -void Translator::V_SUBREV_I32(const GcnInst& inst) { - // Unsigned components - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 result{ir.ISub(src1, src0)}; - SetDst(inst.dst[0], result); - - const IR::U1 did_underflow{ir.IGreaterThan(src0, src1, false)}; - SetCarryOut(inst, did_underflow); -} - -void Translator::V_ADDC_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 carry{GetCarryIn(inst)}; - const IR::U32 result1{ir.IAdd(src0, src1)}; - const IR::U32 result2{ir.IAdd(result1, carry)}; - const IR::U1 carry_out1{ir.ILessThan(result1, src0, false)}; - const IR::U1 carry_out2{ir.ILessThan(result2, result1, false)}; - SetDst(inst.dst[0], result2); - - const IR::U1 did_overflow{ir.LogicalOr(carry_out1, carry_out2)}; - SetCarryOut(inst, did_overflow); -} - -void Translator::V_SUBB_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 carry{GetCarryIn(inst)}; - const IR::U32 result{ir.ISub(ir.ISub(src0, src1), carry)}; - SetDst(inst.dst[0], result); - - const IR::U1 underflow{ir.IGreaterThan(src1, src0, false)}; - const IR::U32 difference{ir.ISub(src0, src1)}; - const IR::U1 borrow_underflow{ir.IGreaterThan(carry, difference, false)}; - SetCarryOut(inst, ir.LogicalOr(underflow, borrow_underflow)); -} - -void Translator::V_SUBBREV_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 carry{GetCarryIn(inst)}; - const IR::U32 result{ir.ISub(ir.ISub(src1, src0), carry)}; - SetDst(inst.dst[0], result); - - const IR::U1 underflow{ir.IGreaterThan(src0, src1, false)}; - const IR::U32 difference{ir.ISub(src1, src0)}; - const IR::U1 borrow_underflow{ir.IGreaterThan(carry, difference, false)}; - SetCarryOut(inst, ir.LogicalOr(underflow, borrow_underflow)); -} - -void Translator::V_LDEXP_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.FPLdexp(src0, src1)); -} - -void Translator::V_CVT_PKNORM_U16_F32(const GcnInst& inst) { - const IR::Value vec_f32 = - ir.CompositeConstruct(GetSrc(inst.src[0]), GetSrc(inst.src[1])); - SetDst(inst.dst[0], ir.Pack2x16(AmdGpu::NumberFormat::Unorm, vec_f32)); -} - -void Translator::V_CVT_PKNORM_I16_F32(const GcnInst& inst) { - const IR::Value vec_f32 = - ir.CompositeConstruct(GetSrc(inst.src[0]), GetSrc(inst.src[1])); - SetDst(inst.dst[0], ir.Pack2x16(AmdGpu::NumberFormat::Snorm, vec_f32)); -} - -void Translator::V_CVT_PKRTZ_F16_F32(const GcnInst& inst) { - const IR::Value vec_f32 = - ir.CompositeConstruct(GetSrc(inst.src[0]), GetSrc(inst.src[1])); - SetDst(inst.dst[0], ir.Pack2x16(AmdGpu::NumberFormat::Float, vec_f32)); -} - -void Translator::V_ADD_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - - const auto result = ir.FPAdd(src0, src1); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_SUB_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - - const auto result = ir.FPSub(src0, src1); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_MUL_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - - const auto result = ir.FPMul(src0, src1); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_MAX_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - - const auto result = ir.FPMax(src0, src1); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_MIN_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - - const auto result = ir.FPMin(src0, src1); - - SetDst16(inst.dst[0], result); -} - -// VOP1 - -void Translator::V_MOV(const GcnInst& inst) { - SetDst(inst.dst[0], GetSrc(inst.src[0])); -} - -void Translator::V_CVT_I32_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToS(32, src0)); -} - -void Translator::V_CVT_F64_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst64(inst.dst[0], ir.ConvertSToF(64, 32, src0)); -} - -void Translator::V_CVT_F64_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst64(inst.dst[0], ir.ConvertUToF(64, 32, src0)); -} - -void Translator::V_CVT_F32_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertSToF(32, 32, src0)); -} - -void Translator::V_CVT_F32_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertUToF(32, 32, src0)); -} - -void Translator::V_CVT_U32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToU(32, src0)); -} - -void Translator::V_CVT_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToS(32, src0)); -} - -void Translator::V_CVT_F16_F32(const GcnInst& inst) { - const IR::F32 src0 = GetSrc(inst.src[0]); - - IR::U32 src0fp16; - if (profile.support_float16) { - const IR::F16 converted = ir.FPConvert(16, src0); - src0fp16 = ir.UConvert(32, ir.BitCast(converted)); - } else { - const IR::U32 packed = - ir.Pack2x16(AmdGpu::NumberFormat::Float, ir.CompositeConstruct(src0, ir.Imm32(0.f))); - src0fp16 = ir.BitFieldExtract(packed, ir.Imm32(0U), ir.Imm32(16U)); - } - - SetDst(inst.dst[0], src0fp16); -} - -void Translator::V_CVT_F32_F16(const GcnInst& inst) { - const IR::U32 src0 = GetSrc(inst.src[0]); - - IR::F32 src0l; - if (profile.support_float16) { - const IR::U16 converted = ir.UConvert(16, src0); - src0l = ir.FPConvert(32, ir.BitCast(converted)); - } else { - const IR::Value unpacked = ir.Unpack2x16(AmdGpu::NumberFormat::Float, src0); - src0l = IR::F32{ir.CompositeExtract(unpacked, 0)}; - } - - SetDst(inst.dst[0], src0l); -} - -void Translator::V_CVT_RPI_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToI(32, true, ir.FPFloor(ir.FPAdd(src0, ir.Imm32(0.5f))))); -} - -void Translator::V_CVT_FLR_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.ConvertFToI(32, true, ir.FPFloor(src0))); -} - -void Translator::V_CVT_OFF_F32_I4(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - ASSERT(src0.IsImmediate()); - static constexpr std::array IntToFloat = { - 0.0f, 0.0625f, 0.1250f, 0.1875f, 0.2500f, 0.3125f, 0.3750f, 0.4375f, - -0.5000f, -0.4375f, -0.3750f, -0.3125f, -0.2500f, -0.1875f, -0.1250f, -0.0625f}; - SetDst(inst.dst[0], ir.Imm32(IntToFloat[src0.U32() & 0xF])); -} - -void Translator::V_CVT_F32_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst(inst.dst[0], ir.FPConvert(32, src0)); -} - -void Translator::V_CVT_F64_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPConvert(64, src0)); -} - -void Translator::V_CVT_F32_UBYTE(u32 index, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 byte = ir.BitFieldExtract(src0, ir.Imm32(8 * index), ir.Imm32(8)); - SetDst(inst.dst[0], ir.ConvertUToF(32, 32, byte)); -} - -void Translator::V_TRUNC_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPTrunc(src0)); -} - -void Translator::V_FLOOR_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPFloor(src0)); -} - -void Translator::V_FRACT_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPFract(src0)); -} - -void Translator::V_TRUNC_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPTrunc(src0)); -} - -void Translator::V_CEIL_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPCeil(src0)); -} - -void Translator::V_RNDNE_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPRoundEven(src0)); -} - -void Translator::V_FLOOR_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPFloor(src0)); -} - -void Translator::V_EXP_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPExp2(src0)); -} - -void Translator::V_LOG_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPLog2(src0)); -} - -void Translator::V_RCP_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPRecip(src0)); -} - -void Translator::V_RCP_LEGACY_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const auto result = ir.FPRecip(src0); - const auto inf = ir.FPIsInf(result); - - const auto raw_result = ir.ConvertFToU(32, result); - const auto sign_bit = ir.ShiftRightLogical(raw_result, ir.Imm32(31u)); - const auto sign_bit_set = ir.INotEqual(sign_bit, ir.Imm32(0u)); - const IR::F32 inf_result{ir.Select(sign_bit_set, ir.Imm32(-0.0f), ir.Imm32(0.0f))}; - const IR::F32 val{ir.Select(inf, inf_result, result)}; - - SetDst(inst.dst[0], val); -} - -void Translator::V_RCP_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPRecip(src0)); -} - -void Translator::V_RSQ_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPRecipSqrt(src0)); -} - -void Translator::V_SQRT_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPSqrt(src0)); -} - -void Translator::V_SIN_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPSin(src0)); -} - -void Translator::V_COS_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPCos(src0)); -} - -void Translator::V_NOT_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.BitwiseNot(src0)); -} - -void Translator::V_BFREV_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.BitReverse(src0)); -} - -void Translator::V_FFBH_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) - // position - const IR::U32 msb_pos = ir.FindUMsb(src0); - const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); - // Select 0xFFFFFFFF if src0 was 0 - const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); - SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); -} - -void Translator::V_FFBL_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FindILsb(src0)); -} - -void Translator::V_FFBH_I32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) - // position - const IR::U32 msb_pos = ir.FindSMsb(src0); - const IR::U32 pos_from_left = ir.ISub(ir.Imm32(31), msb_pos); - // Select 0xFFFFFFFF if src0 was 0 or -1 - const IR::U32 minusOne = ir.Imm32(~0U); - const IR::U1 cond = - ir.LogicalAnd(ir.INotEqual(src0, ir.Imm32(0)), ir.INotEqual(src0, minusOne)); - SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, minusOne)}); -} - -void Translator::V_FREXP_EXP_I32_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst(inst.dst[0], ir.FPFrexpExp(src0)); -} - -void Translator::V_FREXP_MANT_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPFrexpSig(src0)); -} - -void Translator::V_FRACT_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - SetDst64(inst.dst[0], ir.FPFract(src0)); -} - -void Translator::V_FREXP_EXP_I32_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPFrexpExp(src0)); -} - -void Translator::V_FREXP_MANT_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - SetDst(inst.dst[0], ir.FPFrexpSig(src0)); -} - -void Translator::V_MOVRELD_B32(const GcnInst& inst) { - const IR::U32 src_val{GetSrc(inst.src[0])}; - u32 dst_vgprno = inst.dst[0].code - static_cast(IR::VectorReg::V0); - IR::U32 m0 = ir.GetM0(); - - VMovRelDHelper(dst_vgprno, src_val, m0); -} - -void Translator::V_MOVRELS_B32(const GcnInst& inst) { - u32 src_vgprno = inst.src[0].code - static_cast(IR::VectorReg::V0); - const IR::U32 m0 = ir.GetM0(); - - const IR::U32 src_val = VMovRelSHelper(src_vgprno, m0); - SetDst(inst.dst[0], src_val); -} - -void Translator::V_MOVRELSD_B32(const GcnInst& inst) { - u32 src_vgprno = inst.src[0].code - static_cast(IR::VectorReg::V0); - u32 dst_vgprno = inst.dst[0].code - static_cast(IR::VectorReg::V0); - IR::U32 m0 = ir.GetM0(); - - const IR::U32 src_val = VMovRelSHelper(src_vgprno, m0); - VMovRelDHelper(dst_vgprno, src_val, m0); -} - -// VOPC - -void Translator::V_CMP_F32(ConditionOp op, bool set_exec, const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::U1 result = [&] { - switch (op) { - case ConditionOp::F: - return ir.Imm1(false); - case ConditionOp::EQ: - return ir.FPEqual(src0, src1); - case ConditionOp::LG: - return ir.FPNotEqual(src0, src1); - case ConditionOp::GT: - return ir.FPGreaterThan(src0, src1); - case ConditionOp::LT: - return ir.FPLessThan(src0, src1); - case ConditionOp::LE: - return ir.FPLessThanEqual(src0, src1); - case ConditionOp::GE: - return ir.FPGreaterThanEqual(src0, src1); - case ConditionOp::U: - return ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)); - default: - UNREACHABLE(); - } - }(); - if (set_exec) { - // V_CMPX evaluates on active lanes only; hardware writes exec & result to both EXEC - // and the VCC/SDST destination, zeroing inactive lanes' bits. - const IR::U1 masked{ir.LogicalAnd(ir.GetExec(), result)}; - ir.SetExec(masked); - SetDst64(inst.dst[1], ir.Ballot(masked)); - return; - } - // Inactive lanes' bits are zero in the destination. - SetDst64(inst.dst[1], ir.Ballot(ir.LogicalAnd(ir.GetExec(), result))); -} - -void Translator::V_CMP_F64(ConditionOp op, bool set_exec, const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - const IR::U1 result = [&] { - switch (op) { - case ConditionOp::F: - return ir.Imm1(false); - case ConditionOp::EQ: - return ir.FPEqual(src0, src1); - case ConditionOp::LG: - return ir.FPNotEqual(src0, src1); - case ConditionOp::GT: - return ir.FPGreaterThan(src0, src1); - case ConditionOp::LT: - return ir.FPLessThan(src0, src1); - case ConditionOp::LE: - return ir.FPLessThanEqual(src0, src1); - case ConditionOp::GE: - return ir.FPGreaterThanEqual(src0, src1); - case ConditionOp::U: - return ir.LogicalOr(ir.FPIsNan(src0), ir.FPIsNan(src1)); - default: - UNREACHABLE(); - } - }(); - if (set_exec) { - // See the V_CMPX note in V_CMP_F32. - const IR::U1 masked{ir.LogicalAnd(ir.GetExec(), result)}; - ir.SetExec(masked); - SetDst64(inst.dst[1], ir.Ballot(masked)); - return; - } - // Inactive lanes' bits are zero in the destination. - SetDst64(inst.dst[1], ir.Ballot(ir.LogicalAnd(ir.GetExec(), result))); -} - -void Translator::V_CMP_U32(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U1 result = [&] { - switch (op) { - case ConditionOp::F: - return ir.Imm1(false); - case ConditionOp::TRU: - return ir.Imm1(true); - case ConditionOp::EQ: - return ir.IEqual(src0, src1); - case ConditionOp::LG: - return ir.INotEqual(src0, src1); - case ConditionOp::GT: - return ir.IGreaterThan(src0, src1, is_signed); - case ConditionOp::LT: - return ir.ILessThan(src0, src1, is_signed); - case ConditionOp::LE: - return ir.ILessThanEqual(src0, src1, is_signed); - case ConditionOp::GE: - return ir.IGreaterThanEqual(src0, src1, is_signed); - default: - UNREACHABLE(); - } - }(); - if (set_exec) { - // See the V_CMPX note in V_CMP_F32. - const IR::U1 masked{ir.LogicalAnd(ir.GetExec(), result)}; - ir.SetExec(masked); - SetDst64(inst.dst[1], ir.Ballot(masked)); - return; - } - // Inactive lanes' bits are zero in the destination. - SetDst64(inst.dst[1], ir.Ballot(ir.LogicalAnd(ir.GetExec(), result))); -} - -void Translator::V_CMP_U64(ConditionOp op, bool is_signed, bool set_exec, const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - const IR::U1 result = [&] { - switch (op) { - case ConditionOp::F: - return ir.Imm1(false); - case ConditionOp::TRU: - return ir.Imm1(true); - case ConditionOp::EQ: - return ir.IEqual(src0, src1); - case ConditionOp::LG: - return ir.INotEqual(src0, src1); - case ConditionOp::GT: - return ir.IGreaterThan(src0, src1, is_signed); - case ConditionOp::LT: - return ir.ILessThan(src0, src1, is_signed); - case ConditionOp::LE: - return ir.ILessThanEqual(src0, src1, is_signed); - case ConditionOp::GE: - return ir.IGreaterThanEqual(src0, src1, is_signed); - default: - UNREACHABLE(); - } - }(); - if (set_exec) { - // See the V_CMPX note in V_CMP_F32. - const IR::U1 masked{ir.LogicalAnd(ir.GetExec(), result)}; - ir.SetExec(masked); - SetDst64(inst.dst[1], ir.Ballot(masked)); - return; - } - // Inactive lanes' bits are zero in the destination. - SetDst64(inst.dst[1], ir.Ballot(ir.LogicalAnd(ir.GetExec(), result))); -} - -void Translator::V_CMP_CLASS_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - IR::U1 value; - if (src1.IsImmediate()) { - const auto class_mask = static_cast(src1.U32()); - if ((class_mask & IR::FloatClassFunc::NaN) == IR::FloatClassFunc::NaN) { - value = ir.FPIsNan(src0); - } else if ((class_mask & IR::FloatClassFunc::Infinity) == IR::FloatClassFunc::Infinity) { - value = ir.FPIsInf(src0); - } else if ((class_mask & IR::FloatClassFunc::Negative) == IR::FloatClassFunc::Negative) { - value = ir.FPLessThanEqual(src0, ir.Imm32(-0.f)); - } else { - UNREACHABLE_MSG("Unsupported float class mask: {:#x}", static_cast(class_mask)); - } - } else { - // We don't know the type yet, delay its resolution. - value = ir.FPCmpClass32(src0, src1); - } - // Inactive lanes' bits are zero in the destination. - SetDst64(inst.dst[1], ir.Ballot(ir.LogicalAnd(ir.GetExec(), value))); -} - -// VOP3a - -void Translator::V_MAD_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPAdd(ir.FPMul(src0, src1), src2)); -} - -void Translator::V_MAD_I32_I24(const GcnInst& inst, bool is_signed) { - const IR::U32 src0{ - ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - const IR::U32 src1{ - ir.BitFieldExtract(GetSrc(inst.src[1]), ir.Imm32(0), ir.Imm32(24), is_signed)}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.IAdd(ir.IMul(src0, src1), src2)); -} - -void Translator::V_MAD_U32_U24(const GcnInst& inst) { - V_MAD_I32_I24(inst, false); -} - -void Translator::V_CUBEID_F32(const GcnInst& inst) { - const auto x = GetSrc(inst.src[0]); - const auto y = GetSrc(inst.src[1]); - const auto z = GetSrc(inst.src[2]); - - SetDst(inst.dst[0], ir.CubeFaceIndex(x, y, z)); -} - -void Translator::V_CUBESC_F32(const GcnInst& inst) { - const auto x = GetSrc(inst.src[0]); - const auto y = GetSrc(inst.src[1]); - const auto z = GetSrc(inst.src[2]); - - SetDst(inst.dst[0], ir.CubeFaceCoordS(x, y, z)); -} - -void Translator::V_CUBETC_F32(const GcnInst& inst) { - const auto x = GetSrc(inst.src[0]); - const auto y = GetSrc(inst.src[1]); - const auto z = GetSrc(inst.src[2]); - - SetDst(inst.dst[0], ir.CubeFaceCoordT(x, y, z)); -} - -void Translator::V_CUBEMA_F32(const GcnInst& inst) { - const auto x = GetSrc(inst.src[0]); - const auto y = GetSrc(inst.src[1]); - const auto z = GetSrc(inst.src[2]); - - SetDst(inst.dst[0], ir.CubeFaceMajorAxis(x, y, z)); -} - -void Translator::V_BFE_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - IR::U32 src1{GetSrc(inst.src[1])}; - IR::U32 src2{GetSrc(inst.src[2])}; - if (!src1.IsImmediate()) { - src1 = ir.BitwiseAnd(src1, ir.Imm32(0x1F)); - } - if (!src2.IsImmediate()) { - src2 = ir.BitwiseAnd(src2, ir.Imm32(0x1F)); - } - SetDst(inst.dst[0], ir.BitFieldExtract(src0, src1, src2, is_signed)); -} - -void Translator::V_BFI_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], - ir.BitwiseOr(ir.BitwiseAnd(src0, src1), ir.BitwiseAnd(ir.BitwiseNot(src0), src2))); -} - -void Translator::V_FMA_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPFma(src0, src1, src2)); -} - -void Translator::V_FMA_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - const IR::F64 src2{GetSrc64(inst.src[2])}; - SetDst64(inst.dst[0], ir.FPFma(src0, src1, src2)); -} - -void Translator::V_MIN3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPMinTri(src0, src1, src2)); -} - -void Translator::V_MIN3_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.IMinTri(src0, src1, src2, is_signed)); -} - -void Translator::V_MAX3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPMaxTri(src0, src1, src2)); -} - -void Translator::V_MAX3_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.IMaxTri(src0, src1, src2, is_signed)); -} - -void Translator::V_MED3_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::F32 src1{GetSrc(inst.src[1])}; - const IR::F32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.FPMedTri(src0, src1, src2)); -} - -void Translator::V_MED3_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - SetDst(inst.dst[0], ir.IMedTri(src0, src1, src2, is_signed)); -} - -void Translator::V_SAD(const GcnInst& inst) { - const IR::U32 abs_diff = ir.IAbs(ir.ISub(GetSrc(inst.src[0]), GetSrc(inst.src[1]))); - SetDst(inst.dst[0], ir.IAdd(abs_diff, GetSrc(inst.src[2]))); -} - -void Translator::V_SAD_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - IR::U32 result; - if (src0.IsImmediate() && src0.U32() == 0U) { - result = src1; - } else if (src1.IsImmediate() && src1.U32() == 0U) { - result = src0; - } else { - const IR::U32 max{ir.IMax(src0, src1, false)}; - const IR::U32 min{ir.IMin(src0, src1, false)}; - result = ir.ISub(max, min); - } - SetDst(inst.dst[0], ir.IAdd(result, src2)); -} - -void Translator::V_CVT_PK_U16_U32(const GcnInst& inst) { - const IR::Value vec_u32 = - ir.CompositeConstruct(ir.BitCast(GetSrc(inst.src[0])), - ir.BitCast(GetSrc(inst.src[1]))); - SetDst(inst.dst[0], ir.Pack2x16(AmdGpu::NumberFormat::Uint, vec_u32)); -} - -void Translator::V_CVT_PK_I16_I32(const GcnInst& inst) { - const IR::Value vec_u32 = - ir.CompositeConstruct(ir.BitCast(GetSrc(inst.src[0])), - ir.BitCast(GetSrc(inst.src[1]))); - SetDst(inst.dst[0], ir.Pack2x16(AmdGpu::NumberFormat::Sint, vec_u32)); -} - -void Translator::V_CVT_PK_U8_F32(const GcnInst& inst) { - const IR::F32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{GetSrc(inst.src[2])}; - - const IR::F32 clamped{ir.FPClamp(ir.FPRoundEven(src0), ir.Imm32(0.0f), ir.Imm32(255.0f))}; - const IR::F32 value{ir.Select(ir.FPIsNan(src0), ir.Imm32(0.0f), clamped)}; - const IR::U32 value_uint{ir.ConvertFToU(32, value)}; - const IR::U32 offset{ir.ShiftLeftLogical(ir.BitwiseAnd(src1, ir.Imm32(3)), ir.Imm32(3))}; - SetDst(inst.dst[0], ir.BitFieldInsert(src2, value_uint, offset, ir.Imm32(8))); -} - -void Translator::V_LSHL_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))); -} - -void Translator::V_LSHR_B64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.ShiftRightLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))); -} - -void Translator::V_ASHR_I64(const GcnInst& inst) { - const IR::U64 src0{GetSrc64(inst.src[0])}; - const IR::U64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))); -} - -void Translator::V_ALIGNBIT_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{ir.BitwiseAnd(GetSrc(inst.src[2]), ir.Imm32(0x1F))}; - const IR::U32 lo{ir.ShiftRightLogical(src1, src2)}; - const IR::U32 hi{ - ir.ShiftLeftLogical(ir.ShiftLeftLogical(src0, ir.Imm32(1)), ir.ISub(ir.Imm32(31), src2))}; - SetDst(inst.dst[0], ir.BitwiseOr(lo, hi)); -} - -void Translator::V_ALIGNBYTE_B32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 src2{ir.BitwiseAnd(GetSrc(inst.src[2]), ir.Imm32(0x3))}; - const IR::U32 shift{ir.ShiftLeftLogical(src2, ir.Imm32(3))}; - const IR::U32 lo{ir.ShiftRightLogical(src1, shift)}; - const IR::U32 hi{ - ir.ShiftLeftLogical(ir.ShiftLeftLogical(src0, ir.Imm32(1)), ir.ISub(ir.Imm32(31), shift))}; - SetDst(inst.dst[0], ir.BitwiseOr(lo, hi)); -} - -void Translator::V_MUL_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.FPMul(src0, src1)); -} - -void Translator::V_MIN_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.FPMin(src0, src1)); -} - -void Translator::V_MAX_F64(const GcnInst& inst) { - const IR::F64 src0{GetSrc64(inst.src[0])}; - const IR::F64 src1{GetSrc64(inst.src[1])}; - SetDst64(inst.dst[0], ir.FPMax(src0, src1)); -} - -void Translator::V_MUL_LO_U32(const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - SetDst(inst.dst[0], ir.IMul(src0, src1)); -} - -void Translator::V_MUL_HI_U32(bool is_signed, const GcnInst& inst) { - const IR::U32 src0{GetSrc(inst.src[0])}; - const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 hi{ir.IMulHi(src0, src1, is_signed)}; - SetDst(inst.dst[0], hi); -} - -void Translator::V_MAD_U64_U32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc64(inst.src[2]); - - const IR::U64 mul_result = ir.IMul(ir.UConvert(64, src0), ir.UConvert(64, src1)); - const IR::U64 sum_result = ir.IAdd(mul_result, src2); - - SetDst64(inst.dst[0], sum_result); - - const IR::U1 less_src0 = ir.ILessThan(sum_result, mul_result, false); - const IR::U1 less_src1 = ir.ILessThan(sum_result, src2, false); - const IR::U1 did_overflow = ir.LogicalOr(less_src0, less_src1); - - const auto unpacked = ir.UnpackUint2x32(ir.Ballot(did_overflow)); - const IR::U32 lo{ir.CompositeExtract(unpacked, 0U)}; - const IR::U32 hi{ir.CompositeExtract(unpacked, 1U)}; - ir.SetVccLo(lo); - ir.SetVccHi(hi); -} - -void Translator::V_LSHLREV_B16(const GcnInst& inst) { - const auto shift = GetSrc16(inst.src[0]); - const auto src = GetSrc16(inst.src[1]); - - const auto result = ir.ShiftLeftLogical(src, ir.BitwiseAnd(shift, ir.Imm32(0xF))); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_LSHRREV_B16(const GcnInst& inst) { - const auto shift = GetSrc16(inst.src[0]); - const auto src = GetSrc16(inst.src[1]); - - const auto result = ir.ShiftRightLogical(src, ir.BitwiseAnd(shift, ir.Imm32(0xF))); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_ASHRREV_I16(const GcnInst& inst) { - const auto shift = GetSrc16(inst.src[0]); - const auto src = GetSrc16(inst.src[1]); - - const auto result = ir.ShiftRightArithmetic(src, ir.BitwiseAnd(shift, ir.Imm32(0xF))); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_ADD_LSHL_U32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - const auto shift = ir.BitwiseAnd(src2, ir.Imm32(0x1F)); - - const auto result = ir.ShiftLeftLogical(ir.IAdd(src0, src1), shift); - - SetDst(inst.dst[0], result); -} - -void Translator::V_LSHL_ADD_U32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - const auto shift = ir.BitwiseAnd(src1, ir.Imm32(0x1F)); - - const auto result = ir.IAdd(ir.ShiftLeftLogical(src0, shift), src2); - - SetDst(inst.dst[0], result); -} - -void Translator::V_MIN3_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - const auto src2 = GetSrc16(inst.src[2]); - - const auto result = ir.FPMinTri(src0, src1, src2); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_MAX3_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - const auto src2 = GetSrc16(inst.src[2]); - - const auto result = ir.FPMaxTri(src0, src1, src2); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_MED3_F16(const GcnInst& inst) { - const auto src0 = GetSrc16(inst.src[0]); - const auto src1 = GetSrc16(inst.src[1]); - const auto src2 = GetSrc16(inst.src[2]); - - const auto result = ir.FPMedTri(src0, src1, src2); - - SetDst16(inst.dst[0], result); -} - -void Translator::V_ADD3_U32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - SetDst(inst.dst[0], ir.IAdd(src0, ir.IAdd(src1, src2))); -} - -void Translator::V_PK_MUL_LO_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.IMul(src0.first, src1.first); - const auto result_hi = ir.IMul(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_ADD_I16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.IAdd(src0.first, src1.first); - const auto result_hi = ir.IAdd(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_SUB_I16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.ISub(src0.first, src1.first); - const auto result_hi = ir.ISub(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_LSHLREV_B16(const GcnInst& inst) { - const auto shift = GetSrcPk(inst.src[0]); - const auto src = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.ShiftLeftLogical(src.first, shift.first); - const auto result_hi = ir.ShiftLeftLogical(src.second, shift.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_LSHRREV_B16(const GcnInst& inst) { - const auto shift = GetSrcPk(inst.src[0]); - const auto src = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.ShiftRightLogical(src.first, shift.first); - const auto result_hi = ir.ShiftRightLogical(src.second, shift.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MAD_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - const auto src2 = GetSrcPk(inst.src[2]); - - const auto result_lo = ir.IAdd(ir.IMul(src0.first, src1.first), src2.first); - const auto result_hi = ir.IAdd(ir.IMul(src0.second, src1.second), src2.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_ADD_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.IAdd(src0.first, src1.first); - const auto result_hi = ir.IAdd(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_SUB_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.ISub(src0.first, src1.first); - const auto result_hi = ir.ISub(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MAX_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.UMax(src0.first, src1.first); - const auto result_hi = ir.UMax(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MIN_U16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.UMin(src0.first, src1.first); - const auto result_hi = ir.UMin(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_FMA_F16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - const auto src2 = GetSrcPk(inst.src[2]); - - const auto result_lo = ir.FPFma(src0.first, src1.first, src2.first); - const auto result_hi = ir.FPFma(src0.second, src1.second, src2.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_ADD_F16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.FPAdd(src0.first, src1.first); - const auto result_hi = ir.FPAdd(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MUL_F16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.FPMul(src0.first, src1.first); - const auto result_hi = ir.FPMul(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MIN_F16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.FPMin(src0.first, src1.first); - const auto result_hi = ir.FPMin(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_PK_MAX_F16(const GcnInst& inst) { - const auto src0 = GetSrcPk(inst.src[0]); - const auto src1 = GetSrcPk(inst.src[1]); - - const auto result_lo = ir.FPMax(src0.first, src1.first); - const auto result_hi = ir.FPMax(src0.second, src1.second); - - SetDstPk(inst.dst[0], {result_lo, result_hi}); -} - -void Translator::V_LSHL_OR_B32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - const auto shift = ir.BitwiseAnd(src1, ir.Imm32(0x1F)); - - const auto result = ir.BitwiseOr(ir.ShiftLeftLogical(src0, shift), src2); - - SetDst(inst.dst[0], result); -} - -void Translator::V_AND_OR_B32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - const auto result = ir.BitwiseOr(ir.BitwiseAnd(src0, src1), src2); - - SetDst(inst.dst[0], result); -} - -void Translator::V_OR3_B32(const GcnInst& inst) { - const auto src0 = GetSrc(inst.src[0]); - const auto src1 = GetSrc(inst.src[1]); - const auto src2 = GetSrc(inst.src[2]); - - const auto result = ir.BitwiseOr(ir.BitwiseOr(src0, src1), src2); - - SetDst(inst.dst[0], result); -} - -void Translator::V_MAD_MIX_F32(const GcnInst& inst) { - const auto src0 = GetSrcMix(inst.src[0]); - const auto src1 = GetSrcMix(inst.src[1]); - const auto src2 = GetSrcMix(inst.src[2]); - - const IR::F32 result = ir.FPAdd(ir.FPMul(src0, src1), src2); - - SetDst(inst.dst[0], result); -} - -void Translator::V_MAD_MIXLO_F16(const GcnInst& inst) { - const auto src0 = GetSrcMix(inst.src[0]); - const auto src1 = GetSrcMix(inst.src[1]); - const auto src2 = GetSrcMix(inst.src[2]); - - const IR::F32 result = ir.FPAdd(ir.FPMul(src0, src1), src2); - const IR::F16 result_f16 = ir.FPConvert(16, result); - const IR::U16 result_f16_u16 = ir.BitCast(result_f16); - - const IR::U32 old_value{GetSrc(inst.dst[0])}; - const IR::U32 new_value{ - ir.BitFieldInsert(old_value, ir.UConvert(32, result_f16_u16), ir.Imm32(0U), ir.Imm32(16U))}; - SetDst(inst.dst[0], new_value); -} - -void Translator::V_MAD_MIXHI_F16(const GcnInst& inst) { - const auto src0 = GetSrcMix(inst.src[0]); - const auto src1 = GetSrcMix(inst.src[1]); - const auto src2 = GetSrcMix(inst.src[2]); - - const IR::F32 result = ir.FPAdd(ir.FPMul(src0, src1), src2); - const IR::F16 result_f16 = ir.FPConvert(16, result); - const IR::U16 result_f16_u16 = ir.BitCast(result_f16); - - const IR::U32 old_value{GetSrc(inst.dst[0])}; - const IR::U32 new_value{ir.BitFieldInsert(old_value, ir.UConvert(32, result_f16_u16), - ir.Imm32(16U), ir.Imm32(16U))}; - SetDst(inst.dst[0], new_value); -} - -IR::U32 Translator::GetCarryIn(const GcnInst& inst) { - IR::U64 carry; - if (inst.src_count == 3) { // VOP3 - carry = GetSrc64(inst.src[2]); - } else { // VOP2 - carry = ir.PackUint2x32(ir.CompositeConstruct(ir.GetVccLo(), ir.GetVccHi())); - } - - return IR::U32{ir.Select(ir.InverseBallot(carry), ir.Imm32(1), ir.Imm32(0))}; -} - -void Translator::SetCarryOut(const GcnInst& inst, const IR::U1& carry) { - if (inst.dst_count == 2) { // VOP3 - SetDst64(inst.dst[1], ir.Ballot(carry)); - } else { // VOP2 - const auto unpacked = ir.UnpackUint2x32(ir.Ballot(carry)); - const IR::U32 lo{ir.CompositeExtract(unpacked, 0U)}; - const IR::U32 hi{ir.CompositeExtract(unpacked, 1U)}; - ir.SetVccLo(lo); - ir.SetVccHi(hi); - } -} - -// TODO: add range analysis pass to hopefully put an upper bound on m0, and only select one of -// [src_vgprno, src_vgprno + max_m0]. Same for dst regs we may write back to - -IR::U32 Translator::VMovRelSHelper(u32 src_vgprno, const IR::U32 m0) { - // Read from VGPR0 by default when src_vgprno + m0 > num_allocated_vgprs - IR::U32 src_val = ir.GetVectorReg(IR::VectorReg::V0); - for (u32 i = src_vgprno; i < runtime_info.props.num_allocated_vgprs; i++) { - const IR::U1 cond = ir.IEqual(m0, ir.Imm32(i - src_vgprno)); - src_val = - IR::U32{ir.Select(cond, ir.GetVectorReg(IR::VectorReg::V0 + i), src_val)}; - } - return src_val; -} - -void Translator::VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0) { - for (u32 i = dst_vgprno; i < runtime_info.props.num_allocated_vgprs; i++) { - const IR::U1 cond = ir.IEqual(m0, ir.Imm32(i - dst_vgprno)); - const IR::U32 dst_val = - IR::U32{ir.Select(cond, src_val, ir.GetVectorReg(IR::VectorReg::V0 + i))}; - ir.SetVectorReg(IR::VectorReg::V0 + i, dst_val); - } -} - -} // namespace Shader::Gcn diff --git a/src/shader_recompiler/ir/condition.h b/src/shader_recompiler/ir/condition.h deleted file mode 100644 index 5ee6d15..0000000 --- a/src/shader_recompiler/ir/condition.h +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include "common/types.h" - -namespace Shader::IR { - -enum class Condition : u32 { - False, - True, - Scc0, - Scc1, - Vccz, - Vccnz, - Execz, - Execnz, -}; - -constexpr std::string_view NameOf(Condition condition) { - switch (condition) { - case Condition::False: - return "False"; - case Condition::True: - return "True"; - case Condition::Scc0: - return "Scc0"; - case Condition::Scc1: - return "Scc1"; - case Condition::Vccz: - return "Vccz"; - case Condition::Vccnz: - return "Vccnz"; - case Condition::Execz: - return "Execz"; - case Condition::Execnz: - return "Execnz"; - default: - UNREACHABLE(); - } -} - -} // namespace Shader::IR - -template <> -struct fmt::formatter : formatter { - auto format(const Shader::IR::Condition cond, format_context& ctx) const { - return formatter::format(NameOf(cond), ctx); - } -}; diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp deleted file mode 100644 index fe3e030..0000000 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ /dev/null @@ -1,2232 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include "common/assert.h" -#include "shader_recompiler/ir/debug_print.h" -#include "shader_recompiler/ir/ir_emitter.h" -#include "shader_recompiler/ir/opcodes.h" -#include "shader_recompiler/ir/value.h" - -namespace Shader::IR { -namespace { -[[noreturn]] void ThrowInvalidType(Type type, - std::source_location loc = std::source_location::current()) { - const std::string functionName = loc.function_name(); - const int lineNumber = loc.line(); - UNREACHABLE_MSG("Invalid type = {}, functionName = {}, line = {}", u32(type), functionName, - lineNumber); -} -} // Anonymous namespace - -U1 IREmitter::Imm1(bool value) const { - return U1{Value{value}}; -} - -U8 IREmitter::Imm8(u8 value) const { - return U8{Value{value}}; -} - -U16 IREmitter::Imm16(u16 value) const { - return U16{Value{value}}; -} - -U32 IREmitter::Imm32(u32 value) const { - return U32{Value{value}}; -} - -U32 IREmitter::Imm32(s32 value) const { - return U32{Value{static_cast(value)}}; -} - -F32 IREmitter::Imm32(f32 value) const { - return F32{Value{value}}; -} - -U64 IREmitter::Imm64(u64 value) const { - return U64{Value{value}}; -} - -U64 IREmitter::Imm64(s64 value) const { - return U64{Value{static_cast(value)}}; -} - -F64 IREmitter::Imm64(f64 value) const { - return F64{Value{value}}; -} - -template <> -IR::U32 IREmitter::BitCast(const IR::U1& value) { - return IR::U32{Select(value, Imm32(1), Imm32(0))}; -} - -template <> -IR::U32 IREmitter::BitCast(const IR::F32& value) { - return Inst(Opcode::BitCastU32F32, value); -} - -template <> -IR::F32 IREmitter::BitCast(const IR::U32& value) { - return Inst(Opcode::BitCastF32U32, value); -} - -template <> -IR::U16 IREmitter::BitCast(const IR::F16& value) { - return Inst(Opcode::BitCastU16F16, value); -} - -template <> -IR::F16 IREmitter::BitCast(const IR::U16& value) { - return Inst(Opcode::BitCastF16U16, value); -} - -U1 IREmitter::ConditionRef(const U1& value) { - return Inst(Opcode::ConditionRef, value); -} - -void IREmitter::Prologue() { - Inst(Opcode::Prologue); -} - -void IREmitter::Epilogue() { - Inst(Opcode::Epilogue); -} - -void IREmitter::Discard() { - Inst(Opcode::Discard); -} - -void IREmitter::Discard(const U1& cond) { - Inst(Opcode::DiscardCond, cond); -} - -void IREmitter::Barrier() { - Inst(Opcode::Barrier); -} - -void IREmitter::WorkgroupMemoryBarrier() { - Inst(Opcode::WorkgroupMemoryBarrier); -} - -void IREmitter::DeviceMemoryBarrier() { - Inst(Opcode::DeviceMemoryBarrier); -} - -U32 IREmitter::GetUserData(IR::ScalarReg reg) { - ASSERT(static_cast(reg) < IR::NumScalarRegs); - return Inst(Opcode::GetUserData, reg); -} - -template <> -U32 IREmitter::GetScalarReg(IR::ScalarReg reg) { - ASSERT(static_cast(reg) < IR::NumScalarRegs); - return Inst(Opcode::GetScalarRegister, reg); -} - -template <> -F32 IREmitter::GetScalarReg(IR::ScalarReg reg) { - return BitCast(GetScalarReg(reg)); -} - -template <> -U32 IREmitter::GetVectorReg(IR::VectorReg reg) { - ASSERT(static_cast(reg) < IR::NumVectorRegs); - return Inst(Opcode::GetVectorRegister, reg); -} - -template <> -F32 IREmitter::GetVectorReg(IR::VectorReg reg) { - return BitCast(GetVectorReg(reg)); -} - -void IREmitter::SetScalarReg(IR::ScalarReg reg, const U32F32& value) { - ASSERT(reg < IR::ScalarReg::Max); - const U32 value_typed = value.Type() == Type::F32 ? BitCast(F32{value}) : U32{value}; - Inst(Opcode::SetScalarRegister, reg, value_typed); -} - -void IREmitter::SetVectorReg(IR::VectorReg reg, const U32F32& value) { - ASSERT(reg < IR::VectorReg::Max); - const U32 value_typed = value.Type() == Type::F32 ? BitCast(F32{value}) : U32{value}; - Inst(Opcode::SetVectorRegister, reg, value_typed); -} - -Value IREmitter::GetVirtualReg(IR::VirtualReg reg) { - return Inst(Opcode::GetVirtualRegister, reg); -} - -void IREmitter::SetVirtualReg(IR::VirtualReg reg, const Value& value) { - Inst(Opcode::SetVirtualRegister, reg, value); -} - -U1 IREmitter::GetGotoVariable(u32 id) { - return Inst(Opcode::GetGotoVariable, id); -} - -U1 IREmitter::Condition(IR::Condition cond) { - switch (cond) { - case IR::Condition::False: - return Imm1(false); - case IR::Condition::True: - return Imm1(true); - case IR::Condition::Scc0: - return LogicalNot(GetScc()); - case IR::Condition::Scc1: - return GetScc(); - // Branches on VCC test the whole wave, as the hardware does. - case IR::Condition::Vccz: - return IEqual(PackUint2x32(CompositeConstruct(GetVccLo(), GetVccHi())), Imm64(u64(0))); - case IR::Condition::Vccnz: - return INotEqual(PackUint2x32(CompositeConstruct(GetVccLo(), GetVccHi())), Imm64(u64(0))); - // EXEC branches are taken per lane: the lanes with EXEC clear skip the code the hardware - // masks for them. - case IR::Condition::Execz: - return LogicalNot(GetExec()); - case IR::Condition::Execnz: - return GetExec(); - default: - UNREACHABLE_MSG(""); - } -} - -void IREmitter::SetGotoVariable(u32 id, const U1& value) { - Inst(Opcode::SetGotoVariable, id, value); -} - -U1 IREmitter::GetScc() { - return Inst(Opcode::GetScc); -} - -U1 IREmitter::GetExec() { - return Inst(Opcode::GetExec); -} - -U32 IREmitter::GetVccLo() { - return Inst(Opcode::GetVccLo); -} - -U32 IREmitter::GetVccHi() { - return Inst(Opcode::GetVccHi); -} - -U32 IREmitter::GetM0() { - return Inst(Opcode::GetM0); -} - -void IREmitter::SetScc(const U1& value) { - Inst(Opcode::SetScc, value); -} - -void IREmitter::SetExec(const U1& value) { - Inst(Opcode::SetExec, value); -} - -void IREmitter::SetVccLo(const U32& value) { - Inst(Opcode::SetVccLo, value); -} - -void IREmitter::SetVccHi(const U32& value) { - Inst(Opcode::SetVccHi, value); -} - -void IREmitter::SetM0(const U32& value) { - Inst(Opcode::SetM0, value); -} - -F32 IREmitter::GetAttribute(IR::Attribute attribute, u32 comp, u32 index) { - return Inst(Opcode::GetAttribute, attribute, Imm32(comp), Imm32(index)); -} - -U1 IREmitter::GetAttributeU1(IR::Attribute attribute, u32 comp) { - return Inst(Opcode::GetAttributeU1, attribute, Imm32(comp)); -} - -U32 IREmitter::GetAttributeU32(IR::Attribute attribute, u32 comp) { - return Inst(Opcode::GetAttributeU32, attribute, Imm32(comp)); -} - -void IREmitter::SetAttribute(IR::Attribute attribute, const F32& value, u32 comp) { - Inst(Opcode::SetAttribute, attribute, value, Imm32(comp)); -} - -F32 IREmitter::GetTessGenericAttribute(const U32& vertex_index, const U32& attr_index, - const U32& comp_index) { - return Inst(IR::Opcode::GetTessGenericAttribute, vertex_index, attr_index, comp_index); -} - -void IREmitter::SetTcsGenericAttribute(const F32& value, const U32& attr_index, - const U32& comp_index) { - Inst(Opcode::SetTcsGenericAttribute, value, attr_index, comp_index); -} - -F32 IREmitter::ReadTcsGenericOuputAttribute(const U32& vertex_index, const U32& attr_index, - const U32& comp_index) { - return Inst(IR::Opcode::ReadTcsGenericOuputAttribute, vertex_index, attr_index, - comp_index); -} - -U32 IREmitter::GetPcLo(const U32& pc) { - return Inst(IR::Opcode::GetPcLo, pc); -} - -F32 IREmitter::GetPatch(Patch patch) { - return Inst(Opcode::GetPatch, patch); -} - -void IREmitter::SetPatch(Patch patch, const F32& value) { - Inst(Opcode::SetPatch, patch, value); -} - -Value IREmitter::LoadShared(int bit_size, bool is_signed, const U32& offset, bool is_gds) { - switch (bit_size) { - case 16: - return Inst(Opcode::LoadSharedU16, Flags{is_gds}, offset); - case 32: - return Inst(Opcode::LoadSharedU32, Flags{is_gds}, offset); - case 64: - return Inst(Opcode::LoadSharedU64, Flags{is_gds}, offset); - default: - UNREACHABLE_MSG("Invalid bit size {}", bit_size); - } -} - -void IREmitter::WriteShared(int bit_size, const Value& value, const U32& offset, bool is_gds) { - switch (bit_size) { - case 16: - Inst(Opcode::WriteSharedU16, Flags{is_gds}, offset, value); - break; - case 32: - Inst(Opcode::WriteSharedU32, Flags{is_gds}, offset, value); - break; - case 64: - Inst(Opcode::WriteSharedU64, Flags{is_gds}, offset, value); - break; - default: - UNREACHABLE_MSG("Invalid bit size {}", bit_size); - } -} - -U32U64 IREmitter::SharedAtomicIAdd(const U32& address, const U32U64& data, bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicIAdd32, Flags{is_gds}, address, data); - case Type::U64: - return Inst(Opcode::SharedAtomicIAdd64, Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicIMin(const U32& address, const U32U64& data, bool is_signed, - bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SharedAtomicSMin32 : Opcode::SharedAtomicUMin32, - Flags{is_gds}, address, data); - case Type::U64: - return Inst(is_signed ? Opcode::SharedAtomicSMin64 : Opcode::SharedAtomicUMin64, - Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicIMax(const U32& address, const U32U64& data, bool is_signed, - bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SharedAtomicSMax32 : Opcode::SharedAtomicUMax32, - Flags{is_gds}, address, data); - case Type::U64: - return Inst(is_signed ? Opcode::SharedAtomicSMax64 : Opcode::SharedAtomicUMax64, - Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicAnd(const U32& address, const U32U64& data, bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicAnd32, Flags{is_gds}, address, data); - case Type::U64: - return Inst(Opcode::SharedAtomicAnd64, Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicOr(const U32& address, const U32U64& data, bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicOr32, Flags{is_gds}, address, data); - case Type::U64: - return Inst(Opcode::SharedAtomicOr64, Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicXor(const U32& address, const U32U64& data, bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicXor32, Flags{is_gds}, address, data); - case Type::U64: - return Inst(Opcode::SharedAtomicXor64, Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicISub(const U32& address, const U32U64& data, bool is_gds) { - switch (data.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicISub32, Flags{is_gds}, address, data); - case Type::U64: - return Inst(Opcode::SharedAtomicISub64, Flags{is_gds}, address, data); - default: - ThrowInvalidType(data.Type()); - } -} - -U32U64 IREmitter::SharedAtomicCmpSwap(const U32& address, const U32U64& value, - const U32U64& cmp_value, bool is_gds) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::SharedAtomicCmpSwap32, Flags{is_gds}, address, value, cmp_value); - case Type::U64: - return Inst(Opcode::SharedAtomicCmpSwap64, Flags{is_gds}, address, value, cmp_value); - default: - ThrowInvalidType(value.Type()); - } -} - -template <> -U32 IREmitter::SharedAtomicInc(const U32& address, bool is_gds) { - return Inst(Opcode::SharedAtomicInc32, Flags{is_gds}, address); -} - -template <> -U64 IREmitter::SharedAtomicInc(const U32& address, bool is_gds) { - return Inst(Opcode::SharedAtomicInc64, Flags{is_gds}, address); -} - -template <> -U32 IREmitter::SharedAtomicDec(const U32& address, bool is_gds) { - return Inst(Opcode::SharedAtomicDec32, Flags{is_gds}, address); -} - -template <> -U64 IREmitter::SharedAtomicDec(const U32& address, bool is_gds) { - return Inst(Opcode::SharedAtomicDec64, Flags{is_gds}, address); -} - -U32 IREmitter::ReadConst(const Value& base, const U32& offset) { - return Inst(Opcode::ReadConst, base, offset); -} - -U32 IREmitter::ReadConstBuffer(const Value& handle, const U32& index, BufferInstInfo info) { - return Inst(Opcode::ReadConstBuffer, Flags{info}, handle, index); -} - -U8 IREmitter::LoadBufferU8(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::LoadBufferU8, Flags{info}, handle, address); -} - -U16 IREmitter::LoadBufferU16(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::LoadBufferU16, Flags{info}, handle, address); -} - -Value IREmitter::LoadBufferU32(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info) { - switch (num_dwords) { - case 1: - return Inst(Opcode::LoadBufferU32, Flags{info}, handle, address); - case 2: - return Inst(Opcode::LoadBufferU32x2, Flags{info}, handle, address); - case 3: - return Inst(Opcode::LoadBufferU32x3, Flags{info}, handle, address); - case 4: - return Inst(Opcode::LoadBufferU32x4, Flags{info}, handle, address); - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } -} - -U64 IREmitter::LoadBufferU64(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::LoadBufferU64, Flags{info}, handle, address); -} - -Value IREmitter::LoadBufferF32(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info) { - switch (num_dwords) { - case 1: - return Inst(Opcode::LoadBufferF32, Flags{info}, handle, address); - case 2: - return Inst(Opcode::LoadBufferF32x2, Flags{info}, handle, address); - case 3: - return Inst(Opcode::LoadBufferF32x3, Flags{info}, handle, address); - case 4: - return Inst(Opcode::LoadBufferF32x4, Flags{info}, handle, address); - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } -} - -Value IREmitter::LoadBufferFormat(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::LoadBufferFormatF32, Flags{info}, handle, address); -} - -void IREmitter::StoreBufferU8(const Value& handle, const Value& address, const U8& data, - BufferInstInfo info) { - Inst(Opcode::StoreBufferU8, Flags{info}, handle, address, data); -} - -void IREmitter::StoreBufferU16(const Value& handle, const Value& address, const U16& data, - BufferInstInfo info) { - Inst(Opcode::StoreBufferU16, Flags{info}, handle, address, data); -} - -void IREmitter::StoreBufferU32(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info) { - switch (num_dwords) { - case 1: - Inst(Opcode::StoreBufferU32, Flags{info}, handle, address, data); - break; - case 2: - Inst(Opcode::StoreBufferU32x2, Flags{info}, handle, address, data); - break; - case 3: - Inst(Opcode::StoreBufferU32x3, Flags{info}, handle, address, data); - break; - case 4: - Inst(Opcode::StoreBufferU32x4, Flags{info}, handle, address, data); - break; - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } -} - -void IREmitter::StoreBufferU64(const Value& handle, const Value& address, const U64& data, - BufferInstInfo info) { - Inst(Opcode::StoreBufferU64, Flags{info}, handle, address, data); -} - -void IREmitter::StoreBufferF32(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info) { - switch (num_dwords) { - case 1: - Inst(Opcode::StoreBufferF32, Flags{info}, handle, address, data); - break; - case 2: - Inst(Opcode::StoreBufferF32x2, Flags{info}, handle, address, data); - break; - case 3: - Inst(Opcode::StoreBufferF32x3, Flags{info}, handle, address, data); - break; - case 4: - Inst(Opcode::StoreBufferF32x4, Flags{info}, handle, address, data); - break; - default: - UNREACHABLE_MSG("Invalid number of dwords {}", num_dwords); - } -} - -void IREmitter::StoreBufferFormat(const Value& handle, const Value& address, const Value& data, - BufferInstInfo info) { - Inst(Opcode::StoreBufferFormatF32, Flags{info}, handle, address, data); -} - -Value IREmitter::BufferAtomicIAdd(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::BufferAtomicIAdd32, Flags{info}, handle, address, value); - case Type::U64: - return Inst(Opcode::BufferAtomicIAdd64, Flags{info}, handle, address, value); - default: - ThrowInvalidType(value.Type()); - } -} - -Value IREmitter::BufferAtomicISub(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicISub32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicIMin(const Value& handle, const Value& address, const Value& value, - bool is_signed, BufferInstInfo info) { - switch (value.Type()) { - case Type::U32: - return is_signed ? Inst(Opcode::BufferAtomicSMin32, Flags{info}, handle, address, value) - : Inst(Opcode::BufferAtomicUMin32, Flags{info}, handle, address, value); - case Type::U64: - return is_signed ? Inst(Opcode::BufferAtomicSMin64, Flags{info}, handle, address, value) - : Inst(Opcode::BufferAtomicUMin64, Flags{info}, handle, address, value); - default: - ThrowInvalidType(value.Type()); - } -} - -Value IREmitter::BufferAtomicFMin(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicFMin32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicIMax(const Value& handle, const Value& address, const Value& value, - bool is_signed, BufferInstInfo info) { - switch (value.Type()) { - case Type::U32: - return is_signed ? Inst(Opcode::BufferAtomicSMax32, Flags{info}, handle, address, value) - : Inst(Opcode::BufferAtomicUMax32, Flags{info}, handle, address, value); - case Type::U64: - return is_signed ? Inst(Opcode::BufferAtomicSMax64, Flags{info}, handle, address, value) - : Inst(Opcode::BufferAtomicUMax64, Flags{info}, handle, address, value); - default: - ThrowInvalidType(value.Type()); - } -} - -Value IREmitter::BufferAtomicFMax(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicFMax32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicInc(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::BufferAtomicInc32, Flags{info}, handle, address); -} - -Value IREmitter::BufferAtomicDec(const Value& handle, const Value& address, BufferInstInfo info) { - return Inst(Opcode::BufferAtomicDec32, Flags{info}, handle, address); -} - -Value IREmitter::BufferAtomicAnd(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicAnd32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicOr(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicOr32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicXor(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicXor32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, const Value& value, - BufferInstInfo info) { - return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value); -} - -Value IREmitter::BufferAtomicCmpSwap(const Value& handle, const Value& address, const Value& vdata, - const Value& cmp_value, BufferInstInfo info) { - return Inst(Opcode::BufferAtomicCmpSwap32, Flags{info}, handle, address, vdata, cmp_value); -} - -Value IREmitter::BufferAtomicFCmpSwap(const Value& handle, const Value& address, const Value& vdata, - const Value& cmp_value, BufferInstInfo info) { - return Inst(Opcode::BufferAtomicFCmpSwap32, Flags{info}, handle, address, vdata, cmp_value); -} - -U32 IREmitter::DataAppend(const U32& gds_dw_offset) { - return Inst(Opcode::DataAppend, gds_dw_offset, GetExec()); -} - -U32 IREmitter::DataConsume(const U32& gds_dw_offset) { - return Inst(Opcode::DataConsume, gds_dw_offset, GetExec()); -} - -U32 IREmitter::LaneId() { - return Inst(Opcode::LaneId); -} - -U32 IREmitter::WarpId() { - return Inst(Opcode::WarpId); -} - -U32 IREmitter::QuadBroadcast(const U32& value, const U32& index) { - return Inst(Opcode::QuadBroadcast, value, index); -} - -U32 IREmitter::Shuffle(const U32& value, const U32& index) { - return Inst(Opcode::Shuffle, value, index); -} - -U32 IREmitter::ShuffleXor(const U32& value, const U32& mask) { - return Inst(Opcode::ShuffleXor, value, mask); -} - -U32 IREmitter::ReadFirstLane(const U32& value, const U1& exec) { - return Inst(Opcode::ReadFirstLane, value, exec); -} - -U32 IREmitter::ReadLane(const U32& value, const U32& lane) { - return Inst(Opcode::ReadLane, value, lane); -} - -U32 IREmitter::WriteLane(const U32& value, const U32& write_value, const U32& lane) { - return Inst(Opcode::WriteLane, value, write_value, lane); -} - -U64 IREmitter::Ballot(const U1& bit) { - return Inst(Opcode::Ballot, bit); -} - -U32 IREmitter::BallotFindLsb(const U64& mask) { - return Inst(Opcode::BallotFindLsb, mask); -} - -U1 IREmitter::InverseBallot(const U64& mask) { - return Inst(Opcode::InverseBallot, mask); -} - -U1 IREmitter::GroupAny(const U1& bit) { - return Inst(Opcode::GroupAny, bit); -} - -F32F64 IREmitter::FPAdd(const F32F64& a, const F32F64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::F32: - return Inst(Opcode::FPAdd32, a, b); - case Type::F64: - return Inst(Opcode::FPAdd64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -F32F64 IREmitter::FPSub(const F32F64& a, const F32F64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::F32: - return Inst(Opcode::FPSub32, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2) { - if (e1.Type() != e2.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", e1.Type(), e2.Type()); - } - switch (e1.Type()) { - case Type::U32: - return Inst(Opcode::CompositeConstructU32x2, e1, e2); - case Type::U32x2: - return Inst(Opcode::CompositeConstructU32x2x2, e1, e2); - case Type::F32: - return Inst(Opcode::CompositeConstructF32x2, e1, e2); - case Type::F32x2: - return Inst(Opcode::CompositeConstructF32x2x2, e1, e2); - default: - ThrowInvalidType(e1.Type()); - } -} - -Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3) { - if (e1.Type() != e2.Type() || e1.Type() != e3.Type()) { - UNREACHABLE_MSG("Mismatching types {}, {}, and {}", e1.Type(), e2.Type(), e3.Type()); - } - switch (e1.Type()) { - case Type::U32: - return Inst(Opcode::CompositeConstructU32x3, e1, e2, e3); - case Type::F32: - return Inst(Opcode::CompositeConstructF32x3, e1, e2, e3); - default: - ThrowInvalidType(e1.Type()); - } -} - -Value IREmitter::CompositeConstruct(const Value& e1, const Value& e2, const Value& e3, - const Value& e4) { - if (e1.Type() != e2.Type() || e1.Type() != e3.Type() || e1.Type() != e4.Type()) { - UNREACHABLE_MSG("Mismatching types {}, {}, {}, and {}", e1.Type(), e2.Type(), e3.Type(), - e4.Type()); - } - switch (e1.Type()) { - case Type::U32: - return Inst(Opcode::CompositeConstructU32x4, e1, e2, e3, e4); - case Type::F32: - return Inst(Opcode::CompositeConstructF32x4, e1, e2, e3, e4); - default: - ThrowInvalidType(e1.Type()); - } -} - -Value IREmitter::CompositeConstruct(std::span elements) { - switch (elements.size()) { - case 2: - return CompositeConstruct(elements[0], elements[1]); - case 3: - return CompositeConstruct(elements[0], elements[1], elements[2]); - case 4: - return CompositeConstruct(elements[0], elements[1], elements[2], elements[3]); - default: - UNREACHABLE_MSG("Composite construct with {} elements, only 2-4 are supported", - elements.size()); - } -} - -Value IREmitter::CompositeExtract(const Value& vector, size_t element) { - const auto read{[&](Opcode opcode, size_t limit) -> Value { - if (element >= limit) { - UNREACHABLE_MSG("Out of bounds element {}", element); - } - return Inst(opcode, vector, Value{static_cast(element)}); - }}; - switch (vector.Type()) { - case Type::U32x2: - return read(Opcode::CompositeExtractU32x2, 2); - case Type::U32x3: - return read(Opcode::CompositeExtractU32x3, 3); - case Type::U32x4: - return read(Opcode::CompositeExtractU32x4, 4); - case Type::F32x2: - return read(Opcode::CompositeExtractF32x2, 2); - case Type::F32x3: - return read(Opcode::CompositeExtractF32x3, 3); - case Type::F32x4: - return read(Opcode::CompositeExtractF32x4, 4); - default: - ThrowInvalidType(vector.Type()); - } -} - -Value IREmitter::CompositeInsert(const Value& vector, const Value& object, size_t element) { - const auto insert{[&](Opcode opcode, size_t limit) { - if (element >= limit) { - UNREACHABLE_MSG("Out of bounds element {}", element); - } - return Inst(opcode, vector, object, Value{static_cast(element)}); - }}; - switch (vector.Type()) { - case Type::U32x2: - return insert(Opcode::CompositeInsertU32x2, 2); - case Type::U32x3: - return insert(Opcode::CompositeInsertU32x3, 3); - case Type::U32x4: - return insert(Opcode::CompositeInsertU32x4, 4); - case Type::F32x2: - return insert(Opcode::CompositeInsertF32x2, 2); - case Type::F32x3: - return insert(Opcode::CompositeInsertF32x3, 3); - case Type::F32x4: - return insert(Opcode::CompositeInsertF32x4, 4); - default: - ThrowInvalidType(vector.Type()); - } -} - -Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1) { - if (vector1.Type() != vector2.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); - } - if (comp0 >= 4 || comp1 >= 4) { - UNREACHABLE_MSG("One or more out of bounds elements {}, {}", comp0, comp1); - } - const auto shuffle{[&](Opcode opcode) -> Value { - return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, - Value{static_cast(comp1)}); - }}; - switch (vector1.Type()) { - case Type::U32x4: - return shuffle(Opcode::CompositeShuffleU32x2); - case Type::F32x4: - return shuffle(Opcode::CompositeShuffleF32x2); - default: - ThrowInvalidType(vector1.Type()); - } -} - -Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1, size_t comp2) { - if (vector1.Type() != vector2.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); - } - if (comp0 >= 6 || comp1 >= 6 || comp2 >= 6) { - UNREACHABLE_MSG("One or more out of bounds elements {}, {}, {}", comp0, comp1, comp2); - } - const auto shuffle{[&](Opcode opcode) -> Value { - return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, - Value{static_cast(comp1)}, Value{static_cast(comp2)}); - }}; - switch (vector1.Type()) { - case Type::U32x4: - return shuffle(Opcode::CompositeShuffleU32x3); - case Type::F32x4: - return shuffle(Opcode::CompositeShuffleF32x3); - default: - ThrowInvalidType(vector1.Type()); - } -} - -Value IREmitter::CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1, size_t comp2, size_t comp3) { - if (vector1.Type() != vector2.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", vector1.Type(), vector2.Type()); - } - if (comp0 >= 8 || comp1 >= 8 || comp2 >= 8 || comp3 >= 8) { - UNREACHABLE_MSG("One or more out of bounds elements {}, {}, {}, {}", comp0, comp1, comp2, - comp3); - } - const auto shuffle{[&](Opcode opcode) -> Value { - return Inst(opcode, vector1, vector2, Value{static_cast(comp0)}, - Value{static_cast(comp1)}, Value{static_cast(comp2)}, - Value{static_cast(comp3)}); - }}; - switch (vector1.Type()) { - case Type::U32x4: - return shuffle(Opcode::CompositeShuffleU32x4); - case Type::F32x4: - return shuffle(Opcode::CompositeShuffleF32x4); - default: - ThrowInvalidType(vector1.Type()); - } -} - -Value IREmitter::Select(const U1& condition, const Value& true_value, const Value& false_value) { - if (true_value.Type() != false_value.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", true_value.Type(), false_value.Type()); - } - switch (true_value.Type()) { - case Type::U1: - return Inst(Opcode::SelectU1, condition, true_value, false_value); - case Type::U32: - return Inst(Opcode::SelectU32, condition, true_value, false_value); - case Type::F32: - return Inst(Opcode::SelectF32, condition, true_value, false_value); - case Type::U64: - return Inst(Opcode::SelectU64, condition, true_value, false_value); - default: - UNREACHABLE_MSG("Invalid type {}", true_value.Type()); - } -} - -U64 IREmitter::PackUint2x32(const Value& vector) { - return Inst(Opcode::PackUint2x32, vector); -} - -Value IREmitter::UnpackUint2x32(const U64& value) { - return Inst(Opcode::UnpackUint2x32, value); -} - -F64 IREmitter::PackDouble2x32(const Value& vector) { - return Inst(Opcode::PackDouble2x32, vector); -} - -Value IREmitter::UnpackDouble2x32(const F64& value) { - return Inst(Opcode::UnpackDouble2x32, value); -} - -U32 IREmitter::Pack2x16(const AmdGpu::NumberFormat number_format, const Value& vector) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::PackUnorm2x16, vector); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::PackSnorm2x16, vector); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::PackUint2x16, vector); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::PackSint2x16, vector); - case AmdGpu::NumberFormat::Float: - return Inst(Opcode::PackHalf2x16, vector); - default: - UNREACHABLE_MSG("Unsupported 2x16 number format: {}", number_format); - } -} - -Value IREmitter::Unpack2x16(const AmdGpu::NumberFormat number_format, const U32& value) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::UnpackUnorm2x16, value); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::UnpackSnorm2x16, value); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::UnpackUint2x16, value); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::UnpackSint2x16, value); - case AmdGpu::NumberFormat::Float: - return Inst(Opcode::UnpackHalf2x16, value); - default: - UNREACHABLE_MSG("Unsupported 2x16 number format: {}", number_format); - } -} - -U32 IREmitter::Pack4x8(const AmdGpu::NumberFormat number_format, const Value& vector) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::PackUnorm4x8, vector); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::PackSnorm4x8, vector); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::PackUint4x8, vector); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::PackSint4x8, vector); - default: - UNREACHABLE_MSG("Unsupported 4x8 number format: {}", number_format); - } -} - -Value IREmitter::Unpack4x8(const AmdGpu::NumberFormat number_format, const U32& value) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::UnpackUnorm4x8, value); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::UnpackSnorm4x8, value); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::UnpackUint4x8, value); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::UnpackSint4x8, value); - default: - UNREACHABLE_MSG("Unsupported 4x8 number format: {}", number_format); - } -} - -U32 IREmitter::Pack10_11_11(const AmdGpu::NumberFormat number_format, const Value& vector) { - switch (number_format) { - case AmdGpu::NumberFormat::Float: - return Inst(Opcode::PackUfloat10_11_11, vector); - default: - UNREACHABLE_MSG("Unsupported 10_11_11 number format: {}", number_format); - } -} - -U32 IREmitter::Pack2_10_10_10(const AmdGpu::NumberFormat number_format, const Value& vector) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::PackUnorm2_10_10_10, vector); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::PackSnorm2_10_10_10, vector); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::PackUint2_10_10_10, vector); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::PackSint2_10_10_10, vector); - default: - UNREACHABLE_MSG("Unsupported 2_10_10_10 number format: {}", number_format); - } -} - -Value IREmitter::Unpack2_10_10_10(const AmdGpu::NumberFormat number_format, const U32& value) { - switch (number_format) { - case AmdGpu::NumberFormat::Unorm: - return Inst(Opcode::UnpackUnorm2_10_10_10, value); - case AmdGpu::NumberFormat::Snorm: - return Inst(Opcode::UnpackSnorm2_10_10_10, value); - case AmdGpu::NumberFormat::Uint: - return Inst(Opcode::UnpackUint2_10_10_10, value); - case AmdGpu::NumberFormat::Sint: - return Inst(Opcode::UnpackSint2_10_10_10, value); - default: - UNREACHABLE_MSG("Unsupported 2_10_10_10 number format: {}", number_format); - } -} - -Value IREmitter::Unpack10_11_11(const AmdGpu::NumberFormat number_format, const U32& value) { - switch (number_format) { - case AmdGpu::NumberFormat::Float: - return Inst(Opcode::UnpackUfloat10_11_11, value); - default: - UNREACHABLE_MSG("Unsupported 10_11_11 number format: {}", number_format); - } -} - -F32F64 IREmitter::FPMul(const F32F64& a, const F32F64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::F32: - return Inst(Opcode::FPMul32, a, b); - case Type::F64: - return Inst(Opcode::FPMul64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -F32F64 IREmitter::FPDiv(const F32F64& a, const F32F64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::F32: - return Inst(Opcode::FPDiv32, a, b); - case Type::F64: - return Inst(Opcode::FPDiv64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -F32F64 IREmitter::FPFma(const F32F64& a, const F32F64& b, const F32F64& c) { - if (a.Type() != b.Type() || a.Type() != c.Type()) { - UNREACHABLE_MSG("Mismatching types {}, {}, and {}", a.Type(), b.Type(), c.Type()); - } - switch (a.Type()) { - case Type::F32: - return Inst(Opcode::FPFma32, a, b, c); - case Type::F64: - return Inst(Opcode::FPFma64, a, b, c); - default: - ThrowInvalidType(a.Type()); - } -} - -F32F64 IREmitter::FPAbs(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPAbs32, value); - case Type::F64: - return Inst(Opcode::FPAbs64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPNeg(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPNeg32, value); - case Type::F64: - return Inst(Opcode::FPNeg64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPAbsNeg(const F32F64& value, bool abs, bool neg) { - F32F64 result{value}; - if (abs) { - result = FPAbs(result); - } - if (neg) { - result = FPNeg(result); - } - return result; -} - -F32 IREmitter::FPCos(const F32& value) { - return Inst(Opcode::FPCos, value); -} - -F32 IREmitter::FPSin(const F32& value) { - return Inst(Opcode::FPSin, value); -} - -F32 IREmitter::FPExp2(const F32& value) { - return Inst(Opcode::FPExp2, value); -} - -F32 IREmitter::FPLdexp(const F32& value, const U32& exp) { - return Inst(Opcode::FPLdexp, value, exp); -} - -F32 IREmitter::FPLog2(const F32& value) { - return Inst(Opcode::FPLog2, value); -} - -F32 IREmitter::FPPow(const F32& x, const F32& y) { - return Inst(Opcode::FPPow, x, y); -} - -F32F64 IREmitter::FPRecip(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPRecip32, value); - case Type::F64: - return Inst(Opcode::FPRecip64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPRecipSqrt(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPRecipSqrt32, value); - case Type::F64: - return Inst(Opcode::FPRecipSqrt64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32 IREmitter::FPSqrt(const F32& value) { - return Inst(Opcode::FPSqrt, value); -} - -F32F64 IREmitter::FPSaturate(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPSaturate32, value); - case Type::F64: - return Inst(Opcode::FPSaturate64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPClamp(const F32F64& value, const F32F64& min_value, const F32F64& max_value) { - if (value.Type() != min_value.Type() || value.Type() != max_value.Type()) { - UNREACHABLE_MSG("Mismatching types {}, {}, and {}", value.Type(), min_value.Type(), - max_value.Type()); - } - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPClamp32, value, min_value, max_value); - case Type::F64: - return Inst(Opcode::FPClamp64, value, min_value, max_value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPRoundEven(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPRoundEven32, value); - case Type::F64: - return Inst(Opcode::FPRoundEven64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPFloor(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPFloor32, value); - case Type::F64: - return Inst(Opcode::FPFloor64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPCeil(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPCeil32, value); - case Type::F64: - return Inst(Opcode::FPCeil64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPTrunc(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPTrunc32, value); - case Type::F64: - return Inst(Opcode::FPTrunc64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPFract(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPFract32, value); - case Type::F64: - return Inst(Opcode::FPFract64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -F32F64 IREmitter::FPFrexpSig(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPFrexpSig32, value); - case Type::F64: - return Inst(Opcode::FPFrexpSig64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32 IREmitter::FPFrexpExp(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPFrexpExp32, value); - case Type::F64: - return Inst(Opcode::FPFrexpExp64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U1 IREmitter::FPEqual(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdEqual32 : Opcode::FPUnordEqual32, lhs, rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdEqual64 : Opcode::FPUnordEqual64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPNotEqual(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdNotEqual32 : Opcode::FPUnordNotEqual32, lhs, rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdNotEqual64 : Opcode::FPUnordNotEqual64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPLessThan(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdLessThan32 : Opcode::FPUnordLessThan32, lhs, rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdLessThan64 : Opcode::FPUnordLessThan64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPGreaterThan(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdGreaterThan32 : Opcode::FPUnordGreaterThan32, lhs, - rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdGreaterThan64 : Opcode::FPUnordGreaterThan64, lhs, - rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPLessThanEqual(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdLessThanEqual32 : Opcode::FPUnordLessThanEqual32, - lhs, rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdLessThanEqual64 : Opcode::FPUnordLessThanEqual64, - lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPGreaterThanEqual(const F32F64& lhs, const F32F64& rhs, bool ordered) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(ordered ? Opcode::FPOrdGreaterThanEqual32 - : Opcode::FPUnordGreaterThanEqual32, - lhs, rhs); - case Type::F64: - return Inst(ordered ? Opcode::FPOrdGreaterThanEqual64 - : Opcode::FPUnordGreaterThanEqual64, - lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::FPIsNan(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPIsNan32, value); - case Type::F64: - return Inst(Opcode::FPIsNan64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U1 IREmitter::FPIsInf(const F32F64& value) { - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::FPIsInf32, value); - case Type::F64: - return Inst(Opcode::FPIsInf64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U1 IREmitter::FPCmpClass32(const F32& value, const U32& op) { - return Inst(Opcode::FPCmpClass32, value, op); -} - -U1 IREmitter::FPOrdered(const F32F64& lhs, const F32F64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - return LogicalAnd(LogicalNot(FPIsNan(lhs)), LogicalNot(FPIsNan(rhs))); -} - -U1 IREmitter::FPUnordered(const F32F64& lhs, const F32F64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - return LogicalOr(FPIsNan(lhs), FPIsNan(rhs)); -} - -F32F64 IREmitter::FPMax(const F32F64& lhs, const F32F64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - - switch (lhs.Type()) { - case Type::F32: - return Inst(Opcode::FPMax32, lhs, rhs); - case Type::F64: - return Inst(Opcode::FPMax64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -F32F64 IREmitter::FPMin(const F32F64& lhs, const F32F64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::F32: - return Inst(Opcode::FPMin32, lhs, rhs); - case Type::F64: - return Inst(Opcode::FPMin64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -F32F64 IREmitter::FPMinTri(const F32F64& a, const F32F64& b, const F32F64& c) { - return Inst(Opcode::FPMinTri32, a, b, c); -} - -F32F64 IREmitter::FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c) { - return Inst(Opcode::FPMaxTri32, a, b, c); -} - -F32F64 IREmitter::FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c) { - return Inst(Opcode::FPMedTri32, a, b, c); -} - -U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::IAdd32, a, b); - case Type::U64: - return Inst(Opcode::IAdd64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32U64 IREmitter::ISub(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::ISub32, a, b); - case Type::U64: - return Inst(Opcode::ISub64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32 IREmitter::IMulHi(const U32& a, const U32& b, bool is_signed) { - return Inst(is_signed ? Opcode::SMulHi : Opcode::UMulHi, a, b); -} - -U32U64 IREmitter::IMul(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::IMul32, a, b); - case Type::U64: - return Inst(Opcode::IMul64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32 IREmitter::IDiv(const U32& a, const U32& b, bool is_signed) { - return Inst(is_signed ? Opcode::SDiv32 : Opcode::UDiv32, a, b); -} - -U32 IREmitter::IMod(const U32& a, const U32& b, bool is_signed) { - return Inst(is_signed ? Opcode::SMod32 : Opcode::UMod32, a, b); -} - -U32U64 IREmitter::INeg(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::INeg32, value); - case Type::U64: - return Inst(Opcode::INeg64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32 IREmitter::IAbs(const U32& value) { - return Inst(Opcode::IAbs32, value); -} - -U32U64 IREmitter::ShiftLeftLogical(const U32U64& base, const U32& shift) { - if (shift.IsImmediate() && shift.U32() == 0) { - return base; - } - - switch (base.Type()) { - case Type::U32: - return Inst(Opcode::ShiftLeftLogical32, base, shift); - case Type::U64: - return Inst(Opcode::ShiftLeftLogical64, base, shift); - default: - ThrowInvalidType(base.Type()); - } -} - -U32U64 IREmitter::ShiftRightLogical(const U32U64& base, const U32& shift) { - if (shift.IsImmediate() && shift.U32() == 0) { - return base; - } - - switch (base.Type()) { - case Type::U32: - return Inst(Opcode::ShiftRightLogical32, base, shift); - case Type::U64: - return Inst(Opcode::ShiftRightLogical64, base, shift); - default: - ThrowInvalidType(base.Type()); - } -} - -U32U64 IREmitter::ShiftRightArithmetic(const U32U64& base, const U32& shift) { - if (shift.IsImmediate() && shift.U32() == 0) { - return base; - } - - switch (base.Type()) { - case Type::U32: - return Inst(Opcode::ShiftRightArithmetic32, base, shift); - case Type::U64: - return Inst(Opcode::ShiftRightArithmetic64, base, shift); - default: - ThrowInvalidType(base.Type()); - } -} - -U32U64 IREmitter::BitwiseAnd(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::BitwiseAnd32, a, b); - case Type::U64: - return Inst(Opcode::BitwiseAnd64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32U64 IREmitter::BitwiseOr(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::BitwiseOr32, a, b); - case Type::U64: - return Inst(Opcode::BitwiseOr64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32U64 IREmitter::BitwiseXor(const U32U64& a, const U32U64& b) { - if (a.Type() != b.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type()); - } - switch (a.Type()) { - case Type::U32: - return Inst(Opcode::BitwiseXor32, a, b); - case Type::U64: - return Inst(Opcode::BitwiseXor64, a, b); - default: - ThrowInvalidType(a.Type()); - } -} - -U32U64 IREmitter::BitFieldInsert(const U32U64& base, const U32U64& insert, const U32& offset, - const U32& count) { - if (base.Type() != insert.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", base.Type(), insert.Type()); - } - switch (base.Type()) { - case Type::U32: - return Inst(Opcode::BitFieldInsert32, base, insert, offset, count); - case Type::U64: - return Inst(Opcode::BitFieldInsert64, base, insert, offset, count); - default: - ThrowInvalidType(base.Type()); - } -} - -U32 IREmitter::BitFieldExtract(const U32& base, const U32& offset, const U32& count, - bool is_signed) { - return Inst(is_signed ? Opcode::BitFieldSExtract : Opcode::BitFieldUExtract, base, offset, - count); -} - -U32 IREmitter::BitReverse(const U32& value) { - return Inst(Opcode::BitReverse32, value); -} - -U32 IREmitter::BitCount(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::BitCount32, value); - case Type::U64: - return Inst(Opcode::BitCount64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32U64 IREmitter::BitwiseNot(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::BitwiseNot32, value); - case Type::U64: - return Inst(Opcode::BitwiseNot64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32 IREmitter::MaskedBitCount(const U32& value, const U32& addend, bool hi) { - return Inst(Opcode::MaskedBitCount32, value, addend, Imm1(hi)); -} - -U32 IREmitter::FindSMsb(const U32& value) { - return Inst(Opcode::FindSMsb32, value); -} - -U32 IREmitter::FindUMsb(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::FindUMsb32, value); - case Type::U64: - return Inst(Opcode::FindUMsb64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32 IREmitter::FindILsb(const U32U64& value) { - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::FindILsb32, value); - case Type::U64: - return Inst(Opcode::FindILsb64, value); - default: - ThrowInvalidType(value.Type()); - } -} - -U32 IREmitter::SMin(const U32& a, const U32& b) { - return Inst(Opcode::SMin32, a, b); -} - -U32 IREmitter::UMin(const U32& a, const U32& b) { - return Inst(Opcode::UMin32, a, b); -} - -U32 IREmitter::IMin(const U32& a, const U32& b, bool is_signed) { - return is_signed ? SMin(a, b) : UMin(a, b); -} - -U32 IREmitter::SMax(const U32& a, const U32& b) { - return Inst(Opcode::SMax32, a, b); -} - -U32 IREmitter::UMax(const U32& a, const U32& b) { - return Inst(Opcode::UMax32, a, b); -} - -U32 IREmitter::IMax(const U32& a, const U32& b, bool is_signed) { - return is_signed ? SMax(a, b) : UMax(a, b); -} - -U32 IREmitter::SMinTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::SMinTri32, a, b, c); -} - -U32 IREmitter::UMinTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::UMinTri32, a, b, c); -} - -U32 IREmitter::IMinTri(const U32& a, const U32& b, const U32& c, bool is_signed) { - return is_signed ? SMinTri(a, b, c) : UMinTri(a, b, c); -} - -U32 IREmitter::SMaxTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::SMaxTri32, a, b, c); -} - -U32 IREmitter::UMaxTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::UMaxTri32, a, b, c); -} - -U32 IREmitter::IMaxTri(const U32& a, const U32& b, const U32& c, bool is_signed) { - return is_signed ? SMaxTri(a, b, c) : UMaxTri(a, b, c); -} - -U32 IREmitter::SMedTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::SMedTri32, a, b, c); -} - -U32 IREmitter::UMedTri(const U32& a, const U32& b, const U32& c) { - return Inst(Opcode::UMedTri32, a, b, c); -} - -U32 IREmitter::IMedTri(const U32& a, const U32& b, const U32& c, bool is_signed) { - return is_signed ? SMedTri(a, b, c) : UMedTri(a, b, c); -} - -U32 IREmitter::SClamp(const U32& value, const U32& min, const U32& max) { - return Inst(Opcode::SClamp32, value, min, max); -} - -U32 IREmitter::UClamp(const U32& value, const U32& min, const U32& max) { - return Inst(Opcode::UClamp32, value, min, max); -} - -U1 IREmitter::ILessThan(const U32U64& lhs, const U32U64& rhs, bool is_signed) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SLessThan32 : Opcode::ULessThan32, lhs, rhs); - case Type::U64: - return Inst(is_signed ? Opcode::SLessThan64 : Opcode::ULessThan64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::IEqual(const U32U64& lhs, const U32U64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(Opcode::IEqual32, lhs, rhs); - case Type::U64: - return Inst(Opcode::IEqual64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::ILessThanEqual(const U32U64& lhs, const U32U64& rhs, bool is_signed) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SLessThanEqual32 : Opcode::ULessThanEqual32, lhs, rhs); - case Type::U64: - return Inst(is_signed ? Opcode::SLessThanEqual64 : Opcode::ULessThanEqual64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::IGreaterThan(const U32U64& lhs, const U32U64& rhs, bool is_signed) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SGreaterThan32 : Opcode::UGreaterThan32, lhs, rhs); - case Type::U64: - return Inst(is_signed ? Opcode::SGreaterThan64 : Opcode::UGreaterThan64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::INotEqual(const U32U64& lhs, const U32U64& rhs) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(Opcode::INotEqual32, lhs, rhs); - case Type::U64: - return Inst(Opcode::INotEqual64, lhs, rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::IGreaterThanEqual(const U32U64& lhs, const U32U64& rhs, bool is_signed) { - if (lhs.Type() != rhs.Type()) { - UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type()); - } - switch (lhs.Type()) { - case Type::U32: - return Inst(is_signed ? Opcode::SGreaterThanEqual32 : Opcode::UGreaterThanEqual32, lhs, - rhs); - case Type::U64: - return Inst(is_signed ? Opcode::SGreaterThanEqual64 : Opcode::UGreaterThanEqual64, lhs, - rhs); - default: - ThrowInvalidType(lhs.Type()); - } -} - -U1 IREmitter::LogicalOr(const U1& a, const U1& b) { - return Inst(Opcode::LogicalOr, a, b); -} - -U1 IREmitter::LogicalAnd(const U1& a, const U1& b) { - return Inst(Opcode::LogicalAnd, a, b); -} - -U1 IREmitter::LogicalXor(const U1& a, const U1& b) { - return Inst(Opcode::LogicalXor, a, b); -} - -U1 IREmitter::LogicalNot(const U1& value) { - return Inst(Opcode::LogicalNot, value); -} - -U32U64 IREmitter::ConvertFToS(size_t bitsize, const F32F64& value) { - switch (bitsize) { - case 32: - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::ConvertS32F32, value); - case Type::F64: - return Inst(Opcode::ConvertS32F64, value); - default: - ThrowInvalidType(value.Type()); - } - default: - break; - } - UNREACHABLE_MSG("Invalid destination bitsize {}", bitsize); -} - -U32U64 IREmitter::ConvertFToU(size_t bitsize, const F32F64& value) { - switch (bitsize) { - case 32: - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::ConvertU32F32, value); - default: - ThrowInvalidType(value.Type()); - } - default: - UNREACHABLE_MSG("Invalid destination bitsize {}", bitsize); - } -} - -U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F32F64& value) { - return is_signed ? ConvertFToS(bitsize, value) : ConvertFToU(bitsize, value); -} - -F32F64 IREmitter::ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) { - switch (dest_bitsize) { - case 32: - switch (src_bitsize) { - case 32: - return Inst(Opcode::ConvertF32S32, value); - default: - break; - } - case 64: - switch (src_bitsize) { - case 32: - return Inst(Opcode::ConvertF64S32, value); - default: - break; - } - default: - break; - } - UNREACHABLE_MSG("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize); -} - -F32F64 IREmitter::ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value) { - switch (dest_bitsize) { - case 32: - switch (src_bitsize) { - case 16: - return Inst(Opcode::ConvertF32U16, value); - case 32: - return Inst(Opcode::ConvertF32U32, value); - default: - break; - } - case 64: - switch (src_bitsize) { - case 32: - return Inst(Opcode::ConvertF64U32, value); - default: - break; - } - default: - break; - } - UNREACHABLE_MSG("Invalid bit size combination dst={} src={}", dest_bitsize, src_bitsize); -} - -F32F64 IREmitter::ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed, - const Value& value) { - return is_signed ? ConvertSToF(dest_bitsize, src_bitsize, value) - : ConvertUToF(dest_bitsize, src_bitsize, value); -} - -U8U16U32U64 IREmitter::UConvert(size_t result_bitsize, const U8U16U32U64& value) { - switch (result_bitsize) { - case 8: - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::ConvertU8U32, value); - default: - break; - } - case 16: - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::ConvertU16U32, value); - default: - break; - } - case 32: - switch (value.Type()) { - case Type::U8: - return Inst(Opcode::ConvertU32U8, value); - case Type::U16: - return Inst(Opcode::ConvertU32U16, value); - default: - break; - } - case 64: - switch (value.Type()) { - case Type::U32: - return Inst(Opcode::ConvertU64U32, value); - default: - break; - } - default: - break; - } - UNREACHABLE_MSG("Conversion from {} to {} bits", value.Type(), result_bitsize); -} - -U8U16U32U64 IR::IREmitter::SConvert(size_t result_bitsize, const U8U16U32U64& value) { - switch (result_bitsize) { - case 32: - switch (value.Type()) { - case Type::U8: - return Inst(Opcode::ConvertS32S8, value); - case Type::U16: - return Inst(Opcode::ConvertS32S16, value); - default: - break; - } - default: - break; - } - UNREACHABLE_MSG("Signed Conversion from {} to {} bits", value.Type(), result_bitsize); -} - -F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value) { - switch (result_bitsize) { - case 16: - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::ConvertF16F32, value); - default: - break; - } - case 32: - switch (value.Type()) { - case Type::F16: - return Inst(Opcode::ConvertF32F16, value); - case Type::F64: - return Inst(Opcode::ConvertF32F64, value); - default: - break; - } - case 64: - switch (value.Type()) { - case Type::F32: - return Inst(Opcode::ConvertF64F32, value); - default: - break; - } - default: - break; - } - UNREACHABLE_MSG("Conversion from {} to {} bits", value.Type(), result_bitsize); -} - -Value IREmitter::ImageAtomicIAdd(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicIAdd32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicSMin(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicSMin32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicUMin(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicUMin32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicIMin(const Value& handle, const Value& coords, const Value& value, - bool is_signed, TextureInstInfo info) { - return is_signed ? ImageAtomicSMin(handle, coords, value, info) - : ImageAtomicUMin(handle, coords, value, info); -} - -Value IREmitter::ImageAtomicSMax(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicSMax32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicUMax(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicUMax32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicFMax(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicFMax32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicFMin(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicFMin32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicIMax(const Value& handle, const Value& coords, const Value& value, - bool is_signed, TextureInstInfo info) { - return is_signed ? ImageAtomicSMax(handle, coords, value, info) - : ImageAtomicUMax(handle, coords, value, info); -} - -Value IREmitter::ImageAtomicInc(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicInc32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicDec(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicDec32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicAnd(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicAnd32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicOr(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicOr32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicXor(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicXor32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicExchange(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info) { - return Inst(Opcode::ImageAtomicExchange32, Flags{info}, handle, coords, value); -} - -Value IREmitter::ImageAtomicCmpSwap(const Value& handle, const Value& coords, const Value& value, - const Value& cmp_value, TextureInstInfo info) { - return Inst(Opcode::ImageAtomicCmpSwap32, Flags{info}, handle, coords, value, cmp_value); -} - -Value IREmitter::ImageHandle(const Value& tsharp_low, const Value& tsharp_high) { - return Inst(Opcode::ImageHandle, tsharp_low, tsharp_high); -} - -Value IREmitter::ImageSampleRaw(const Value& image_handle, const Value& sampler_handle, - const Value& address1, const Value& address2, const Value& address3, - const Value& address4, TextureInstInfo info) { - return Inst(Opcode::ImageSampleRaw, Flags{info}, image_handle, sampler_handle, address1, - address2, address3, address4); -} - -Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& coords, const F32& bias, - const Value& offset, TextureInstInfo info) { - return Inst(Opcode::ImageSampleImplicitLod, Flags{info}, handle, coords, bias, offset); -} - -Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod, - const Value& offset, TextureInstInfo info) { - return Inst(Opcode::ImageSampleExplicitLod, Flags{info}, handle, coords, lod, offset); -} - -Value IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, - const F32& dref, const F32& bias, const Value& offset, - TextureInstInfo info) { - return Inst(Opcode::ImageSampleDrefImplicitLod, Flags{info}, handle, coords, dref, bias, - offset); -} - -Value IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, - const F32& dref, const F32& lod, const Value& offset, - TextureInstInfo info) { - return Inst(Opcode::ImageSampleDrefExplicitLod, Flags{info}, handle, coords, dref, lod, offset); -} - -Value IREmitter::ImageGather(const Value& handle, const Value& coords, const Value& offset, - TextureInstInfo info) { - return Inst(Opcode::ImageGather, Flags{info}, handle, coords, offset); -} - -Value IREmitter::ImageGatherDref(const Value& handle, const Value& coords, const Value& offset, - const F32& dref, TextureInstInfo info) { - return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref); -} - -Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, - const IR::U1& skip_mips, TextureInstInfo info) { - return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips); -} - -Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) { - return Inst(Opcode::ImageQueryLod, Flags{info}, handle, coords); -} - -Value IREmitter::ImageGradient(const Value& handle, const Value& coords, - const Value& derivatives_dx, const Value& derivatives_dy, - const Value& offset, const F32& lod_clamp, TextureInstInfo info) { - return Inst(Opcode::ImageGradient, Flags{info}, handle, coords, derivatives_dx, derivatives_dy, - offset, lod_clamp); -} - -Value IREmitter::ImageRead(const Value& handle, const Value& coords, const U32& lod, - const U32& multisampling, TextureInstInfo info) { - return Inst(Opcode::ImageRead, Flags{info}, handle, coords, lod, multisampling); -} - -void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32& lod, - const U32& multisampling, const Value& color, TextureInstInfo info) { - Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, multisampling, color); -} - -[[nodiscard]] F32 IREmitter::CubeFaceIndex(const Value& x, const Value& y, const Value& z) { - return Inst(Opcode::CubeFaceIndex, x, y, z); -} - -[[nodiscard]] F32 IREmitter::CubeFaceCoordS(const Value& x, const Value& y, const Value& z) { - return Inst(Opcode::CubeFaceCoordS, x, y, z); -} - -[[nodiscard]] F32 IREmitter::CubeFaceCoordT(const Value& x, const Value& y, const Value& z) { - return Inst(Opcode::CubeFaceCoordT, x, y, z); -} - -[[nodiscard]] F32 IREmitter::CubeFaceMajorAxis(const Value& x, const Value& y, const Value& z) { - return Inst(Opcode::CubeFaceMajorAxis, x, y, z); -} - -// Debug print maps to SPIRV's NonSemantic DebugPrintf instruction -// Renderdoc will hook in its own implementation of the SPIRV instruction -// Renderdoc accepts format specifiers, e.g. %u, listed here: -// https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/debug_printf.md -// -// fmt must be a string literal (pointer is shallow copied into a Value) -// Example usage: -// ir.DebugPrint("invocation xyz: (%u, %u, %u)", -// {ir.GetVectorReg(IR::VectorReg::V0), -// ir.GetVectorReg(IR::VectorReg::V1), -// ir.GetVectorReg(IR::VectorReg::V2)}); -void IREmitter::DebugPrint(const char* fmt, boost::container::small_vector format_args) { - std::array args; - - ASSERT_MSG(format_args.size() < DEBUGPRINT_NUM_FORMAT_ARGS, - "DebugPrint only supports up to {} format args", DEBUGPRINT_NUM_FORMAT_ARGS); - - for (int i = 0; i < format_args.size(); i++) { - args[i] = format_args[i]; - } - - for (int i = format_args.size(); i < DEBUGPRINT_NUM_FORMAT_ARGS; i++) { - args[i] = Inst(Opcode::Void); - } - - IR::Value fmt_val{fmt}; - - DebugPrintFlags flags; - flags.num_args.Assign(format_args.size()); - Inst(Opcode::DebugPrint, Flags{flags}, fmt_val, args[0], args[1], args[2], args[3]); -} - -void IREmitter::EmitVertex() { - Inst(Opcode::EmitVertex); -} - -void IREmitter::EmitPrimitive() { - Inst(Opcode::EmitPrimitive); -} - -U64 IREmitter::Memtime() { - return Inst(Opcode::Memtime); -} - -} // namespace Shader::IR diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h deleted file mode 100644 index b9ebbb3..0000000 --- a/src/shader_recompiler/ir/ir_emitter.h +++ /dev/null @@ -1,449 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "shader_recompiler/ir/attribute.h" -#include "shader_recompiler/ir/basic_block.h" -#include "shader_recompiler/ir/condition.h" -#include "shader_recompiler/ir/patch.h" -#include "shader_recompiler/ir/value.h" - -namespace Shader::IR { - -class IREmitter { -public: - explicit IREmitter() = default; - explicit IREmitter(Block& block_) : block{&block_}, insertion_point{block->end()} {} - explicit IREmitter(Block& block_, Block::iterator insertion_point_) - : block{&block_}, insertion_point{insertion_point_} {} - - [[nodiscard]] U1 Imm1(bool value) const; - [[nodiscard]] U8 Imm8(u8 value) const; - [[nodiscard]] U16 Imm16(u16 value) const; - [[nodiscard]] U32 Imm32(u32 value) const; - [[nodiscard]] U32 Imm32(s32 value) const; - [[nodiscard]] F32 Imm32(f32 value) const; - [[nodiscard]] U64 Imm64(u64 value) const; - [[nodiscard]] U64 Imm64(s64 value) const; - [[nodiscard]] F64 Imm64(f64 value) const; - - template - [[nodiscard]] Dest BitCast(const Source& value); - - U1 ConditionRef(const U1& value); - - void Prologue(); - void Epilogue(); - void Discard(); - void Discard(const U1& cond); - void DebugPrint(const char* fmt, boost::container::small_vector args); - - void Barrier(); - void WorkgroupMemoryBarrier(); - void DeviceMemoryBarrier(); - - [[nodiscard]] U32 GetUserData(IR::ScalarReg reg); - - template - [[nodiscard]] T GetScalarReg(IR::ScalarReg reg); - template - [[nodiscard]] T GetVectorReg(IR::VectorReg reg); - void SetScalarReg(IR::ScalarReg reg, const U32F32& value); - void SetVectorReg(IR::VectorReg reg, const U32F32& value); - - [[nodiscard]] Value GetVirtualReg(IR::VirtualReg reg); - void SetVirtualReg(IR::VirtualReg reg, const Value& value); - - [[nodiscard]] U1 GetGotoVariable(u32 id); - void SetGotoVariable(u32 id, const U1& value); - - [[nodiscard]] U1 GetScc(); - [[nodiscard]] U1 GetExec(); - [[nodiscard]] U32 GetVccLo(); - [[nodiscard]] U32 GetVccHi(); - [[nodiscard]] U32 GetM0(); - void SetScc(const U1& value); - void SetExec(const U1& value); - void SetVccLo(const U32& value); - void SetVccHi(const U32& value); - void SetM0(const U32& value); - - [[nodiscard]] U1 Condition(IR::Condition cond); - - [[nodiscard]] F32 GetAttribute(Attribute attribute, u32 comp = 0, u32 index = 0); - [[nodiscard]] U1 GetAttributeU1(Attribute attribute, u32 comp = 0); - [[nodiscard]] U32 GetAttributeU32(Attribute attribute, u32 comp = 0); - void SetAttribute(Attribute attribute, const F32& value, u32 comp = 0); - - [[nodiscard]] F32 GetTessGenericAttribute(const U32& vertex_index, const U32& attr_index, - const U32& comp_index); - void SetTcsGenericAttribute(const F32& value, const U32& attr_index, const U32& comp_index); - - [[nodiscard]] F32 ReadTcsGenericOuputAttribute(const U32& vertex_index, const U32& attr_index, - const U32& comp_index); - - [[nodiscard]] U32 GetPcLo(const U32& pc); - - [[nodiscard]] F32 GetPatch(Patch patch); - void SetPatch(Patch patch, const F32& value); - - [[nodiscard]] Value LoadShared(int bit_size, bool is_signed, const U32& offset, - bool is_gds = false); - void WriteShared(int bit_size, const Value& value, const U32& offset, bool is_gds = false); - - [[nodiscard]] U32U64 SharedAtomicIAdd(const U32& address, const U32U64& data, bool is_gds); - [[nodiscard]] U32U64 SharedAtomicISub(const U32& address, const U32U64& data, bool is_gds); - [[nodiscard]] U32U64 SharedAtomicIMin(const U32& address, const U32U64& data, bool is_signed, - bool is_gds); - [[nodiscard]] U32U64 SharedAtomicIMax(const U32& address, const U32U64& data, bool is_signed, - bool is_gds); - [[nodiscard]] U32U64 SharedAtomicAnd(const U32& address, const U32U64& data, bool is_gds); - [[nodiscard]] U32U64 SharedAtomicOr(const U32& address, const U32U64& data, bool is_gds); - [[nodiscard]] U32U64 SharedAtomicXor(const U32& address, const U32U64& data, bool is_gds); - [[nodiscard]] U32U64 SharedAtomicCmpSwap(const U32& address, const U32U64& value, - const U32U64& cmp_value, bool is_gds); - - template - [[nodiscard]] T SharedAtomicInc(const U32& address, bool is_gds); - template - [[nodiscard]] T SharedAtomicDec(const U32& address, bool is_gds); - - [[nodiscard]] U32 ReadConst(const Value& base, const U32& offset); - [[nodiscard]] U32 ReadConstBuffer(const Value& handle, const U32& index, BufferInstInfo info); - - [[nodiscard]] U8 LoadBufferU8(const Value& handle, const Value& address, BufferInstInfo info); - [[nodiscard]] U16 LoadBufferU16(const Value& handle, const Value& address, BufferInstInfo info); - [[nodiscard]] Value LoadBufferU32(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info); - [[nodiscard]] U64 LoadBufferU64(const Value& handle, const Value& address, BufferInstInfo info); - [[nodiscard]] Value LoadBufferF32(int num_dwords, const Value& handle, const Value& address, - BufferInstInfo info); - [[nodiscard]] Value LoadBufferFormat(const Value& handle, const Value& address, - BufferInstInfo info); - void StoreBufferU8(const Value& handle, const Value& address, const U8& data, - BufferInstInfo info); - void StoreBufferU16(const Value& handle, const Value& address, const U16& data, - BufferInstInfo info); - void StoreBufferU32(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info); - void StoreBufferU64(const Value& handle, const Value& address, const U64& data, - BufferInstInfo info); - void StoreBufferF32(int num_dwords, const Value& handle, const Value& address, - const Value& data, BufferInstInfo info); - void StoreBufferFormat(const Value& handle, const Value& address, const Value& data, - BufferInstInfo info); - - [[nodiscard]] Value BufferAtomicIAdd(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicISub(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicIMin(const Value& handle, const Value& address, - const Value& value, bool is_signed, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicFMin(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicIMax(const Value& handle, const Value& address, - const Value& value, bool is_signed, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicFMax(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicInc(const Value& handle, const Value& address, - BufferInstInfo info); - [[nodiscard]] Value BufferAtomicDec(const Value& handle, const Value& address, - BufferInstInfo info); - [[nodiscard]] Value BufferAtomicAnd(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicOr(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicXor(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicSwap(const Value& handle, const Value& address, - const Value& value, BufferInstInfo info); - [[nodiscard]] Value BufferAtomicCmpSwap(const Value& handle, const Value& address, - const Value& value, const Value& cmp_value, - BufferInstInfo info); - [[nodiscard]] Value BufferAtomicFCmpSwap(const Value& handle, const Value& address, - const Value& value, const Value& cmp_value, - BufferInstInfo info); - - [[nodiscard]] U32 DataAppend(const U32& gds_dw_offset); - [[nodiscard]] U32 DataConsume(const U32& gds_dw_offset); - [[nodiscard]] U32 LaneId(); - [[nodiscard]] U32 WarpId(); - [[nodiscard]] U32 QuadBroadcast(const U32& value, const U32& index); - [[nodiscard]] U32 Shuffle(const U32& value, const U32& index); - [[nodiscard]] U32 ShuffleXor(const U32& value, const U32& mask); - [[nodiscard]] U32 ReadFirstLane(const U32& value, const U1& exec); - [[nodiscard]] U32 ReadLane(const U32& value, const U32& lane); - [[nodiscard]] U32 WriteLane(const U32& value, const U32& write_value, const U32& lane); - [[nodiscard]] U64 Ballot(const U1& bit); - [[nodiscard]] U32 BallotFindLsb(const U64& mask); - [[nodiscard]] U1 InverseBallot(const U64& mask); - [[nodiscard]] U1 GroupAny(const U1& bit); - - [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); - [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); - [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3, - const Value& e4); - [[nodiscard]] Value CompositeConstruct(std::span values); - - [[nodiscard]] Value CompositeExtract(const Value& vector, size_t element); - [[nodiscard]] Value CompositeInsert(const Value& vector, const Value& object, size_t element); - - [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1); - [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1, size_t comp2); - [[nodiscard]] Value CompositeShuffle(const Value& vector1, const Value& vector2, size_t comp0, - size_t comp1, size_t comp2, size_t comp3); - - [[nodiscard]] Value Select(const U1& condition, const Value& true_value, - const Value& false_value); - - [[nodiscard]] U64 PackUint2x32(const Value& vector); - [[nodiscard]] Value UnpackUint2x32(const U64& value); - [[nodiscard]] F64 PackDouble2x32(const Value& vector); - [[nodiscard]] Value UnpackDouble2x32(const F64& value); - - [[nodiscard]] U32 Pack2x16(AmdGpu::NumberFormat number_format, const Value& vector); - [[nodiscard]] Value Unpack2x16(AmdGpu::NumberFormat number_format, const U32& value); - - [[nodiscard]] U32 Pack4x8(AmdGpu::NumberFormat number_format, const Value& vector); - [[nodiscard]] Value Unpack4x8(AmdGpu::NumberFormat number_format, const U32& value); - - [[nodiscard]] U32 Pack10_11_11(AmdGpu::NumberFormat number_format, const Value& vector); - [[nodiscard]] Value Unpack10_11_11(AmdGpu::NumberFormat number_format, const U32& value); - - [[nodiscard]] U32 Pack2_10_10_10(AmdGpu::NumberFormat number_format, const Value& vector); - [[nodiscard]] Value Unpack2_10_10_10(AmdGpu::NumberFormat number_format, const U32& value); - - [[nodiscard]] F32F64 FPAdd(const F32F64& a, const F32F64& b); - [[nodiscard]] F32F64 FPSub(const F32F64& a, const F32F64& b); - [[nodiscard]] F32F64 FPMul(const F32F64& a, const F32F64& b); - [[nodiscard]] F32F64 FPDiv(const F32F64& a, const F32F64& b); - [[nodiscard]] F32F64 FPFma(const F32F64& a, const F32F64& b, const F32F64& c); - - [[nodiscard]] F32F64 FPAbs(const F32F64& value); - [[nodiscard]] F32F64 FPNeg(const F32F64& value); - [[nodiscard]] F32F64 FPAbsNeg(const F32F64& value, bool abs, bool neg); - - [[nodiscard]] F32 FPCos(const F32& value); - [[nodiscard]] F32 FPSin(const F32& value); - [[nodiscard]] F32 FPExp2(const F32& value); - [[nodiscard]] F32 FPLog2(const F32& value); - [[nodiscard]] F32 FPPow(const F32& x, const F32& y); - [[nodiscard]] F32 FPLdexp(const F32& value, const U32& exp); - [[nodiscard]] F32F64 FPRecip(const F32F64& value); - [[nodiscard]] F32F64 FPRecipSqrt(const F32F64& value); - [[nodiscard]] F32 FPSqrt(const F32& value); - [[nodiscard]] F32F64 FPSaturate(const F32F64& value); - [[nodiscard]] F32F64 FPClamp(const F32F64& value, const F32F64& min_value, - const F32F64& max_value); - [[nodiscard]] F32F64 FPRoundEven(const F32F64& value); - [[nodiscard]] F32F64 FPFloor(const F32F64& value); - [[nodiscard]] F32F64 FPCeil(const F32F64& value); - [[nodiscard]] F32F64 FPTrunc(const F32F64& value); - [[nodiscard]] F32F64 FPFract(const F32F64& value); - [[nodiscard]] F32F64 FPFrexpSig(const F32F64& value); - [[nodiscard]] U32 FPFrexpExp(const F32F64& value); - - [[nodiscard]] U1 FPEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPNotEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPLessThanEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPGreaterThanEqual(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPLessThan(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPGreaterThan(const F32F64& lhs, const F32F64& rhs, bool ordered = true); - [[nodiscard]] U1 FPIsNan(const F32F64& value); - [[nodiscard]] U1 FPIsInf(const F32F64& value); - [[nodiscard]] U1 FPCmpClass32(const F32& value, const U32& op); - [[nodiscard]] U1 FPOrdered(const F32F64& lhs, const F32F64& rhs); - [[nodiscard]] U1 FPUnordered(const F32F64& lhs, const F32F64& rhs); - [[nodiscard]] F32F64 FPMax(const F32F64& lhs, const F32F64& rhs); - [[nodiscard]] F32F64 FPMin(const F32F64& lhs, const F32F64& rhs); - [[nodiscard]] F32F64 FPMinTri(const F32F64& a, const F32F64& b, const F32F64& c); - [[nodiscard]] F32F64 FPMaxTri(const F32F64& a, const F32F64& b, const F32F64& c); - [[nodiscard]] F32F64 FPMedTri(const F32F64& a, const F32F64& b, const F32F64& c); - - [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); - [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); - [[nodiscard]] U32 IMulHi(const U32& a, const U32& b, bool is_signed = false); - [[nodiscard]] U32U64 IMul(const U32U64& a, const U32U64& b); - [[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false); - [[nodiscard]] U32 IMod(const U32& a, const U32& b, bool is_signed = false); - [[nodiscard]] U32U64 INeg(const U32U64& value); - [[nodiscard]] U32 IAbs(const U32& value); - [[nodiscard]] U32U64 ShiftLeftLogical(const U32U64& base, const U32& shift); - [[nodiscard]] U32U64 ShiftRightLogical(const U32U64& base, const U32& shift); - [[nodiscard]] U32U64 ShiftRightArithmetic(const U32U64& base, const U32& shift); - [[nodiscard]] U32U64 BitwiseAnd(const U32U64& a, const U32U64& b); - [[nodiscard]] U32U64 BitwiseOr(const U32U64& a, const U32U64& b); - [[nodiscard]] U32U64 BitwiseXor(const U32U64& a, const U32U64& b); - [[nodiscard]] U32U64 BitFieldInsert(const U32U64& base, const U32U64& insert, const U32& offset, - const U32& count); - [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count, - bool is_signed = false); - [[nodiscard]] U32 BitReverse(const U32& value); - [[nodiscard]] U32 BitCount(const U32U64& value); - [[nodiscard]] U32U64 BitwiseNot(const U32U64& value); - [[nodiscard]] U32 MaskedBitCount(const U32& value, const U32& addend, bool hi); - - [[nodiscard]] U32 FindSMsb(const U32& value); - [[nodiscard]] U32 FindUMsb(const U32U64& value); - [[nodiscard]] U32 FindILsb(const U32U64& value); - [[nodiscard]] U32 SMin(const U32& a, const U32& b); - [[nodiscard]] U32 UMin(const U32& a, const U32& b); - [[nodiscard]] U32 IMin(const U32& a, const U32& b, bool is_signed); - [[nodiscard]] U32 SMax(const U32& a, const U32& b); - [[nodiscard]] U32 UMax(const U32& a, const U32& b); - [[nodiscard]] U32 IMax(const U32& a, const U32& b, bool is_signed); - [[nodiscard]] U32 SMinTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 UMinTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 IMinTri(const U32& a, const U32& b, const U32& c, bool is_signed); - [[nodiscard]] U32 SMaxTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 UMaxTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 IMaxTri(const U32& a, const U32& b, const U32& c, bool is_signed); - [[nodiscard]] U32 SMedTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 UMedTri(const U32& a, const U32& b, const U32& c); - [[nodiscard]] U32 IMedTri(const U32& a, const U32& b, const U32& c, bool is_signed); - [[nodiscard]] U32 SClamp(const U32& value, const U32& min, const U32& max); - [[nodiscard]] U32 UClamp(const U32& value, const U32& min, const U32& max); - - [[nodiscard]] U1 ILessThan(const U32U64& lhs, const U32U64& rhs, bool is_signed); - [[nodiscard]] U1 IEqual(const U32U64& lhs, const U32U64& rhs); - [[nodiscard]] U1 ILessThanEqual(const U32U64& lhs, const U32U64& rhs, bool is_signed); - [[nodiscard]] U1 IGreaterThan(const U32U64& lhs, const U32U64& rhs, bool is_signed); - [[nodiscard]] U1 INotEqual(const U32U64& lhs, const U32U64& rhs); - [[nodiscard]] U1 IGreaterThanEqual(const U32U64& lhs, const U32U64& rhs, bool is_signed); - - [[nodiscard]] U1 LogicalOr(const U1& a, const U1& b); - [[nodiscard]] U1 LogicalAnd(const U1& a, const U1& b); - [[nodiscard]] U1 LogicalXor(const U1& a, const U1& b); - [[nodiscard]] U1 LogicalNot(const U1& value); - - [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F32F64& value); - [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F32F64& value); - [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F32F64& value); - [[nodiscard]] F32F64 ConvertSToF(size_t dest_bitsize, size_t src_bitsize, const Value& value); - [[nodiscard]] F32F64 ConvertUToF(size_t dest_bitsize, size_t src_bitsize, const Value& value); - [[nodiscard]] F32F64 ConvertIToF(size_t dest_bitsize, size_t src_bitsize, bool is_signed, - const Value& value); - - [[nodiscard]] U8U16U32U64 UConvert(size_t result_bitsize, const U8U16U32U64& value); - [[nodiscard]] U8U16U32U64 SConvert(size_t result_bitsize, const U8U16U32U64& value); - [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value); - - [[nodiscard]] Value ImageAtomicIAdd(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicSMin(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicUMin(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicIMin(const Value& handle, const Value& coords, - const Value& value, bool is_signed, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicSMax(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicUMax(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicFMax(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicFMin(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicIMax(const Value& handle, const Value& coords, - const Value& value, bool is_signed, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicInc(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info); - [[nodiscard]] Value ImageAtomicDec(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info); - [[nodiscard]] Value ImageAtomicAnd(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info); - [[nodiscard]] Value ImageAtomicOr(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info); - [[nodiscard]] Value ImageAtomicXor(const Value& handle, const Value& coords, const Value& value, - TextureInstInfo info); - [[nodiscard]] Value ImageAtomicExchange(const Value& handle, const Value& coords, - const Value& value, TextureInstInfo info); - [[nodiscard]] Value ImageAtomicCmpSwap(const Value& handle, const Value& coords, - const Value& value, const Value& cmp_value, - TextureInstInfo info); - - [[nodiscard]] Value ImageHandle(const Value& tsharp_low, const Value& tsharp_high); - - [[nodiscard]] Value ImageSampleRaw(const Value& handle, const Value& sampler_handle, - const Value& address1, const Value& address2, - const Value& address3, const Value& address4, - TextureInstInfo info); - - [[nodiscard]] Value ImageSampleImplicitLod(const Value& handle, const Value& body, - const F32& bias, const Value& offset, - TextureInstInfo info); - - [[nodiscard]] Value ImageSampleExplicitLod(const Value& handle, const Value& body, - const F32& lod, const Value& offset, - TextureInstInfo info); - - [[nodiscard]] Value ImageSampleDrefImplicitLod(const Value& handle, const Value& body, - const F32& dref, const F32& bias, - const Value& offset, TextureInstInfo info); - - [[nodiscard]] Value ImageSampleDrefExplicitLod(const Value& handle, const Value& body, - const F32& dref, const F32& lod, - const Value& offset, TextureInstInfo info); - - [[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod, - const U1& skip_mips, TextureInstInfo info); - - [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, - TextureInstInfo info); - [[nodiscard]] Value ImageGather(const Value& handle, const Value& coords, const Value& offset, - TextureInstInfo info); - [[nodiscard]] Value ImageGatherDref(const Value& handle, const Value& coords, - const Value& offset, const F32& dref, TextureInstInfo info); - [[nodiscard]] Value ImageGradient(const Value& handle, const Value& coords, - const Value& derivatives_dx, const Value& derivatives_dy, - const Value& offset, const F32& lod_clamp, - TextureInstInfo info); - [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, const U32& lod, - const U32& multisampling, TextureInstInfo info); - void ImageWrite(const Value& handle, const Value& coords, const U32& lod, - const U32& multisampling, const Value& color, TextureInstInfo info); - - [[nodiscard]] F32 CubeFaceIndex(const Value& x, const Value& y, const Value& z); - [[nodiscard]] F32 CubeFaceCoordS(const Value& x, const Value& y, const Value& z); - [[nodiscard]] F32 CubeFaceCoordT(const Value& x, const Value& y, const Value& z); - [[nodiscard]] F32 CubeFaceMajorAxis(const Value& x, const Value& y, const Value& z); - - void EmitVertex(); - void EmitPrimitive(); - U64 Memtime(); - -private: - Block* block; - IR::Block::iterator insertion_point; - - template - T Inst(Opcode op, Args... args) { - auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})}; - return T{Value{&*it}}; - } - - template - requires(sizeof(T) <= sizeof(u64) && std::is_trivially_copyable_v) - struct Flags { - Flags() = default; - Flags(T proxy_) : proxy{proxy_} {} - - T proxy; - }; - - template - T Inst(Opcode op, Flags flags, Args... args) { - u64 raw_flags{}; - std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy)); - auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)}; - return T{Value{&*it}}; - } -}; - -} // namespace Shader::IR diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc deleted file mode 100644 index 21ce9b9..0000000 --- a/src/shader_recompiler/ir/opcodes.inc +++ /dev/null @@ -1,474 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -// opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, arg4 type, ... -OPCODE(Phi, Opaque, ) -OPCODE(Void, Void, ) -OPCODE(ConditionRef, U1, U1, ) - -// Special operations -OPCODE(Prologue, Void, ) -OPCODE(Epilogue, Void, ) -OPCODE(Discard, Void, ) -OPCODE(DiscardCond, Void, U1, ) -OPCODE(DebugPrint, Void, StringLiteral, Opaque, Opaque, Opaque, Opaque, ) - -// Constant memory operations -OPCODE(ReadConst, U32, U32x2, U32, ) -OPCODE(ReadConstBuffer, U32, Opaque, U32, ) - -// Barriers -OPCODE(Barrier, Void, ) -OPCODE(WorkgroupMemoryBarrier, Void, ) -OPCODE(DeviceMemoryBarrier, Void, ) - -// Geometry shader specific -OPCODE(EmitVertex, Void, ) -OPCODE(EmitPrimitive, Void, ) - -// Shared memory operations -OPCODE(LoadSharedU16, U16, U32, ) -OPCODE(LoadSharedU32, U32, U32, ) -OPCODE(LoadSharedU64, U64, U32, ) -OPCODE(WriteSharedU16, Void, U32, U16, ) -OPCODE(WriteSharedU32, Void, U32, U32, ) -OPCODE(WriteSharedU64, Void, U32, U64, ) - -// Shared atomic operations -OPCODE(SharedAtomicIAdd32, U32, U32, U32, ) -OPCODE(SharedAtomicIAdd64, U64, U32, U64, ) -OPCODE(SharedAtomicISub32, U32, U32, U32, ) -OPCODE(SharedAtomicISub64, U64, U32, U64, ) -OPCODE(SharedAtomicSMin32, U32, U32, U32, ) -OPCODE(SharedAtomicSMin64, U64, U32, U64, ) -OPCODE(SharedAtomicUMin32, U32, U32, U32, ) -OPCODE(SharedAtomicUMin64, U64, U32, U64, ) -OPCODE(SharedAtomicSMax32, U32, U32, U32, ) -OPCODE(SharedAtomicSMax64, U64, U32, U64, ) -OPCODE(SharedAtomicUMax32, U32, U32, U32, ) -OPCODE(SharedAtomicUMax64, U64, U32, U64, ) -OPCODE(SharedAtomicInc32, U32, U32, ) -OPCODE(SharedAtomicInc64, U64, U32, ) -OPCODE(SharedAtomicDec32, U32, U32, ) -OPCODE(SharedAtomicDec64, U64, U32, ) -OPCODE(SharedAtomicAnd32, U32, U32, U32, ) -OPCODE(SharedAtomicAnd64, U64, U32, U64, ) -OPCODE(SharedAtomicOr32, U32, U32, U32, ) -OPCODE(SharedAtomicOr64, U64, U32, U64, ) -OPCODE(SharedAtomicXor32, U32, U32, U32, ) -OPCODE(SharedAtomicXor64, U64, U32, U64, ) -OPCODE(SharedAtomicCmpSwap32, U32, U32, U32, U32, ) -OPCODE(SharedAtomicCmpSwap64, U64, U32, U64, U64, ) - -// Context getters/setters -OPCODE(GetUserData, U32, ScalarReg, ) -OPCODE(GetScalarRegister, U32, ScalarReg, ) -OPCODE(SetScalarRegister, Void, ScalarReg, U32, ) -OPCODE(GetVectorRegister, U32, VectorReg, ) -OPCODE(SetVectorRegister, Void, VectorReg, U32, ) -OPCODE(GetVirtualRegister, Opaque, VirtualReg, ) -OPCODE(SetVirtualRegister, Void, VirtualReg, Opaque, ) -OPCODE(GetGotoVariable, U1, U32, ) -OPCODE(SetGotoVariable, Void, U32, U1, ) -OPCODE(GetAttribute, F32, Attribute, U32, U32, ) -OPCODE(GetAttributeU1, U1, Attribute, U32, ) -OPCODE(GetAttributeU32, U32, Attribute, U32, ) -OPCODE(SetAttribute, Void, Attribute, F32, U32, ) -OPCODE(GetPatch, F32, Patch, ) -OPCODE(SetPatch, Void, Patch, F32, ) -OPCODE(GetTessGenericAttribute, F32, U32, U32, U32, ) -OPCODE(SetTcsGenericAttribute, Void, F32, U32, U32, ) -OPCODE(ReadTcsGenericOuputAttribute, F32, U32, U32, U32, ) -OPCODE(GetPcLo, U32, U32, ) - -// Flags -OPCODE(GetScc, U1, Void, ) -OPCODE(GetExec, U1, Void, ) -OPCODE(GetVcc, U1, Void, ) -OPCODE(GetVccLo, U32, Void, ) -OPCODE(GetVccHi, U32, Void, ) -OPCODE(GetM0, U32, Void, ) -OPCODE(SetScc, Void, U1, ) -OPCODE(SetExec, Void, U1, ) -OPCODE(SetVcc, Void, U1, ) -OPCODE(SetVccLo, Void, U32, ) -OPCODE(SetVccHi, Void, U32, ) -OPCODE(SetM0, Void, U32, ) - -// Undefined -OPCODE(UndefU1, U1, ) -OPCODE(UndefU8, U8, ) -OPCODE(UndefU16, U16, ) -OPCODE(UndefU32, U32, ) -OPCODE(UndefU32x2, U32x2, ) -OPCODE(UndefU32x3, U32x3, ) -OPCODE(UndefU32x4, U32x4, ) -OPCODE(UndefF32, F32, ) -OPCODE(UndefU64, U64, ) - -// Buffer operations -OPCODE(LoadBufferU8, U8, Opaque, Opaque, ) -OPCODE(LoadBufferU16, U16, Opaque, Opaque, ) -OPCODE(LoadBufferU32, U32, Opaque, Opaque, ) -OPCODE(LoadBufferU32x2, U32x2, Opaque, Opaque, ) -OPCODE(LoadBufferU32x3, U32x3, Opaque, Opaque, ) -OPCODE(LoadBufferU32x4, U32x4, Opaque, Opaque, ) -OPCODE(LoadBufferU64, U64, Opaque, Opaque, ) -OPCODE(LoadBufferF32, F32, Opaque, Opaque, ) -OPCODE(LoadBufferF32x2, F32x2, Opaque, Opaque, ) -OPCODE(LoadBufferF32x3, F32x3, Opaque, Opaque, ) -OPCODE(LoadBufferF32x4, F32x4, Opaque, Opaque, ) -OPCODE(LoadBufferFormatF32, F32x4, Opaque, Opaque, ) -OPCODE(StoreBufferU8, Void, Opaque, Opaque, U8, ) -OPCODE(StoreBufferU16, Void, Opaque, Opaque, U16, ) -OPCODE(StoreBufferU32, Void, Opaque, Opaque, U32, ) -OPCODE(StoreBufferU32x2, Void, Opaque, Opaque, U32x2, ) -OPCODE(StoreBufferU32x3, Void, Opaque, Opaque, U32x3, ) -OPCODE(StoreBufferU32x4, Void, Opaque, Opaque, U32x4, ) -OPCODE(StoreBufferU64, Void, Opaque, Opaque, U64, ) -OPCODE(StoreBufferF32, Void, Opaque, Opaque, F32, ) -OPCODE(StoreBufferF32x2, Void, Opaque, Opaque, F32x2, ) -OPCODE(StoreBufferF32x3, Void, Opaque, Opaque, F32x3, ) -OPCODE(StoreBufferF32x4, Void, Opaque, Opaque, F32x4, ) -OPCODE(StoreBufferFormatF32, Void, Opaque, Opaque, F32x4, ) - -// Buffer atomic operations -OPCODE(BufferAtomicIAdd32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicIAdd64, U64, Opaque, Opaque, U64 ) -OPCODE(BufferAtomicISub32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicSMin32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicSMin64, U64, Opaque, Opaque, U64 ) -OPCODE(BufferAtomicUMin32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicUMin64, U64, Opaque, Opaque, U64 ) -OPCODE(BufferAtomicFMin32, F32, Opaque, Opaque, F32 ) -OPCODE(BufferAtomicSMax32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicSMax64, U64, Opaque, Opaque, U64 ) -OPCODE(BufferAtomicUMax32, U32, Opaque, Opaque, U32 ) -OPCODE(BufferAtomicUMax64, U64, Opaque, Opaque, U64 ) -OPCODE(BufferAtomicFMax32, F32, Opaque, Opaque, F32 ) -OPCODE(BufferAtomicInc32, U32, Opaque, Opaque, ) -OPCODE(BufferAtomicDec32, U32, Opaque, Opaque, ) -OPCODE(BufferAtomicAnd32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicOr32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicSwap32, U32, Opaque, Opaque, U32, ) -OPCODE(BufferAtomicCmpSwap32, U32, Opaque, Opaque, U32, U32, ) -OPCODE(BufferAtomicFCmpSwap32, F32, Opaque, Opaque, F32, F32, ) - -// Vector utility -OPCODE(CompositeConstructU32x2, U32x2, U32, U32, ) -OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32, ) -OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32, ) -OPCODE(CompositeConstructU32x2x2, U32x4, U32x2, U32x2, ) -OPCODE(CompositeExtractU32x2, U32, U32x2, U32, ) -OPCODE(CompositeExtractU32x3, U32, U32x3, U32, ) -OPCODE(CompositeExtractU32x4, U32, U32x4, U32, ) -OPCODE(CompositeInsertU32x2, U32x2, U32x2, U32, U32, ) -OPCODE(CompositeInsertU32x3, U32x3, U32x3, U32, U32, ) -OPCODE(CompositeInsertU32x4, U32x4, U32x4, U32, U32, ) -OPCODE(CompositeShuffleU32x2, U32x2, U32x2, U32x2, U32, U32, ) -OPCODE(CompositeShuffleU32x3, U32x3, U32x3, U32x3, U32, U32, U32, ) -OPCODE(CompositeShuffleU32x4, U32x4, U32x4, U32x4, U32, U32, U32, U32, ) -OPCODE(CompositeConstructF32x2, F32x2, F32, F32, ) -OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, ) -OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, ) -OPCODE(CompositeConstructF32x2x2, F32x4, F32x2, F32x2, ) -OPCODE(CompositeExtractF32x2, F32, F32x2, U32, ) -OPCODE(CompositeExtractF32x3, F32, F32x3, U32, ) -OPCODE(CompositeExtractF32x4, F32, F32x4, U32, ) -OPCODE(CompositeInsertF32x2, F32x2, F32x2, F32, U32, ) -OPCODE(CompositeInsertF32x3, F32x3, F32x3, F32, U32, ) -OPCODE(CompositeInsertF32x4, F32x4, F32x4, F32, U32, ) -OPCODE(CompositeShuffleF32x2, F32x2, F32x2, F32x2, U32, U32, ) -OPCODE(CompositeShuffleF32x3, F32x3, F32x3, F32x3, U32, U32, U32, ) -OPCODE(CompositeShuffleF32x4, F32x4, F32x4, F32x4, U32, U32, U32, U32, ) - -// Select operations -OPCODE(SelectU1, U1, U1, U1, U1, ) -OPCODE(SelectU32, U32, U1, U32, U32, ) -OPCODE(SelectF32, F32, U1, F32, F32, ) -OPCODE(SelectU64, U64, U1, U64, U64, ) - -// Bitwise conversions -OPCODE(BitCastU16F16, U16, F16, ) -OPCODE(BitCastU32F32, U32, F32, ) -OPCODE(BitCastF16U16, F16, U16, ) -OPCODE(BitCastF32U32, F32, U32, ) - -OPCODE(PackUint2x32, U64, U32x2, ) -OPCODE(UnpackUint2x32, U32x2, U64, ) -OPCODE(PackDouble2x32, F64, U32x2, ) -OPCODE(UnpackDouble2x32, U32x2, F64, ) - -OPCODE(PackUnorm2x16, U32, F32x2, ) -OPCODE(UnpackUnorm2x16, F32x2, U32, ) -OPCODE(PackSnorm2x16, U32, F32x2, ) -OPCODE(UnpackSnorm2x16, F32x2, U32, ) -OPCODE(PackUint2x16, U32, F32x2, ) -OPCODE(UnpackUint2x16, F32x2, U32, ) -OPCODE(PackSint2x16, U32, F32x2, ) -OPCODE(UnpackSint2x16, F32x2, U32, ) -OPCODE(PackHalf2x16, U32, F32x2, ) -OPCODE(UnpackHalf2x16, F32x2, U32, ) - -OPCODE(PackUnorm4x8, U32, F32x4, ) -OPCODE(UnpackUnorm4x8, F32x4, U32, ) -OPCODE(PackSnorm4x8, U32, F32x4, ) -OPCODE(UnpackSnorm4x8, F32x4, U32, ) -OPCODE(PackUint4x8, U32, F32x4, ) -OPCODE(UnpackUint4x8, F32x4, U32, ) -OPCODE(PackSint4x8, U32, F32x4, ) -OPCODE(UnpackSint4x8, F32x4, U32, ) - -OPCODE(PackUfloat10_11_11, U32, F32x3, ) -OPCODE(UnpackUfloat10_11_11, F32x3, U32, ) - -OPCODE(PackUnorm2_10_10_10, U32, F32x4, ) -OPCODE(UnpackUnorm2_10_10_10, F32x4, U32, ) -OPCODE(PackSnorm2_10_10_10, U32, F32x4, ) -OPCODE(UnpackSnorm2_10_10_10, F32x4, U32, ) -OPCODE(PackUint2_10_10_10, U32, F32x4, ) -OPCODE(UnpackUint2_10_10_10, F32x4, U32, ) -OPCODE(PackSint2_10_10_10, U32, F32x4, ) -OPCODE(UnpackSint2_10_10_10, F32x4, U32, ) - -// Floating-point operations -OPCODE(FPAbs32, F32, F32, ) -OPCODE(FPAbs64, F64, F64, ) -OPCODE(FPAdd32, F32, F32, F32, ) -OPCODE(FPAdd64, F64, F64, F64, ) -OPCODE(FPSub32, F32, F32, F32, ) -OPCODE(FPFma32, F32, F32, F32, F32, ) -OPCODE(FPFma64, F64, F64, F64, F64, ) -OPCODE(FPMax32, F32, F32, F32, ) -OPCODE(FPMax64, F64, F64, F64, ) -OPCODE(FPMin32, F32, F32, F32, ) -OPCODE(FPMin64, F64, F64, F64, ) -OPCODE(FPMinTri32, F32, F32, F32, F32, ) -OPCODE(FPMaxTri32, F32, F32, F32, F32, ) -OPCODE(FPMedTri32, F32, F32, F32, F32, ) -OPCODE(FPMul32, F32, F32, F32, ) -OPCODE(FPMul64, F64, F64, F64, ) -OPCODE(FPDiv32, F32, F32, F32, ) -OPCODE(FPDiv64, F64, F64, F64, ) -OPCODE(FPNeg32, F32, F32, ) -OPCODE(FPNeg64, F64, F64, ) -OPCODE(FPRecip32, F32, F32, ) -OPCODE(FPRecip64, F64, F64, ) -OPCODE(FPRecipSqrt32, F32, F32, ) -OPCODE(FPRecipSqrt64, F64, F64, ) -OPCODE(FPSqrt, F32, F32, ) -OPCODE(FPSin, F32, F32, ) -OPCODE(FPExp2, F32, F32, ) -OPCODE(FPPow, F32, F32, F32, ) -OPCODE(FPLdexp, F32, F32, U32, ) -OPCODE(FPCos, F32, F32, ) -OPCODE(FPLog2, F32, F32, ) -OPCODE(FPSaturate32, F32, F32, ) -OPCODE(FPSaturate64, F64, F64, ) -OPCODE(FPClamp32, F32, F32, F32, F32, ) -OPCODE(FPClamp64, F64, F64, F64, F64, ) -OPCODE(FPRoundEven32, F32, F32, ) -OPCODE(FPRoundEven64, F64, F64, ) -OPCODE(FPFloor32, F32, F32, ) -OPCODE(FPFloor64, F64, F64, ) -OPCODE(FPCeil32, F32, F32, ) -OPCODE(FPCeil64, F64, F64, ) -OPCODE(FPTrunc32, F32, F32, ) -OPCODE(FPTrunc64, F64, F64, ) -OPCODE(FPFract32, F32, F32, ) -OPCODE(FPFract64, F64, F64, ) -OPCODE(FPFrexpSig32, F32, F32, ) -OPCODE(FPFrexpSig64, F64, F64, ) -OPCODE(FPFrexpExp32, U32, F32, ) -OPCODE(FPFrexpExp64, U32, F64, ) - -OPCODE(FPOrdEqual32, U1, F32, F32, ) -OPCODE(FPOrdEqual64, U1, F64, F64, ) -OPCODE(FPUnordEqual32, U1, F32, F32, ) -OPCODE(FPUnordEqual64, U1, F64, F64, ) -OPCODE(FPOrdNotEqual32, U1, F32, F32, ) -OPCODE(FPOrdNotEqual64, U1, F64, F64, ) -OPCODE(FPUnordNotEqual32, U1, F32, F32, ) -OPCODE(FPUnordNotEqual64, U1, F64, F64, ) -OPCODE(FPOrdLessThan32, U1, F32, F32, ) -OPCODE(FPOrdLessThan64, U1, F64, F64, ) -OPCODE(FPUnordLessThan32, U1, F32, F32, ) -OPCODE(FPUnordLessThan64, U1, F64, F64, ) -OPCODE(FPOrdGreaterThan32, U1, F32, F32, ) -OPCODE(FPOrdGreaterThan64, U1, F64, F64, ) -OPCODE(FPUnordGreaterThan32, U1, F32, F32, ) -OPCODE(FPUnordGreaterThan64, U1, F64, F64, ) -OPCODE(FPOrdLessThanEqual32, U1, F32, F32, ) -OPCODE(FPOrdLessThanEqual64, U1, F64, F64, ) -OPCODE(FPUnordLessThanEqual32, U1, F32, F32, ) -OPCODE(FPUnordLessThanEqual64, U1, F64, F64, ) -OPCODE(FPOrdGreaterThanEqual32, U1, F32, F32, ) -OPCODE(FPOrdGreaterThanEqual64, U1, F64, F64, ) -OPCODE(FPUnordGreaterThanEqual32, U1, F32, F32, ) -OPCODE(FPUnordGreaterThanEqual64, U1, F64, F64, ) -OPCODE(FPIsNan32, U1, F32, ) -OPCODE(FPIsNan64, U1, F64, ) -OPCODE(FPIsInf32, U1, F32, ) -OPCODE(FPIsInf64, U1, F64, ) -OPCODE(FPCmpClass32, U1, F32, U32 ) - -// Integer operations -OPCODE(IAdd32, U32, U32, U32, ) -OPCODE(IAdd64, U64, U64, U64, ) -OPCODE(ISub32, U32, U32, U32, ) -OPCODE(ISub64, U64, U64, U64, ) -OPCODE(IMul32, U32, U32, U32, ) -OPCODE(IMul64, U64, U64, U64, ) -OPCODE(SMulHi, U32, U32, U32, ) -OPCODE(UMulHi, U32, U32, U32, ) -OPCODE(SDiv32, U32, U32, U32, ) -OPCODE(UDiv32, U32, U32, U32, ) -OPCODE(SMod32, U32, U32, U32, ) -OPCODE(UMod32, U32, U32, U32, ) -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(BitwiseAnd64, U64, U64, U64, ) -OPCODE(BitwiseOr32, U32, U32, U32, ) -OPCODE(BitwiseOr64, U64, U64, U64, ) -OPCODE(BitwiseXor32, U32, U32, U32, ) -OPCODE(BitwiseXor64, U64, U64, U64, ) -OPCODE(BitFieldInsert32, U32, U32, U32, U32, U32, ) -OPCODE(BitFieldInsert64, U64, U64, U64, U32, U32, ) -OPCODE(BitFieldSExtract, U32, U32, U32, U32, ) -OPCODE(BitFieldUExtract, U32, U32, U32, U32, ) -OPCODE(BitReverse32, U32, U32, ) -OPCODE(BitCount32, U32, U32, ) -OPCODE(BitCount64, U32, U64, ) -OPCODE(BitwiseNot32, U32, U32, ) -OPCODE(BitwiseNot64, U64, U64, ) -OPCODE(MaskedBitCount32, U32, U32, U32, U1, ) - -OPCODE(FindSMsb32, U32, U32, ) -OPCODE(FindUMsb32, U32, U32, ) -OPCODE(FindUMsb64, U32, U64, ) -OPCODE(FindILsb32, U32, U32, ) -OPCODE(FindILsb64, U32, U64, ) -OPCODE(SMin32, U32, U32, U32, ) -OPCODE(UMin32, U32, U32, U32, ) -OPCODE(SMax32, U32, U32, U32, ) -OPCODE(UMax32, U32, U32, U32, ) -OPCODE(SMinTri32, U32, U32, U32, U32, ) -OPCODE(UMinTri32, U32, U32, U32, U32, ) -OPCODE(SMaxTri32, U32, U32, U32, U32, ) -OPCODE(UMaxTri32, U32, U32, U32, U32, ) -OPCODE(SMedTri32, U32, U32, U32, U32, ) -OPCODE(UMedTri32, U32, U32, U32, U32, ) -OPCODE(SClamp32, U32, U32, U32, U32, ) -OPCODE(UClamp32, U32, U32, U32, U32, ) -OPCODE(SLessThan32, U1, U32, U32, ) -OPCODE(SLessThan64, U1, U64, U64, ) -OPCODE(ULessThan32, U1, U32, U32, ) -OPCODE(ULessThan64, U1, U64, U64, ) -OPCODE(IEqual32, U1, U32, U32, ) -OPCODE(IEqual64, U1, U64, U64, ) -OPCODE(SLessThanEqual32, U1, U32, U32, ) -OPCODE(SLessThanEqual64, U1, U64, U64, ) -OPCODE(ULessThanEqual32, U1, U32, U32, ) -OPCODE(ULessThanEqual64, U1, U64, U64, ) -OPCODE(SGreaterThan32, U1, U32, U32, ) -OPCODE(SGreaterThan64, U1, U64, U64, ) -OPCODE(UGreaterThan32, U1, U32, U32, ) -OPCODE(UGreaterThan64, U1, U64, U64, ) -OPCODE(INotEqual32, U1, U32, U32, ) -OPCODE(INotEqual64, U1, U64, U64, ) -OPCODE(SGreaterThanEqual32, U1, U32, U32, ) -OPCODE(SGreaterThanEqual64, U1, U64, U64, ) -OPCODE(UGreaterThanEqual32, U1, U32, U32, ) -OPCODE(UGreaterThanEqual64, U1, U64, U64, ) - -// Logical operations -OPCODE(LogicalOr, U1, U1, U1, ) -OPCODE(LogicalAnd, U1, U1, U1, ) -OPCODE(LogicalXor, U1, U1, U1, ) -OPCODE(LogicalNot, U1, U1, ) - -// Conversion operations -OPCODE(ConvertS32F32, U32, F32, ) -OPCODE(ConvertS32F64, U32, F64, ) -OPCODE(ConvertU32F32, U32, F32, ) -OPCODE(ConvertF16F32, F16, F32, ) -OPCODE(ConvertF32F16, F32, F16, ) -OPCODE(ConvertF32F64, F32, F64, ) -OPCODE(ConvertF64F32, F64, F32, ) -OPCODE(ConvertF32S32, F32, U32, ) -OPCODE(ConvertF32U32, F32, U32, ) -OPCODE(ConvertF64S32, F64, U32, ) -OPCODE(ConvertF64U32, F64, U32, ) -OPCODE(ConvertF32U16, F32, U16, ) -OPCODE(ConvertU16U32, U16, U32, ) -OPCODE(ConvertU32U16, U32, U16, ) -OPCODE(ConvertU64U32, U64, U32, ) -OPCODE(ConvertU8U32, U8, U32, ) -OPCODE(ConvertU32U8, U32, U8, ) -OPCODE(ConvertS32S8, U32, U8, ) -OPCODE(ConvertS32S16, U32, U16, ) - -// Image operations -OPCODE(ImageHandle, Opaque, U32x4, U32x4, ) -OPCODE(ImageSampleRaw, F32x4, Opaque, Opaque, F32x4, F32x4, F32x4, F32, ) -OPCODE(ImageSampleImplicitLod, F32x4, Opaque, F32x4, F32, Opaque, ) -OPCODE(ImageSampleExplicitLod, F32x4, Opaque, Opaque, F32, Opaque, ) -OPCODE(ImageSampleDrefImplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) -OPCODE(ImageSampleDrefExplicitLod, F32x4, Opaque, Opaque, F32, F32, Opaque, ) -OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, ) -OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, F32, ) -OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) -OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) -OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, F32, ) -OPCODE(ImageRead, F32x4, Opaque, Opaque, U32, U32, ) -OPCODE(ImageWrite, Void, Opaque, Opaque, U32, U32, F32x4, ) - -// Image atomic operations -OPCODE(ImageAtomicIAdd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMin32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicSMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicUMax32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicFMax32, F32, Opaque, Opaque, F32, ) -OPCODE(ImageAtomicFMin32, F32, Opaque, Opaque, F32, ) -OPCODE(ImageAtomicInc32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicDec32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicAnd32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, ) -OPCODE(ImageAtomicCmpSwap32, U32, Opaque, Opaque, U32, U32, ) - -// Cube operations - optional, usable if profile.supports_native_cube_calc -OPCODE(CubeFaceIndex, F32, F32, F32, F32, ) -OPCODE(CubeFaceCoordS, F32, F32, F32, F32, ) -OPCODE(CubeFaceCoordT, F32, F32, F32, F32, ) -OPCODE(CubeFaceMajorAxis, F32, F32, F32, F32, ) - -// Warp operations -OPCODE(LaneId, U32, ) -OPCODE(WarpId, U32, ) -OPCODE(QuadBroadcast, U32, U32, U32 ) -OPCODE(Shuffle, U32, U32, U32 ) -OPCODE(ShuffleXor, U32, U32, U32, ) -OPCODE(ReadFirstLane, U32, U32, U1, ) -OPCODE(ReadLane, U32, U32, U32 ) -OPCODE(WriteLane, U32, U32, U32, U32 ) -OPCODE(Ballot, U64, U1, ) -OPCODE(BallotFindLsb, U32, U64, ) -OPCODE(InverseBallot, U1, U64, ) -OPCODE(DataAppend, U32, U32, U1 ) -OPCODE(DataConsume, U32, U32, U1 ) -OPCODE(GroupAny, U1, U1, ) - -// Time operations -OPCODE(Memtime, U64, )