From a7109c767bdc014327b574012794156c92174495 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 12 Oct 2021 17:35:31 -0300 Subject: [PATCH] Rewrite shader decoding stage (#2698) * Rewrite shader decoding stage * Fix P2R constant buffer encoding * Fix PSET/PSETP * PR feedback * Log unimplemented shader instructions * Implement NOP * Remove using * PR feedback --- .../Shader/CachedGpuAccessor.cs | 10 +- Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs | 23 +- Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 2 +- .../TextureDescriptorCapableGpuAccessor.cs | 3 +- .../Glsl/Instructions/InstGenMemory.cs | 2 +- Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs | 16 - .../Decoders/BarrierLevel.cs | 10 - .../Decoders/BarrierMode.cs | 12 - .../Decoders/BitfieldExtensions.cs | 10 - Ryujinx.Graphics.Shader/Decoders/Block.cs | 147 +- .../Decoders/CbIndexMode.cs | 10 - Ryujinx.Graphics.Shader/Decoders/Condition.cs | 45 - .../Decoders/ConditionalOperation.cs | 10 - Ryujinx.Graphics.Shader/Decoders/Decoder.cs | 306 +- .../Decoders/DecoderHelper.cs | 74 - .../Decoders/FPHalfSwizzle.cs | 10 - .../Decoders/FPMultiplyScale.cs | 13 - Ryujinx.Graphics.Shader/Decoders/FPType.cs | 19 - Ryujinx.Graphics.Shader/Decoders/IOpCode.cs | 16 - .../Decoders/IOpCodeAlu.cs | 9 - .../Decoders/IOpCodeAttribute.cs | 9 - .../Decoders/IOpCodeCbuf.cs | 8 - .../Decoders/IOpCodeFArith.cs | 12 - .../Decoders/IOpCodeHfma.cs | 13 - .../Decoders/IOpCodeImm.cs | 7 - .../Decoders/IOpCodeImmF.cs | 7 - .../Decoders/IOpCodeLop.cs | 10 - .../Decoders/IOpCodePredicate39.cs | 9 - Ryujinx.Graphics.Shader/Decoders/IOpCodeRa.cs | 7 - Ryujinx.Graphics.Shader/Decoders/IOpCodeRc.cs | 7 - Ryujinx.Graphics.Shader/Decoders/IOpCodeRd.cs | 7 - .../Decoders/IOpCodeReg.cs | 7 - .../Decoders/IOpCodeRegCbuf.cs | 8 - .../Decoders/IOpCodeTexture.cs | 23 - .../Decoders/IOpCodeTld4.cs | 11 - .../Decoders/ImageComponents.cs | 10 - .../Decoders/ImageDimensions.cs | 12 - .../Decoders/InstDecoders.cs | 5362 +++++++++++++++++ Ryujinx.Graphics.Shader/Decoders/InstName.cs | 188 + Ryujinx.Graphics.Shader/Decoders/InstOp.cs | 27 + Ryujinx.Graphics.Shader/Decoders/InstProps.cs | 20 + Ryujinx.Graphics.Shader/Decoders/InstTable.cs | 388 ++ .../Decoders/IntegerCondition.cs | 18 - .../Decoders/IntegerHalfPart.cs | 9 - .../Decoders/IntegerShift.cs | 9 - .../Decoders/IntegerSize.cs | 14 - .../Decoders/IntegerType.cs | 14 - .../Decoders/InterpolationMode.cs | 10 - .../Decoders/LogicalOperation.cs | 10 - .../Decoders/MufuOperation.cs | 15 - Ryujinx.Graphics.Shader/Decoders/OpCode.cs | 32 - .../Decoders/OpCodeAl2p.cs | 24 - Ryujinx.Graphics.Shader/Decoders/OpCodeAlu.cs | 36 - .../Decoders/OpCodeAluCbuf.cs | 18 - .../Decoders/OpCodeAluImm.cs | 16 - .../Decoders/OpCodeAluImm2x10.cs | 16 - .../Decoders/OpCodeAluImm32.cs | 20 - .../Decoders/OpCodeAluReg.cs | 16 - .../Decoders/OpCodeAluRegCbuf.cs | 20 - .../Decoders/OpCodeAtom.cs | 28 - .../Decoders/OpCodeAttribute.cs | 23 - .../Decoders/OpCodeBarrier.cs | 16 - .../Decoders/OpCodeBranch.cs | 25 - .../Decoders/OpCodeBranchIndir.cs | 25 - .../Decoders/OpCodeBranchPop.cs | 17 - .../Decoders/OpCodeConditional.cs | 16 - .../Decoders/OpCodeDArithImm.cs | 16 - .../Decoders/OpCodeExit.cs | 13 - .../Decoders/OpCodeFArith.cs | 26 - .../Decoders/OpCodeFArithCbuf.cs | 18 - .../Decoders/OpCodeFArithImm.cs | 16 - .../Decoders/OpCodeFArithImm32.cs | 32 - .../Decoders/OpCodeFArithReg.cs | 16 - .../Decoders/OpCodeFArithRegCbuf.cs | 18 - .../Decoders/OpCodeFsetImm.cs | 16 - .../Decoders/OpCodeHfma.cs | 24 - .../Decoders/OpCodeHfmaCbuf.cs | 32 - .../Decoders/OpCodeHfmaImm2x10.cs | 28 - .../Decoders/OpCodeHfmaImm32.cs | 27 - .../Decoders/OpCodeHfmaReg.cs | 31 - .../Decoders/OpCodeHfmaRegCbuf.cs | 32 - .../Decoders/OpCodeHsetImm2x10.cs | 16 - .../Decoders/OpCodeImage.cs | 47 - Ryujinx.Graphics.Shader/Decoders/OpCodeIpa.cs | 28 - Ryujinx.Graphics.Shader/Decoders/OpCodeLdc.cs | 30 - Ryujinx.Graphics.Shader/Decoders/OpCodeLop.cs | 26 - .../Decoders/OpCodeLopCbuf.cs | 18 - .../Decoders/OpCodeLopImm.cs | 16 - .../Decoders/OpCodeLopImm32.cs | 24 - .../Decoders/OpCodeLopReg.cs | 16 - .../Decoders/OpCodeMemory.cs | 30 - .../Decoders/OpCodeMemoryBarrier.cs | 16 - .../Decoders/OpCodePset.cs | 28 - .../Decoders/OpCodePush.cs | 24 - Ryujinx.Graphics.Shader/Decoders/OpCodeRed.cs | 34 - Ryujinx.Graphics.Shader/Decoders/OpCodeSet.cs | 28 - .../Decoders/OpCodeSetCbuf.cs | 18 - .../Decoders/OpCodeSetImm.cs | 16 - .../Decoders/OpCodeSetReg.cs | 16 - .../Decoders/OpCodeShuffle.cs | 42 - .../Decoders/OpCodeSuatom.cs | 46 - .../Decoders/OpCodeSured.cs | 44 - .../Decoders/OpCodeTable.cs | 304 - Ryujinx.Graphics.Shader/Decoders/OpCodeTex.cs | 16 - .../Decoders/OpCodeTexB.cs | 22 - .../Decoders/OpCodeTexs.cs | 13 - .../Decoders/OpCodeTexture.cs | 40 - .../Decoders/OpCodeTextureBase.cs | 14 - .../Decoders/OpCodeTextureScalar.cs | 60 - Ryujinx.Graphics.Shader/Decoders/OpCodeTld.cs | 22 - .../Decoders/OpCodeTld4.cs | 24 - .../Decoders/OpCodeTld4B.cs | 24 - .../Decoders/OpCodeTld4s.cs | 26 - .../Decoders/OpCodeTlds.cs | 13 - Ryujinx.Graphics.Shader/Decoders/OpCodeTxd.cs | 20 - .../Decoders/OpCodeVideo.cs | 105 - .../Decoders/OpCodeVote.cs | 28 - .../Decoders/ReductionType.cs | 14 - .../Decoders/RoundingMode.cs | 10 - .../Decoders/ShuffleType.cs | 10 - .../Decoders/SystemRegister.cs | 21 - .../Decoders/TexelLoadTarget.cs | 15 - .../Decoders/TextureDimensions.cs | 10 - .../Decoders/TextureGatherOffset.cs | 9 - .../Decoders/TextureLodMode.cs | 12 - .../Decoders/TextureProperty.cs | 13 - .../Decoders/TextureTarget.cs | 20 - .../Decoders/VideoPostOp.cs | 14 - Ryujinx.Graphics.Shader/Decoders/VideoType.cs | 15 - Ryujinx.Graphics.Shader/Decoders/VoteOp.cs | 9 - Ryujinx.Graphics.Shader/Decoders/XmadCMode.cs | 11 - Ryujinx.Graphics.Shader/IGpuAccessor.cs | 11 +- .../Instructions/InstEmit.cs | 526 ++ .../Instructions/InstEmitAlu.cs | 984 --- .../Instructions/InstEmitAluHelper.cs | 57 +- .../Instructions/InstEmitAttribute.cs | 190 + .../Instructions/InstEmitBarrier.cs | 44 + .../Instructions/InstEmitBitfield.cs | 190 + .../Instructions/InstEmitConversion.cs | 411 +- .../Instructions/InstEmitFArith.cs | 547 -- .../Instructions/InstEmitFloatArithmetic.cs | 545 ++ .../Instructions/InstEmitFloatComparison.cs | 419 ++ .../Instructions/InstEmitFloatMinMax.cs | 70 + ...InstEmitFlow.cs => InstEmitFlowControl.cs} | 107 +- .../Instructions/InstEmitHelper.cs | 267 +- .../Instructions/InstEmitIntegerArithmetic.cs | 656 ++ .../Instructions/InstEmitIntegerComparison.cs | 327 + .../Instructions/InstEmitIntegerLogical.cs | 167 + .../Instructions/InstEmitIntegerMinMax.cs | 71 + .../Instructions/InstEmitMemory.cs | 552 +- .../Instructions/InstEmitMove.cs | 227 +- .../Instructions/InstEmitMultifunction.cs | 85 + .../Instructions/InstEmitNop.cs | 15 + .../Instructions/InstEmitPredicate.cs | 54 + .../Instructions/InstEmitShift.cs | 132 + .../Instructions/InstEmitSurface.cs | 776 +++ .../Instructions/InstEmitTexture.cs | 1468 ++--- .../Instructions/InstEmitVideoArithmetic.cs | 18 + ...nstEmitVideo.cs => InstEmitVideoMinMax.cs} | 85 +- .../Instructions/InstEmitVote.cs | 48 - .../Instructions/InstEmitWarp.cs | 84 + .../Instructions/Lop3Expression.cs | 9 +- .../Translation/ControlFlowGraph.cs | 25 + .../Translation/Dominance.cs | 1 - .../Translation/EmitterContext.cs | 11 +- .../Translation/ShaderHeader.cs | 21 +- .../Translation/Translator.cs | 38 +- Ryujinx.ShaderTools/Program.cs | 4 +- 168 files changed, 12022 insertions(+), 6388 deletions(-) delete mode 100644 Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/CbIndexMode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/Condition.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/ConditionalOperation.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/DecoderHelper.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/FPHalfSwizzle.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/FPMultiplyScale.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/FPType.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeAlu.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeFArith.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeHfma.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeImmF.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeLop.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodePredicate39.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeRa.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeRc.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeRd.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeRegCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeTexture.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IOpCodeTld4.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/ImageDimensions.cs create mode 100644 Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs create mode 100644 Ryujinx.Graphics.Shader/Decoders/InstName.cs create mode 100644 Ryujinx.Graphics.Shader/Decoders/InstOp.cs create mode 100644 Ryujinx.Graphics.Shader/Decoders/InstProps.cs create mode 100644 Ryujinx.Graphics.Shader/Decoders/InstTable.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IntegerCondition.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IntegerHalfPart.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IntegerShift.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IntegerSize.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/IntegerType.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/InterpolationMode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/LogicalOperation.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/MufuOperation.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAl2p.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAlu.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm2x10.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm32.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAluRegCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeAttribute.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeBranchIndir.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeDArithImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArith.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArithCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm32.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArithReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFArithRegCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeFsetImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfma.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm2x10.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm32.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaRegCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeHsetImm2x10.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeImage.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeIpa.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLdc.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLop.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLopCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm32.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeLopReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeMemory.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodePset.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodePush.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeRed.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSet.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSetCbuf.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSetImm.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSetReg.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeShuffle.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSuatom.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeSured.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTex.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTexB.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTexs.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTexture.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTextureBase.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTextureScalar.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTld.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTld4.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTld4B.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTld4s.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTlds.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeTxd.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeVideo.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/OpCodeVote.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/ReductionType.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/RoundingMode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/ShuffleType.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TexelLoadTarget.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TextureDimensions.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TextureGatherOffset.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TextureLodMode.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TextureProperty.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/TextureTarget.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/VideoPostOp.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/VideoType.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/VoteOp.cs delete mode 100644 Ryujinx.Graphics.Shader/Decoders/XmadCMode.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmit.cs delete mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs delete mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs rename Ryujinx.Graphics.Shader/Instructions/{InstEmitFlow.cs => InstEmitFlowControl.cs} (63%) create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs rename Ryujinx.Graphics.Shader/Instructions/{InstEmitVideo.cs => InstEmitVideoMinMax.cs} (51%) delete mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs create mode 100644 Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs diff --git a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs index 625b8bac..3a52b2fe 100644 --- a/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/CachedGpuAccessor.cs @@ -60,14 +60,14 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// - /// Reads data from GPU memory. + /// Gets a span of the specified memory location, containing shader code. /// - /// Type of the data to be read /// GPU virtual address of the data - /// Data at the memory location - public override T MemoryRead(ulong address) + /// Minimum size that the returned span may have + /// Span of the memory location + public override ReadOnlySpan GetCode(ulong address, int minimumSize) { - return MemoryMarshal.Cast(_data.Span.Slice((int)address))[0]; + return MemoryMarshal.Cast(_data.Span.Slice((int)address)); } /// diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index 91746a96..50e24b97 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs @@ -1,6 +1,8 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Shader; +using System; +using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Gpu.Shader { @@ -95,24 +97,15 @@ namespace Ryujinx.Graphics.Gpu.Shader } /// - /// Reads data from GPU memory. + /// Gets a span of the specified memory location, containing shader code. /// - /// Type of the data to be read /// GPU virtual address of the data - /// Data at the memory location - public override T MemoryRead(ulong address) + /// Minimum size that the returned span may have + /// Span of the memory location + public override ReadOnlySpan GetCode(ulong address, int minimumSize) { - return _channel.MemoryManager.Read(address); - } - - /// - /// Checks if a given memory address is mapped. - /// - /// GPU virtual address to be checked - /// True if the address is mapped, false otherwise - public bool MemoryMapped(ulong address) - { - return _channel.MemoryManager.IsMapped(address); + int size = Math.Max(minimumSize, 0x1000 - (int)(address & 0xfff)); + return MemoryMarshal.Cast(_channel.MemoryManager.GetSpan(address, size)); } /// diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index af6f9462..12b7c2f0 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Version of the codegen (to be changed when codegen or guest format change). /// - private const ulong ShaderCodeGenVersion = 2646; + private const ulong ShaderCodeGenVersion = 2697; // Progress reporting helpers private volatile int _shaderCount; diff --git a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs index dfb67f35..40353850 100644 --- a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Shader; +using System; namespace Ryujinx.Graphics.Gpu.Shader { @@ -13,7 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Shader _context = context; } - public abstract T MemoryRead(ulong address) where T : unmanaged; + public abstract ReadOnlySpan GetCode(ulong address, int minimumSize); public abstract ITextureDescriptor GetTextureDescriptor(int handle, int cbufSlot); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 89215736..edaacd3e 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -176,7 +176,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { texCall = "int(" + texCall + ")"; } - } + } else { texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : ""); diff --git a/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs b/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs deleted file mode 100644 index 19955192..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/AtomicOp.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum AtomicOp - { - Add = 0, - Minimum = 1, - Maximum = 2, - Increment = 3, - Decrement = 4, - BitwiseAnd = 5, - BitwiseOr = 6, - BitwiseExclusiveOr = 7, - Swap = 8, - SafeAdd = 10 // Only supported by ATOM. - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs b/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs deleted file mode 100644 index 95c71e00..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/BarrierLevel.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum BarrierLevel - { - Cta = 0, - Gl = 1, - Sys = 2, - Vc = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs b/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs deleted file mode 100644 index a058cbbd..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/BarrierMode.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum BarrierMode - { - ReductionPopCount = 2, - Scan = 3, - ReductionAnd = 0xa, - ReductionOr = 0x12, - Sync = 0x80, - Arrive = 0x81 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs b/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs index d902fc86..79e0a5c0 100644 --- a/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs +++ b/Ryujinx.Graphics.Shader/Decoders/BitfieldExtensions.cs @@ -11,15 +11,5 @@ namespace Ryujinx.Graphics.Shader.Decoders { return (value >> lsb) & (int)(uint.MaxValue >> (32 - length)); } - - public static bool Extract(this long value, int lsb) - { - return ((int)(value >> lsb) & 1) != 0; - } - - public static int Extract(this long value, int lsb, int length) - { - return (int)(value >> lsb) & (int)(uint.MaxValue >> (32 - length)); - } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/Block.cs b/Ryujinx.Graphics.Shader/Decoders/Block.cs index 69cb55b9..0b55c59e 100644 --- a/Ryujinx.Graphics.Shader/Decoders/Block.cs +++ b/Ryujinx.Graphics.Shader/Decoders/Block.cs @@ -1,57 +1,56 @@ +using Ryujinx.Graphics.Shader.IntermediateRepresentation; using System; using System.Collections.Generic; +using System.Linq; namespace Ryujinx.Graphics.Shader.Decoders { + class PushOpInfo + { + public InstOp Op { get; } + public Dictionary Consumers; + + public PushOpInfo(InstOp op) + { + Op = op; + Consumers = new Dictionary(); + } + } + + struct SyncTarget + { + public PushOpInfo PushOpInfo { get; } + public int PushOpId { get; } + + public SyncTarget(PushOpInfo pushOpInfo, int pushOpId) + { + PushOpInfo = pushOpInfo; + PushOpId = pushOpId; + } + } + class Block { - public ulong Address { get; set; } + public ulong Address { get; set; } public ulong EndAddress { get; set; } - private Block _next; - private Block _branch; + public List Predecessors { get; } + public List Successors { get; } - public Block Next - { - get - { - return _next; - } - set - { - _next?.Predecessors.Remove(this); - value?.Predecessors.Add(this); - _next = value; - } - } - - public Block Branch - { - get - { - return _branch; - } - set - { - _branch?.Predecessors.Remove(this); - value?.Predecessors.Add(this); - _branch = value; - } - } - - public HashSet Predecessors { get; } - - public List OpCodes { get; } - public List PushOpCodes { get; } + public List OpCodes { get; } + public List PushOpCodes { get; } + public Dictionary SyncTargets { get; } public Block(ulong address) { Address = address; - Predecessors = new HashSet(); + Predecessors = new List(); + Successors = new List(); - OpCodes = new List(); - PushOpCodes = new List(); + OpCodes = new List(); + PushOpCodes = new List(); + SyncTargets = new Dictionary(); } public void Split(Block rightBlock) @@ -64,36 +63,56 @@ namespace Ryujinx.Graphics.Shader.Decoders } int splitCount = OpCodes.Count - splitIndex; - if (splitCount <= 0) { throw new ArgumentException("Can't split at right block address."); } rightBlock.EndAddress = EndAddress; - - rightBlock.Next = Next; - rightBlock.Branch = Branch; - - rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount)); - - rightBlock.UpdatePushOps(); + rightBlock.Successors.AddRange(Successors); + rightBlock.Predecessors.Add(this); EndAddress = rightBlock.Address; - Next = rightBlock; - Branch = null; + Successors.Clear(); + Successors.Add(rightBlock); + + // Move ops. + rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount)); OpCodes.RemoveRange(splitIndex, splitCount); - UpdatePushOps(); + // Update push consumers that points to this block. + foreach (SyncTarget syncTarget in SyncTargets.Values) + { + PushOpInfo pushOpInfo = syncTarget.PushOpInfo; + + Operand local = pushOpInfo.Consumers[this]; + pushOpInfo.Consumers.Remove(this); + pushOpInfo.Consumers.Add(rightBlock, local); + } + + rightBlock.SyncTargets.Union(SyncTargets); + SyncTargets.Clear(); + + // Move push ops. + for (int i = 0; i < PushOpCodes.Count; i++) + { + if (PushOpCodes[i].Op.Address >= rightBlock.Address) + { + int count = PushOpCodes.Count - i; + rightBlock.PushOpCodes.AddRange(PushOpCodes.Skip(i)); + PushOpCodes.RemoveRange(i, count); + break; + } + } } - private static int BinarySearch(List opCodes, ulong address) + private static int BinarySearch(List opCodes, ulong address) { - int left = 0; + int left = 0; int middle = 0; - int right = opCodes.Count - 1; + int right = opCodes.Count - 1; while (left <= right) { @@ -101,7 +120,7 @@ namespace Ryujinx.Graphics.Shader.Decoders middle = left + (size >> 1); - OpCode opCode = opCodes[middle]; + InstOp opCode = opCodes[middle]; if (address == opCode.Address) { @@ -121,29 +140,25 @@ namespace Ryujinx.Graphics.Shader.Decoders return middle; } - public OpCode GetLastOp() + public InstOp GetLastOp() { if (OpCodes.Count != 0) { return OpCodes[OpCodes.Count - 1]; } - return null; + return default; } - public void UpdatePushOps() + public bool HasNext() { - PushOpCodes.Clear(); + InstOp lastOp = GetLastOp(); + return OpCodes.Count != 0 && !Decoder.IsUnconditionalBranch(ref lastOp); + } - for (int index = 0; index < OpCodes.Count; index++) - { - if (!(OpCodes[index] is OpCodePush op)) - { - continue; - } - - PushOpCodes.Add(op); - } + public void AddPushOp(InstOp op) + { + PushOpCodes.Add(new PushOpInfo(op)); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/CbIndexMode.cs b/Ryujinx.Graphics.Shader/Decoders/CbIndexMode.cs deleted file mode 100644 index 4c7a72b5..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/CbIndexMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum CbIndexMode - { - Default = 0, - Il = 1, - Is = 2, - Isl = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/Condition.cs b/Ryujinx.Graphics.Shader/Decoders/Condition.cs deleted file mode 100644 index 10400f94..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/Condition.cs +++ /dev/null @@ -1,45 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum Condition - { - Less = 1 << 0, - Equal = 1 << 1, - Greater = 1 << 2, - Nan = 1 << 3, - Unsigned = 1 << 4, - - Never = 0, - - LessOrEqual = Less | Equal, - NotEqual = Less | Greater, - GreaterOrEqual = Greater | Equal, - Number = Greater | Equal | Less, - - LessUnordered = Less | Nan, - EqualUnordered = Equal | Nan, - LessOrEqualUnordered = LessOrEqual | Nan, - GreaterUnordered = Greater | Nan, - NotEqualUnordered = NotEqual | Nan, - GreaterOrEqualUnordered = GreaterOrEqual | Nan, - - Always = 0xf, - - Off = Unsigned | Never, - Lower = Unsigned | Less, - Sff = Unsigned | Equal, - LowerOrSame = Unsigned | LessOrEqual, - Higher = Unsigned | Greater, - Sft = Unsigned | NotEqual, - HigherOrSame = Unsigned | GreaterOrEqual, - Oft = Unsigned | Always, - - CsmTa = 0x18, - CsmTr = 0x19, - CsmMx = 0x1a, - FcsmTa = 0x1b, - FcsmTr = 0x1c, - FcsmMx = 0x1d, - Rle = 0x1e, - Rgt = 0x1f - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/ConditionalOperation.cs b/Ryujinx.Graphics.Shader/Decoders/ConditionalOperation.cs deleted file mode 100644 index 4fc31e84..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/ConditionalOperation.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ConditionalOperation - { - False = 0, - True = 1, - Zero = 2, - NotZero = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index c2901eab..656e9c44 100644 --- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs @@ -1,8 +1,8 @@ -using Ryujinx.Graphics.Shader.Instructions; using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -95,32 +95,33 @@ namespace Ryujinx.Graphics.Shader.Decoders { // We should have blocks for all possible branch targets, // including those from SSY/PBK instructions. - foreach (OpCodePush pushOp in currBlock.PushOpCodes) + foreach (PushOpInfo pushOp in currBlock.PushOpCodes) { - GetBlock(pushOp.GetAbsoluteAddress()); + GetBlock(pushOp.Op.GetAbsoluteAddress()); } // Set child blocks. "Branch" is the block the branch instruction // points to (when taken), "Next" is the block at the next address, // executed when the branch is not taken. For Unconditional Branches // or end of program, Next is null. - OpCode lastOp = currBlock.GetLastOp(); + InstOp lastOp = currBlock.GetLastOp(); - if (lastOp is OpCodeBranch opBr) + if (lastOp.Name == InstName.Cal) { - if (lastOp.Emitter == InstEmit.Cal) - { - EnqueueFunction(opBr.GetAbsoluteAddress()); - } - else - { - currBlock.Branch = GetBlock(opBr.GetAbsoluteAddress()); - } + EnqueueFunction(lastOp.GetAbsoluteAddress()); + } + else if (lastOp.Name == InstName.Bra) + { + Block succBlock = GetBlock(lastOp.GetAbsoluteAddress()); + currBlock.Successors.Add(succBlock); + succBlock.Predecessors.Add(currBlock); } - if (!IsUnconditionalBranch(lastOp)) + if (!IsUnconditionalBranch(ref lastOp)) { - currBlock.Next = GetBlock(currBlock.EndAddress); + Block succBlock = GetBlock(currBlock.EndAddress); + currBlock.Successors.Insert(0, succBlock); + succBlock.Predecessors.Add(currBlock); } } @@ -146,33 +147,8 @@ namespace Ryujinx.Graphics.Shader.Decoders } } - // Try to find target for BRX (indirect branch) instructions. - hasNewTarget = false; - - foreach (Block block in blocks) - { - if (block.GetLastOp() is OpCodeBranchIndir opBrIndir && opBrIndir.PossibleTargets.Count == 0) - { - ulong baseOffset = opBrIndir.Address + 8 + (ulong)opBrIndir.Offset; - - // An indirect branch could go anywhere, - // try to get the possible target offsets from the constant buffer. - (int cbBaseOffset, int cbOffsetsCount) = FindBrxTargetRange(block, opBrIndir.Ra.Index); - - if (cbOffsetsCount != 0) - { - hasNewTarget = true; - } - - for (int i = 0; i < cbOffsetsCount; i++) - { - uint targetOffset = config.GpuAccessor.ConstantBuffer1Read(cbBaseOffset + i * 4); - Block target = GetBlock(baseOffset + targetOffset); - opBrIndir.PossibleTargets.Add(target); - target.Predecessors.Add(block); - } - } - } + // Try to find targets for BRX (indirect branch) instructions. + hasNewTarget = FindBrxTargets(config, blocks, GetBlock); // If we discovered new branch targets from the BRX instruction, // we need another round of decoding to decode the new blocks. @@ -227,6 +203,10 @@ namespace Ryujinx.Graphics.Shader.Decoders IGpuAccessor gpuAccessor = config.GpuAccessor; ulong address = block.Address; + int bufferOffset = 0; + ReadOnlySpan buffer = ReadOnlySpan.Empty; + + InstOp op = default; do { @@ -239,66 +219,75 @@ namespace Ryujinx.Graphics.Shader.Decoders if ((address & 0x1f) == 0) { address += 8; - + bufferOffset++; continue; } - ulong opAddress = address; - - address += 8; - - long opCode = gpuAccessor.MemoryRead(startAddress + opAddress); - - (InstEmitter emitter, OpCodeTable.MakeOp makeOp) = OpCodeTable.GetEmitter(opCode); - - if (emitter == null) + if (bufferOffset >= buffer.Length) { - // TODO: Warning, illegal encoding. - - block.OpCodes.Add(new OpCode(null, opAddress, opCode)); - - continue; + buffer = gpuAccessor.GetCode(startAddress + address, 8); + bufferOffset = 0; } - if (makeOp == null) - { - throw new ArgumentNullException(nameof(makeOp)); - } + ulong opCode = buffer[bufferOffset++]; - OpCode op = makeOp(emitter, opAddress, opCode); + op = InstTable.GetOp(address, opCode); - // We check these patterns to figure out the presence of bindless access - if ((op is OpCodeImage image && image.IsBindless) || - (op is OpCodeTxd txd && txd.IsBindless) || - (op is OpCodeTld4B) || - (emitter == InstEmit.TexB) || - (emitter == InstEmit.TldB) || - (emitter == InstEmit.TmmlB) || - (emitter == InstEmit.TxqB)) + if (op.Props.HasFlag(InstProps.TexB)) { config.SetUsedFeature(FeatureFlags.Bindless); } - // Populate used attributes. - if (op is IOpCodeAttribute opAttr) + if (op.Name == InstName.Ald || op.Name == InstName.Ast || op.Name == InstName.Ipa) { - SetUserAttributeUses(config, opAttr); + SetUserAttributeUses(config, op.Name, opCode); + } + else if (op.Name == InstName.Ssy || op.Name == InstName.Pbk) + { + block.AddPushOp(op); } block.OpCodes.Add(op); + + address += 8; } - while (!IsControlFlowChange(block.GetLastOp())); + while (!op.Props.HasFlag(InstProps.Bra)); block.EndAddress = address; - - block.UpdatePushOps(); } - private static void SetUserAttributeUses(ShaderConfig config, IOpCodeAttribute opAttr) + private static void SetUserAttributeUses(ShaderConfig config, InstName name, ulong opCode) { - if (opAttr.Indexed) + int offset; + int count = 1; + bool isStore = false; + bool indexed = false; + + if (name == InstName.Ast) { - if (opAttr.Emitter == InstEmit.Ast) + InstAst opAst = new InstAst(opCode); + count = (int)opAst.AlSize + 1; + offset = opAst.Imm11; + indexed = opAst.Phys; + isStore = true; + } + else if (name == InstName.Ald) + { + InstAld opAld = new InstAld(opCode); + count = (int)opAld.AlSize + 1; + indexed = opAld.Phys; + offset = opAld.Imm11; + } + else /* if (name == InstName.Ipa) */ + { + InstIpa opIpa = new InstIpa(opCode); + offset = opIpa.Imm10; + indexed = opIpa.Idx; + } + + if (indexed) + { + if (isStore) { config.SetAllOutputUserAttributes(); } @@ -309,14 +298,14 @@ namespace Ryujinx.Graphics.Shader.Decoders } else { - for (int elemIndex = 0; elemIndex < opAttr.Count; elemIndex++) + for (int elemIndex = 0; elemIndex < count; elemIndex++) { - int attr = opAttr.AttributeOffset + elemIndex * 4; + int attr = offset + elemIndex * 4; if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd) { int index = (attr - AttributeConsts.UserAttributeBase) / 16; - if (opAttr.Emitter == InstEmit.Ast) + if (isStore) { config.SetOutputUserAttribute(index); } @@ -329,27 +318,57 @@ namespace Ryujinx.Graphics.Shader.Decoders } } - private static bool IsUnconditionalBranch(OpCode opCode) + public static bool IsUnconditionalBranch(ref InstOp op) { - return IsUnconditional(opCode) && IsControlFlowChange(opCode); + return IsUnconditional(ref op) && op.Props.HasFlag(InstProps.Bra); } - private static bool IsUnconditional(OpCode opCode) + private static bool IsUnconditional(ref InstOp op) { - if (opCode is OpCodeExit op && op.Condition != Condition.Always) + InstConditional condOp = new InstConditional(op.RawOpCode); + + if (op.Name == InstName.Exit && condOp.Ccc != Ccc.T) { return false; } - return opCode.Predicate.Index == RegisterConsts.PredicateTrueIndex && !opCode.InvertPredicate; + return condOp.Pred == RegisterConsts.PredicateTrueIndex && !condOp.PredInv; } - private static bool IsControlFlowChange(OpCode opCode) + private static bool FindBrxTargets(ShaderConfig config, IEnumerable blocks, Func getBlock) { - return (opCode is OpCodeBranch opBranch && !opBranch.PushTarget) || - opCode is OpCodeBranchIndir || - opCode is OpCodeBranchPop || - opCode is OpCodeExit; + bool hasNewTarget = false; + + foreach (Block block in blocks) + { + InstOp lastOp = block.GetLastOp(); + bool hasNext = block.HasNext(); + + if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0)) + { + InstBrx opBrx = new InstBrx(lastOp.RawOpCode); + ulong baseOffset = lastOp.GetAbsoluteAddress(); + + // An indirect branch could go anywhere, + // try to get the possible target offsets from the constant buffer. + (int cbBaseOffset, int cbOffsetsCount) = FindBrxTargetRange(block, opBrx.SrcA); + + if (cbOffsetsCount != 0) + { + hasNewTarget = true; + } + + for (int i = 0; i < cbOffsetsCount; i++) + { + uint targetOffset = config.GpuAccessor.ConstantBuffer1Read(cbBaseOffset + i * 4); + Block target = getBlock(baseOffset + targetOffset); + target.Predecessors.Add(block); + block.Successors.Add(target); + } + } + } + + return hasNewTarget; } private static (int, int) FindBrxTargetRange(Block block, int brxReg) @@ -369,41 +388,51 @@ namespace Ryujinx.Graphics.Shader.Decoders HashSet visited = new HashSet(); var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg); - if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index] is not OpCodeLdc opLdc) + if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc) { return (0, 0); } - if (opLdc.Slot != 1 || opLdc.IndexMode != CbIndexMode.Default) + GetOp(ldcLocation, out var opLdc); + + if (opLdc.CbufSlot != 1 || opLdc.AddressMode != 0) { return (0, 0); } - var shlLocation = FindFirstRegWrite(visited, ldcLocation, opLdc.Ra.Index); - if (shlLocation.Block == null || shlLocation.Block.OpCodes[shlLocation.Index] is not OpCodeAluImm opShl) + var shlLocation = FindFirstRegWrite(visited, ldcLocation, opLdc.SrcA); + if (shlLocation.Block == null || !shlLocation.IsImmInst(InstName.Shl)) { return (0, 0); } - if (opShl.Emitter != InstEmit.Shl || opShl.Immediate != 2) + GetOp(shlLocation, out var opShl); + + if (opShl.Imm20 != 2) { return (0, 0); } - var imnmxLocation = FindFirstRegWrite(visited, shlLocation, opShl.Ra.Index); - if (imnmxLocation.Block == null || imnmxLocation.Block.OpCodes[imnmxLocation.Index] is not OpCodeAluImm opImnmx) + var imnmxLocation = FindFirstRegWrite(visited, shlLocation, opShl.SrcA); + if (imnmxLocation.Block == null || !imnmxLocation.IsImmInst(InstName.Imnmx)) { return (0, 0); } - bool isImnmxS32 = opImnmx.RawOpCode.Extract(48); + GetOp(imnmxLocation, out var opImnmx); - if (opImnmx.Emitter != InstEmit.Imnmx || isImnmxS32 || !opImnmx.Predicate39.IsPT || opImnmx.InvertP) + if (opImnmx.Signed || opImnmx.SrcPred != RegisterConsts.PredicateTrueIndex || opImnmx.SrcPredInv) { return (0, 0); } - return (opLdc.Offset, opImnmx.Immediate + 1); + return (opLdc.CbufOffset, opImnmx.Imm20 + 1); + } + + private static void GetOp(BlockLocation location, out T op) where T : unmanaged + { + ulong rawOp = location.Block.OpCodes[location.Index].RawOpCode; + op = Unsafe.As(ref rawOp); } private struct BlockLocation @@ -416,6 +445,12 @@ namespace Ryujinx.Graphics.Shader.Decoders Block = block; Index = index; } + + public bool IsImmInst(InstName name) + { + InstOp op = Block.OpCodes[Index]; + return op.Name == name && op.Props.HasFlag(InstProps.Ib); + } } private static BlockLocation FindFirstRegWrite(HashSet visited, BlockLocation location, int regIndex) @@ -447,18 +482,20 @@ namespace Ryujinx.Graphics.Shader.Decoders return new BlockLocation(null, 0); } - private static bool WritesToRegister(OpCode opCode, int regIndex) + private static bool WritesToRegister(InstOp op, int regIndex) { // Predicate instruction only ever writes to predicate, so we shouldn't check those. - if (opCode.Emitter == InstEmit.Fsetp || - opCode.Emitter == InstEmit.Hsetp2 || - opCode.Emitter == InstEmit.Isetp || - opCode.Emitter == InstEmit.R2p) + if ((op.Props & (InstProps.Rd | InstProps.Rd2)) == 0) { return false; } - return opCode is IOpCodeRd opRd && opRd.Rd.Index == regIndex; + if (op.Props.HasFlag(InstProps.Rd2) && (byte)(op.RawOpCode >> 28) == regIndex) + { + return true; + } + + return (byte)op.RawOpCode == regIndex; } private enum MergeType @@ -527,14 +564,13 @@ namespace Ryujinx.Graphics.Shader.Decoders private static void PropagatePushOp(Dictionary blocks, Block currBlock, int pushOpIndex) { - OpCodePush pushOp = currBlock.PushOpCodes[pushOpIndex]; + PushOpInfo pushOpInfo = currBlock.PushOpCodes[pushOpIndex]; + InstOp pushOp = pushOpInfo.Op; Block target = blocks[pushOp.GetAbsoluteAddress()]; Stack workQueue = new Stack(); - HashSet visited = new HashSet(); - Stack<(ulong, MergeType)> branchStack = new Stack<(ulong, MergeType)>(); void Push(PathBlockState pbs) @@ -574,42 +610,30 @@ namespace Ryujinx.Graphics.Shader.Decoders } int pushOpsCount = current.PushOpCodes.Count; - if (pushOpsCount != 0) { Push(new PathBlockState(branchStack.Count)); for (int index = pushOpIndex; index < pushOpsCount; index++) { - OpCodePush currentPushOp = current.PushOpCodes[index]; - MergeType pushMergeType = currentPushOp.Emitter == InstEmit.Ssy ? MergeType.Sync : MergeType.Brk; + InstOp currentPushOp = current.PushOpCodes[index].Op; + MergeType pushMergeType = currentPushOp.Name == InstName.Ssy ? MergeType.Sync : MergeType.Brk; branchStack.Push((currentPushOp.GetAbsoluteAddress(), pushMergeType)); } } pushOpIndex = 0; - if (current.Next != null) + bool hasNext = current.HasNext(); + if (hasNext) { - Push(new PathBlockState(current.Next)); + Push(new PathBlockState(current.Successors[0])); } - if (current.Branch != null) + InstOp lastOp = current.GetLastOp(); + if (lastOp.Name == InstName.Sync || lastOp.Name == InstName.Brk) { - Push(new PathBlockState(current.Branch)); - } - else if (current.GetLastOp() is OpCodeBranchIndir brIndir) - { - // By adding them in descending order (sorted by address), we process the blocks - // in order (of ascending address), since we work with a LIFO. - foreach (Block possibleTarget in brIndir.PossibleTargets.OrderByDescending(x => x.Address)) - { - Push(new PathBlockState(possibleTarget)); - } - } - else if (current.GetLastOp() is OpCodeBranchPop op) - { - MergeType popMergeType = op.Emitter == InstEmit.Sync ? MergeType.Sync : MergeType.Brk; + MergeType popMergeType = lastOp.Name == InstName.Sync ? MergeType.Sync : MergeType.Brk; bool found = true; ulong targetAddress = 0UL; @@ -641,20 +665,32 @@ namespace Ryujinx.Graphics.Shader.Decoders { // If the entire stack was consumed, then the current pop instruction // just consumed the address from our push instruction. - if (op.Targets.TryAdd(pushOp, op.Targets.Count)) + if (current.SyncTargets.TryAdd(pushOp.Address, new SyncTarget(pushOpInfo, current.SyncTargets.Count))) { - pushOp.PopOps.Add(op, Local()); + pushOpInfo.Consumers.Add(current, Local()); target.Predecessors.Add(current); + current.Successors.Add(target); } } else { - // Push the block itself into the work "queue" (well, it's a stack) - // for processing. + // Push the block itself into the work queue for processing. Push(new PathBlockState(blocks[targetAddress])); } } } + else + { + // By adding them in descending order (sorted by address), we process the blocks + // in order (of ascending address), since we work with a LIFO. + foreach (Block possibleTarget in current.Successors.OrderByDescending(x => x.Address)) + { + if (!hasNext || possibleTarget != current.Successors[0]) + { + Push(new PathBlockState(possibleTarget)); + } + } + } } } } diff --git a/Ryujinx.Graphics.Shader/Decoders/DecoderHelper.cs b/Ryujinx.Graphics.Shader/Decoders/DecoderHelper.cs deleted file mode 100644 index 3585c35f..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/DecoderHelper.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - static class DecoderHelper - { - public static int DecodeS20Immediate(long opCode) - { - int imm = opCode.Extract(20, 19); - - bool sign = opCode.Extract(56); - - if (sign) - { - imm = (imm << 13) >> 13; - } - - return imm; - } - - public static int Decode2xF10Immediate(long opCode) - { - int immH0 = opCode.Extract(20, 9); - int immH1 = opCode.Extract(30, 9); - - bool negateH0 = opCode.Extract(29); - bool negateH1 = opCode.Extract(56); - - if (negateH0) - { - immH0 |= 1 << 9; - } - - if (negateH1) - { - immH1 |= 1 << 9; - } - - return immH1 << 22 | immH0 << 6; - } - - public static float DecodeF20Immediate(long opCode) - { - int imm = opCode.Extract(20, 19); - - bool negate = opCode.Extract(56); - - imm <<= 12; - - if (negate) - { - imm |= 1 << 31; - } - - return BitConverter.Int32BitsToSingle(imm); - } - - public static float DecodeD20Immediate(long opCode) - { - long imm = opCode.Extract(20, 19); - - bool negate = opCode.Extract(56); - - imm <<= 44; - - if (negate) - { - imm |= 1L << 63; - } - - return (float)BitConverter.Int64BitsToDouble(imm); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/FPHalfSwizzle.cs b/Ryujinx.Graphics.Shader/Decoders/FPHalfSwizzle.cs deleted file mode 100644 index 3ddf17cf..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/FPHalfSwizzle.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum FPHalfSwizzle - { - FP16 = 0, - FP32 = 1, - DupH0 = 2, - DupH1 = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/FPMultiplyScale.cs b/Ryujinx.Graphics.Shader/Decoders/FPMultiplyScale.cs deleted file mode 100644 index 398c0e66..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/FPMultiplyScale.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum FPMultiplyScale - { - None = 0, - Divide2 = 1, - Divide4 = 2, - Divide8 = 3, - Multiply8 = 4, - Multiply4 = 5, - Multiply2 = 6 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/FPType.cs b/Ryujinx.Graphics.Shader/Decoders/FPType.cs deleted file mode 100644 index b5af2c1d..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/FPType.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Ryujinx.Graphics.Shader.IntermediateRepresentation; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum FPType - { - FP16 = 1, - FP32 = 2, - FP64 = 3 - } - - static class FPTypeExtensions - { - public static Instruction ToInstFPType(this FPType type) - { - return type == FPType.FP64 ? Instruction.FP64 : Instruction.FP32; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCode.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCode.cs deleted file mode 100644 index dd6ad79a..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCode.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCode - { - InstEmitter Emitter { get; } - - ulong Address { get; } - long RawOpCode { get; } - - Register Predicate { get; } - - bool InvertPredicate { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeAlu.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeAlu.cs deleted file mode 100644 index 6d1382a8..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeAlu.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeAlu : IOpCodeRd, IOpCodeRa, IOpCodePredicate39 - { - bool Extended { get; } - bool SetCondCode { get; } - bool Saturate { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs deleted file mode 100644 index 2b6835be..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeAttribute.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeAttribute : IOpCode - { - int AttributeOffset { get; } - int Count { get; } - bool Indexed { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeCbuf.cs deleted file mode 100644 index 42a17451..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeCbuf.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeCbuf : IOpCode - { - int Offset { get; } - int Slot { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeFArith.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeFArith.cs deleted file mode 100644 index 3d06eae0..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeFArith.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeFArith : IOpCodeAlu - { - RoundingMode RoundingMode { get; } - - FPMultiplyScale Scale { get; } - - bool FlushToZero { get; } - bool AbsoluteA { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeHfma.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeHfma.cs deleted file mode 100644 index 4638f660..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeHfma.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeHfma : IOpCode - { - bool NegateB { get; } - bool NegateC { get; } - bool Saturate { get; } - - FPHalfSwizzle SwizzleA { get; } - FPHalfSwizzle SwizzleB { get; } - FPHalfSwizzle SwizzleC { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeImm.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeImm.cs deleted file mode 100644 index 9cfcd69b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeImm.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeImm : IOpCode - { - int Immediate { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeImmF.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeImmF.cs deleted file mode 100644 index 629eff79..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeImmF.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeImmF : IOpCode - { - float Immediate { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeLop.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeLop.cs deleted file mode 100644 index 62c87bf4..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeLop.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeLop : IOpCodeAlu - { - LogicalOperation LogicalOp { get; } - - bool InvertA { get; } - bool InvertB { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodePredicate39.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodePredicate39.cs deleted file mode 100644 index 74e7aff1..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodePredicate39.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodePredicate39 - { - Register Predicate39 { get; } - - bool InvertP { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRa.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeRa.cs deleted file mode 100644 index e5902110..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRa.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeRa : IOpCode - { - Register Ra { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRc.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeRc.cs deleted file mode 100644 index bb806b95..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRc.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeRc : IOpCode - { - Register Rc { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRd.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeRd.cs deleted file mode 100644 index 099c4061..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRd.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeRd : IOpCode - { - Register Rd { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeReg.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeReg.cs deleted file mode 100644 index 3ed157e8..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeReg.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeReg : IOpCode - { - Register Rb { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRegCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeRegCbuf.cs deleted file mode 100644 index 429f01bb..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeRegCbuf.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeRegCbuf : IOpCodeRc - { - int Offset { get; } - int Slot { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeTexture.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeTexture.cs deleted file mode 100644 index eb835449..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeTexture.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeTexture : IOpCode - { - Register Rd { get; } - Register Ra { get; } - Register Rb { get; } - - bool IsArray { get; } - - TextureDimensions Dimensions { get; } - - int ComponentMask { get; } - - int HandleOffset { get; } - - TextureLodMode LodMode { get; } - - bool HasOffset { get; } - bool HasDepthCompare { get; } - bool IsMultisample { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IOpCodeTld4.cs b/Ryujinx.Graphics.Shader/Decoders/IOpCodeTld4.cs deleted file mode 100644 index 219d00cb..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IOpCodeTld4.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - interface IOpCodeTld4 : IOpCodeTexture - { - TextureGatherOffset Offset { get; } - - int GatherCompIndex { get; } - - bool Bindless { get; } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs b/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs deleted file mode 100644 index 348a4768..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/ImageComponents.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ImageComponents - { - Red = 1 << 0, - Green = 1 << 1, - Blue = 1 << 2, - Alpha = 1 << 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/ImageDimensions.cs b/Ryujinx.Graphics.Shader/Decoders/ImageDimensions.cs deleted file mode 100644 index ecf41a82..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/ImageDimensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ImageDimensions - { - Image1D, - ImageBuffer, - Image1DArray, - Image2D, - Image2DArray, - Image3D - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs new file mode 100644 index 00000000..5e7c40f4 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/InstDecoders.cs @@ -0,0 +1,5362 @@ +namespace Ryujinx.Graphics.Shader.Decoders +{ + enum AlSize + { + _32 = 0, + _64 = 1, + _96 = 2, + _128 = 3, + } + + enum AtomSize + { + U32 = 0, + S32 = 1, + U64 = 2, + F32FtzRn = 3, + F16x2FtzRn = 4, + S64 = 5, + } + + enum AtomOp + { + Add = 0, + Min = 1, + Max = 2, + Inc = 3, + Dec = 4, + And = 5, + Or = 6, + Xor = 7, + Exch = 8, + Safeadd = 10, + } + + enum AtomsSize + { + U32 = 0, + S32 = 1, + U64 = 2, + S64 = 3, + } + + enum BarMode + { + Bar = 0, + Result = 1, + Warp = 2, + } + + enum BarOp + { + Sync = 0, + Arv = 1, + Red = 2, + Scan = 3, + SyncAll = 4, + } + + enum BarRedOp + { + Popc = 0, + And = 1, + Or = 2, + } + + enum Bpt + { + DrainIllegal = 0, + Cal = 1, + Pause = 2, + Trap = 3, + Int = 4, + Drain = 5, + } + + enum Ccc + { + F = 0, + Lt = 1, + Eq = 2, + Le = 3, + Gt = 4, + Ne = 5, + Ge = 6, + Num = 7, + Nan = 8, + Ltu = 9, + Equ = 10, + Leu = 11, + Gtu = 12, + Neu = 13, + Geu = 14, + T = 15, + Lo = 17, + Sff = 18, + Ls = 19, + Hi = 20, + Sft = 21, + Hs = 22, + Oft = 23, + CsmTa = 24, + CsmTr = 25, + CsmMx = 26, + FcsmTa = 27, + FcsmTr = 28, + FcsmMx = 29, + Rle = 30, + Rgt = 31, + } + + enum CacheType + { + U = 1, + C = 2, + I = 3, + Crs = 4, + } + + enum CctlOp + { + Pf1 = 1, + Pf1_5 = 2, + Pf2 = 3, + Wb = 4, + Iv = 5, + Ivall = 6, + Rs = 7, + Rslb = 9, + } + + enum CctltOp + { + Ivth = 1, + } + + enum BoolOp + { + And = 0, + Or = 1, + Xor = 2, + } + + enum SReg + { + LaneId = 0, + Clock = 1, + VirtCfg = 2, + VirtId = 3, + Pm0 = 4, + Pm1 = 5, + Pm2 = 6, + Pm3 = 7, + Pm4 = 8, + Pm5 = 9, + Pm6 = 10, + Pm7 = 11, + OrderingTicket = 15, + PrimType = 16, + InvocationId = 17, + YDirection = 18, + ThreadKill = 19, + ShaderType = 20, + DirectCbeWriteAddressLow = 21, + DirectCbeWriteAddressHigh = 22, + DirectCbeWriteEnabled = 23, + MachineId0 = 24, + MachineId1 = 25, + MachineId2 = 26, + MachineId3 = 27, + Affinity = 28, + InvocationInfo = 29, + WScaleFactorXY = 30, + WScaleFactorZ = 31, + TId = 32, + TIdX = 33, + TIdY = 34, + TIdZ = 35, + CtaParam = 36, + CtaIdX = 37, + CtaIdY = 38, + CtaIdZ = 39, + Ntid = 40, + CirQueueIncrMinusOne = 41, + Nlatc = 42, + Swinlo = 48, + Swinsz = 49, + Smemsz = 50, + Smembanks = 51, + LWinLo = 52, + LWinSz = 53, + LMemLoSz = 54, + LMemHiOff = 55, + EqMask = 56, + LtMask = 57, + LeMask = 58, + GtMask = 59, + GeMask = 60, + RegAlloc = 61, + CtxAddr = 62, + GlobalErrorStatus = 64, + WarpErrorStatus = 66, + WarpErrorStatusClear = 67, + PmHi0 = 72, + PmHi1 = 73, + PmHi2 = 74, + PmHi3 = 75, + PmHi4 = 76, + PmHi5 = 77, + PmHi6 = 78, + PmHi7 = 79, + ClockLo = 80, + ClockHi = 81, + GlobalTimerLo = 82, + GlobalTimerHi = 83, + HwTaskId = 96, + CircularQueueEntryIndex = 97, + CircularQueueEntryAddressLow = 98, + CircularQueueEntryAddressHigh = 99, + } + + enum RoundMode + { + Rn = 0, + Rm = 1, + Rp = 2, + Rz = 3, + } + + enum FComp + { + F = 0, + Lt = 1, + Eq = 2, + Le = 3, + Gt = 4, + Ne = 5, + Ge = 6, + Num = 7, + Nan = 8, + Ltu = 9, + Equ = 10, + Leu = 11, + Gtu = 12, + Neu = 13, + Geu = 14, + T = 15, + } + + enum IntegerRound + { + Pass = 1, + Round = 4, + Floor = 5, + Ceil = 6, + Trunc = 7, + } + + enum IDstFmt + { + U16 = 1, + U32 = 2, + U64 = 3, + S16 = 5, + S32 = 6, + S64 = 7, + } + + enum ISrcFmt + { + U8 = 0, + U16 = 1, + U32 = 2, + U64 = 3, + S8 = 4, + S16 = 5, + S32 = 6, + S64 = 7, + } + + enum RoundMode2 + { + Round = 0, + Floor = 1, + Ceil = 2, + Trunc = 3, + } + + enum ChkModeF + { + Divide = 0, + } + + enum Fmz + { + Ftz = 1, + Fmz = 2, + } + + enum MultiplyScale + { + NoScale = 0, + D2 = 1, + D4 = 2, + D8 = 3, + M8 = 4, + M4 = 5, + M2 = 6, + } + + enum OFmt + { + F16 = 0, + F32 = 1, + MrgH0 = 2, + MrgH1 = 3, + } + + enum HalfSwizzle + { + F16 = 0, + F32 = 1, + H0H0 = 2, + H1H1 = 3, + } + + enum ByteSel + { + B0 = 0, + B1 = 1, + B2 = 2, + B3 = 3, + } + + enum DstFmt + { + F16 = 1, + F32 = 2, + F64 = 3, + } + + enum AvgMode + { + NoNeg = 0, + NegB = 1, + NegA = 2, + PlusOne = 3, + } + + enum Lrs + { + None = 0, + RightShift = 1, + LeftShift = 2, + } + + enum HalfSelect + { + B32 = 0, + H0 = 1, + H1 = 2, + } + + enum IComp + { + F = 0, + Lt = 1, + Eq = 2, + Le = 3, + Gt = 4, + Ne = 5, + Ge = 6, + T = 7, + } + + enum XMode + { + Xlo = 1, + Xmed = 2, + Xhi = 3, + } + + enum IpaOp + { + Pass = 0, + Multiply = 1, + Constant = 2, + Sc = 3, + } + + enum IBase + { + Patch = 1, + Prim = 2, + Attr = 3, + } + + enum CacheOp + { + Cg = 1, + Ci = 2, + Cv = 3, + } + + enum LsSize + { + U8 = 0, + S8 = 1, + U16 = 2, + S16 = 3, + B32 = 4, + B64 = 5, + B128 = 6, + UB128 = 7, + } + + enum LsSize2 + { + U8 = 0, + S8 = 1, + U16 = 2, + S16 = 3, + B32 = 4, + B64 = 5, + B128 = 6, + } + + enum AddressMode + { + Il = 1, + Is = 2, + Isl = 3, + } + + enum CacheOp2 + { + Lu = 1, + Ci = 2, + Cv = 3, + } + + enum PredicateOp + { + F = 0, + T = 1, + Z = 2, + Nz = 3, + } + + enum LogicOp + { + And = 0, + Or = 1, + Xor = 2, + PassB = 3, + } + + enum Membar + { + Cta = 0, + Gl = 1, + Sys = 2, + Vc = 3, + } + + enum Ivall + { + Ivalld = 1, + Ivallt = 2, + Ivalltd = 3, + } + + enum MufuOp + { + Cos = 0, + Sin = 1, + Ex2 = 2, + Lg2 = 3, + Rcp = 4, + Rsq = 5, + Rcp64h = 6, + Rsq64h = 7, + Sqrt = 8, + } + + enum OutType + { + Emit = 1, + Cut = 2, + EmitThenCut = 3, + } + + enum PixMode + { + Covmask = 1, + Covered = 2, + Offset = 3, + CentroidOffset = 4, + MyIndex = 5, + } + + enum PMode + { + F4e = 1, + B4e = 2, + Rc8 = 3, + Ecl = 4, + Ecr = 5, + Rc16 = 6, + } + + enum RedOp + { + Add = 0, + Min = 1, + Max = 2, + Inc = 3, + Dec = 4, + And = 5, + Or = 6, + Xor = 7, + } + + enum XModeShf + { + Hi = 1, + X = 2, + Xhi = 3, + } + + enum MaxShift + { + U64 = 2, + S64 = 3, + } + + enum ShflMode + { + Idx = 0, + Up = 1, + Down = 2, + Bfly = 3, + } + + enum Clamp + { + Ign = 0, + Trap = 2, + } + + enum SuatomSize + { + U32 = 0, + S32 = 1, + U64 = 2, + F32FtzRn = 3, + F16x2FtzRn = 4, + S64 = 5, + Sd32 = 6, + Sd64 = 7, + } + + enum SuDim + { + _1d = 0, + _1dBuffer = 1, + _1dArray = 2, + _2d = 3, + _2dArray = 4, + _3d = 5, + } + + enum SuatomOp + { + Add = 0, + Min = 1, + Max = 2, + Inc = 3, + Dec = 4, + And = 5, + Or = 6, + Xor = 7, + Exch = 8, + } + + enum SuSize + { + U8 = 0, + S8 = 1, + U16 = 2, + S16 = 3, + B32 = 4, + B64 = 5, + B128 = 6, + UB128 = 7, + } + + enum SuRgba + { + R = 1, + G = 2, + Rg = 3, + B = 4, + Rb = 5, + Gb = 6, + Rgb = 7, + A = 8, + Ra = 9, + Ga = 10, + Rga = 11, + Ba = 12, + Rba = 13, + Gba = 14, + Rgba = 15, + } + + enum Lod + { + Lz = 1, + Lb = 2, + Ll = 3, + Lba = 6, + Lla = 7, + } + + enum TexDim + { + _1d = 0, + Array1d = 1, + _2d = 2, + Array2d = 3, + _3d = 4, + Array3d = 5, + Cube = 6, + ArrayCube = 7, + } + + enum TexsTarget + { + Texture1DLodZero = 0, + Texture2D = 1, + Texture2DLodZero = 2, + Texture2DLodLevel = 3, + Texture2DDepthCompare = 4, + Texture2DLodLevelDepthCompare = 5, + Texture2DLodZeroDepthCompare = 6, + Texture2DArray = 7, + Texture2DArrayLodZero = 8, + Texture2DArrayLodZeroDepthCompare = 9, + Texture3D = 10, + Texture3DLodZero = 11, + TextureCube = 12, + TextureCubeLodLevel = 13, + } + + enum TldsTarget + { + Texture1DLodZero = 0x0, + Texture1DLodLevel = 0x1, + Texture2DLodZero = 0x2, + Texture2DLodZeroOffset = 0x4, + Texture2DLodLevel = 0x5, + Texture2DLodZeroMultisample = 0x6, + Texture3DLodZero = 0x7, + Texture2DArrayLodZero = 0x8, + Texture2DLodLevelOffset = 0xc + } + + enum TexComp + { + R = 0, + G = 1, + B = 2, + A = 3, + } + + enum TexOffset + { + None = 0, + Aoffi = 1, + Ptp = 2, + } + + enum TexQuery + { + TexHeaderDimension = 1, + TexHeaderTextureType = 2, + TexHeaderSamplerPos = 5, + TexSamplerFilter = 16, + TexSamplerLod = 18, + TexSamplerWrap = 20, + TexSamplerBorderColor = 22, + } + + enum VectorSelect + { + U8B0 = 0, + U8B1 = 1, + U8B2 = 2, + U8B3 = 3, + U16H0 = 4, + U16H1 = 5, + U32 = 6, + S8B0 = 8, + S8B1 = 9, + S8B2 = 10, + S8B3 = 11, + S16H0 = 12, + S16H1 = 13, + S32 = 14, + } + + enum VideoOp + { + Mrg16h = 0, + Mrg16l = 1, + Mrg8b0 = 2, + Mrg8b2 = 3, + Acc = 4, + Min = 5, + Max = 6, + } + + enum VideoRed + { + Acc = 1, + } + + enum LaneMask4 + { + Z = 1, + W = 2, + Zw = 3, + X = 4, + Xz = 5, + Xw = 6, + Xzw = 7, + Y = 8, + Yz = 9, + Yw = 10, + Yzw = 11, + Xy = 12, + Xyz = 13, + Xyw = 14, + Xyzw = 15, + } + + enum ASelect4 + { + _0000 = 0, + _1111 = 1, + _2222 = 2, + _3333 = 3, + _3210 = 4, + _5432 = 6, + _6543 = 7, + _3201 = 8, + _3012 = 9, + _0213 = 10, + _3120 = 11, + _1230 = 12, + _2310 = 13, + } + + enum BSelect4 + { + _4444 = 0, + _5555 = 1, + _6666 = 2, + _7777 = 3, + _7654 = 4, + _5432 = 6, + _4321 = 7, + _4567 = 8, + _6745 = 9, + _5476 = 10, + } + + enum VideoScale + { + Shr7 = 1, + Shr15 = 2, + } + + enum VoteMode + { + All = 0, + Any = 1, + Eq = 2, + } + + enum XmadCop + { + Cfull = 0, + Clo = 1, + Chi = 2, + Csfu = 3, + Cbcc = 4, + } + + enum XmadCop2 + { + Cfull = 0, + Clo = 1, + Chi = 2, + Csfu = 3, + } + + enum ImadspASelect + { + U32 = 0, + S32 = 1, + U24 = 2, + S24 = 3, + U16h0 = 4, + S16h0 = 5, + U16h1 = 6, + S16h1 = 7, + } + + enum ImadspBSelect + { + U24 = 0, + S24 = 1, + U16h0 = 2, + S16h0 = 3, + } + + struct InstConditional + { + private ulong _opcode; + public InstConditional(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstAl2p + { + private ulong _opcode; + public InstAl2p(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public AlSize AlSize => (AlSize)((_opcode >> 47) & 0x3); + public bool Aio => (_opcode & 0x100000000) != 0; + public int Imm11 => (int)((_opcode >> 20) & 0x7FF); + public int DestPred => (int)((_opcode >> 44) & 0x7); + } + + struct InstAld + { + private ulong _opcode; + public InstAld(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm11 => (int)((_opcode >> 20) & 0x7FF); + public bool P => (_opcode & 0x80000000) != 0; + public bool O => (_opcode & 0x100000000) != 0; + public AlSize AlSize => (AlSize)((_opcode >> 47) & 0x3); + public bool Phys => !P && Imm11 == 0 && SrcA != RegisterConsts.RegisterZeroIndex; + } + + struct InstAst + { + private ulong _opcode; + public InstAst(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 0) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm11 => (int)((_opcode >> 20) & 0x7FF); + public bool P => (_opcode & 0x80000000) != 0; + public AlSize AlSize => (AlSize)((_opcode >> 47) & 0x3); + public bool Phys => !P && Imm11 == 0 && SrcA != RegisterConsts.RegisterZeroIndex; + } + + struct InstAtom + { + private ulong _opcode; + public InstAtom(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm20 => (int)((_opcode >> 28) & 0xFFFFF); + public AtomSize Size => (AtomSize)((_opcode >> 49) & 0x7); + public AtomOp Op => (AtomOp)((_opcode >> 52) & 0xF); + public bool E => (_opcode & 0x1000000000000) != 0; + } + + struct InstAtomCas + { + private ulong _opcode; + public InstAtomCas(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int BcRz => (int)((_opcode >> 50) & 0x3); + public bool E => (_opcode & 0x1000000000000) != 0; + } + + struct InstAtoms + { + private ulong _opcode; + public InstAtoms(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm22 => (int)((_opcode >> 30) & 0x3FFFFF); + public AtomsSize AtomsSize => (AtomsSize)((_opcode >> 28) & 0x3); + public AtomOp AtomOp => (AtomOp)((_opcode >> 52) & 0xF); + } + + struct InstAtomsCas + { + private ulong _opcode; + public InstAtomsCas(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int AtomsBcRz => (int)((_opcode >> 28) & 0x3); + } + + struct InstB2r + { + private ulong _opcode; + public InstB2r(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int DestPred => (int)((_opcode >> 45) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public BarMode Mode => (BarMode)((_opcode >> 32) & 0x3); + } + + struct InstBar + { + private ulong _opcode; + public InstBar(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm12 => (int)((_opcode >> 20) & 0xFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public BarOp BarOp => (BarOp)((_opcode >> 32) & 0x7); + public BarRedOp BarRedOp => (BarRedOp)((_opcode >> 35) & 0x3); + public bool AFixBar => (_opcode & 0x100000000000) != 0; + public bool BFixBar => (_opcode & 0x80000000000) != 0; + } + + struct InstBfeR + { + private ulong _opcode; + public InstBfeR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Brev => (_opcode & 0x10000000000) != 0; + } + + struct InstBfeI + { + private ulong _opcode; + public InstBfeI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Brev => (_opcode & 0x10000000000) != 0; + } + + struct InstBfeC + { + private ulong _opcode; + public InstBfeC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Brev => (_opcode & 0x10000000000) != 0; + } + + struct InstBfiR + { + private ulong _opcode; + public InstBfiR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + } + + struct InstBfiI + { + private ulong _opcode; + public InstBfiI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + } + + struct InstBfiC + { + private ulong _opcode; + public InstBfiC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + } + + struct InstBfiRc + { + private ulong _opcode; + public InstBfiRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + } + + struct InstBpt + { + private ulong _opcode; + public InstBpt(ulong opcode) => _opcode = opcode; + public int Imm20 => (int)((_opcode >> 20) & 0xFFFFF); + public Bpt Bpt => (Bpt)((_opcode >> 6) & 0x7); + } + + struct InstBra + { + private ulong _opcode; + public InstBra(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + public bool Lmt => (_opcode & 0x40) != 0; + public bool U => (_opcode & 0x80) != 0; + } + + struct InstBrk + { + private ulong _opcode; + public InstBrk(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstBrx + { + private ulong _opcode; + public InstBrx(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + public bool Lmt => (_opcode & 0x40) != 0; + } + + struct InstCal + { + private ulong _opcode; + public InstCal(ulong opcode) => _opcode = opcode; + public bool Ca => (_opcode & 0x20) != 0; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Inc => (_opcode & 0x40) != 0; + } + + struct InstCctl + { + private ulong _opcode; + public InstCctl(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm30 => (int)((_opcode >> 22) & 0x3FFFFFFF); + public bool E => (_opcode & 0x10000000000000) != 0; + public CacheType Cache => (CacheType)((_opcode >> 4) & 0x7); + public CctlOp CctlOp => (CctlOp)((_opcode >> 0) & 0xF); + } + + struct InstCctll + { + private ulong _opcode; + public InstCctll(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm22 => (int)((_opcode >> 22) & 0x3FFFFF); + public int Cache => (int)((_opcode >> 4) & 0x3); + public CctlOp CctlOp => (CctlOp)((_opcode >> 0) & 0xF); + } + + struct InstCctlt + { + private ulong _opcode; + public InstCctlt(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int TsIdx13 => (int)((_opcode >> 36) & 0x1FFF); + public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3); + } + + struct InstCctltR + { + private ulong _opcode; + public InstCctltR(ulong opcode) => _opcode = opcode; + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3); + } + + struct InstContUnsup + { + private ulong _opcode; + public InstContUnsup(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstCsetUnsup + { + private ulong _opcode; + public InstCsetUnsup(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 8) & 0x1F); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool BVal => (_opcode & 0x100000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + } + + struct InstCsetp + { + private ulong _opcode; + public InstCsetp(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 8) & 0x1F); + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + } + + struct InstCs2r + { + private ulong _opcode; + public InstCs2r(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public SReg SReg => (SReg)((_opcode >> 20) & 0xFF); + } + + struct InstDaddR + { + private ulong _opcode; + public InstDaddR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstDaddI + { + private ulong _opcode; + public InstDaddI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstDaddC + { + private ulong _opcode; + public InstDaddC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstDepbar + { + private ulong _opcode; + public InstDepbar(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Le => (_opcode & 0x20000000) != 0; + public int Sbid => (int)((_opcode >> 26) & 0x7); + public int PendCnt => (int)((_opcode >> 20) & 0x3F); + public int Imm6 => (int)((_opcode >> 0) & 0x3F); + } + + struct InstDfmaR + { + private ulong _opcode; + public InstDfmaR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 50) & 0x3); + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDfmaI + { + private ulong _opcode; + public InstDfmaI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 50) & 0x3); + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDfmaC + { + private ulong _opcode; + public InstDfmaC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 50) & 0x3); + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDfmaRc + { + private ulong _opcode; + public InstDfmaRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 50) & 0x3); + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDmnmxR + { + private ulong _opcode; + public InstDmnmxR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDmnmxI + { + private ulong _opcode; + public InstDmnmxI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDmnmxC + { + private ulong _opcode; + public InstDmnmxC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDmulR + { + private ulong _opcode; + public InstDmulR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDmulI + { + private ulong _opcode; + public InstDmulI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDmulC + { + private ulong _opcode; + public InstDmulC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public bool NegA => (_opcode & 0x1000000000000) != 0; + } + + struct InstDsetR + { + private ulong _opcode; + public InstDsetR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDsetI + { + private ulong _opcode; + public InstDsetI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDsetC + { + private ulong _opcode; + public InstDsetC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstDsetpR + { + private ulong _opcode; + public InstDsetpR(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool AbsA => (_opcode & 0x80) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstDsetpI + { + private ulong _opcode; + public InstDsetpI(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool AbsA => (_opcode & 0x80) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstDsetpC + { + private ulong _opcode; + public InstDsetpC(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool AbsB => (_opcode & 0x100000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool AbsA => (_opcode & 0x80) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstExit + { + private ulong _opcode; + public InstExit(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + public bool KeepRefCnt => (_opcode & 0x20) != 0; + } + + struct InstF2fR + { + private ulong _opcode; + public InstF2fR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public IntegerRound RoundMode => (IntegerRound)((int)((_opcode >> 40) & 0x4) | (int)((_opcode >> 39) & 0x3)); + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstF2fI + { + private ulong _opcode; + public InstF2fI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public IntegerRound RoundMode => (IntegerRound)((int)((_opcode >> 40) & 0x4) | (int)((_opcode >> 39) & 0x3)); + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstF2fC + { + private ulong _opcode; + public InstF2fC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public IntegerRound RoundMode => (IntegerRound)((int)((_opcode >> 40) & 0x4) | (int)((_opcode >> 39) & 0x3)); + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstF2iR + { + private ulong _opcode; + public InstF2iR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public RoundMode2 RoundMode => (RoundMode2)((_opcode >> 39) & 0x3); + } + + struct InstF2iI + { + private ulong _opcode; + public InstF2iI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public RoundMode2 RoundMode => (RoundMode2)((_opcode >> 39) & 0x3); + } + + struct InstF2iC + { + private ulong _opcode; + public InstF2iC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public DstFmt SrcFmt => (DstFmt)((_opcode >> 10) & 0x3); + public RoundMode2 RoundMode => (RoundMode2)((_opcode >> 39) & 0x3); + } + + struct InstFaddR + { + private ulong _opcode; + public InstFaddR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstFaddI + { + private ulong _opcode; + public InstFaddI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstFaddC + { + private ulong _opcode; + public InstFaddC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + } + + struct InstFadd32i + { + private ulong _opcode; + public InstFadd32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool AbsB => (_opcode & 0x200000000000000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public bool Ftz => (_opcode & 0x80000000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + } + + struct InstFchkR + { + private ulong _opcode; + public InstFchkR(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ChkModeF ChkModeF => (ChkModeF)((_opcode >> 39) & 0x3F); + } + + struct InstFchkI + { + private ulong _opcode; + public InstFchkI(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ChkModeF ChkModeF => (ChkModeF)((_opcode >> 39) & 0x3F); + } + + struct InstFchkC + { + private ulong _opcode; + public InstFchkC(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ChkModeF ChkModeF => (ChkModeF)((_opcode >> 39) & 0x3F); + } + + struct InstFcmpR + { + private ulong _opcode; + public InstFcmpR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFcmpI + { + private ulong _opcode; + public InstFcmpI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFcmpC + { + private ulong _opcode; + public InstFcmpC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFcmpRc + { + private ulong _opcode; + public InstFcmpRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFfmaR + { + private ulong _opcode; + public InstFfmaR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 51) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + } + + struct InstFfmaI + { + private ulong _opcode; + public InstFfmaI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 51) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + } + + struct InstFfmaC + { + private ulong _opcode; + public InstFfmaC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 51) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + } + + struct InstFfmaRc + { + private ulong _opcode; + public InstFfmaRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 51) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + } + + struct InstFfma32i + { + private ulong _opcode; + public InstFfma32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm32 => (int)(_opcode >> 20); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegC => (_opcode & 0x200000000000000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public bool Sat => (_opcode & 0x80000000000000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + } + + struct InstFloR + { + private ulong _opcode; + public InstFloR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstFloI + { + private ulong _opcode; + public InstFloI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstFloC + { + private ulong _opcode; + public InstFloC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public bool Sh => (_opcode & 0x20000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstFmnmxR + { + private ulong _opcode; + public InstFmnmxR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstFmnmxI + { + private ulong _opcode; + public InstFmnmxI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstFmnmxC + { + private ulong _opcode; + public InstFmnmxC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstFmulR + { + private ulong _opcode; + public InstFmulR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 44) & 0x3); + public MultiplyScale Scale => (MultiplyScale)((_opcode >> 41) & 0x7); + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstFmulI + { + private ulong _opcode; + public InstFmulI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 44) & 0x3); + public MultiplyScale Scale => (MultiplyScale)((_opcode >> 41) & 0x7); + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstFmulC + { + private ulong _opcode; + public InstFmulC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public Fmz Fmz => (Fmz)((_opcode >> 44) & 0x3); + public MultiplyScale Scale => (MultiplyScale)((_opcode >> 41) & 0x7); + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstFmul32i + { + private ulong _opcode; + public InstFmul32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 53) & 0x3); + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + } + + struct InstFsetR + { + private ulong _opcode; + public InstFsetR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x80000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + } + + struct InstFsetC + { + private ulong _opcode; + public InstFsetC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x80000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + } + + struct InstFsetI + { + private ulong _opcode; + public InstFsetI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x20000000000000) != 0; + public bool AbsA => (_opcode & 0x40000000000000) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x80000000000000) != 0; + public bool BVal => (_opcode & 0x10000000000000) != 0; + } + + struct InstFsetpR + { + private ulong _opcode; + public InstFsetpR(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public bool AbsA => (_opcode & 0x80) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFsetpI + { + private ulong _opcode; + public InstFsetpI(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public bool AbsA => (_opcode & 0x80) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFsetpC + { + private ulong _opcode; + public InstFsetpC(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x40) != 0; + public bool AbsA => (_opcode & 0x80) != 0; + public bool AbsB => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 48) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x800000000000) != 0; + } + + struct InstFswzadd + { + private ulong _opcode; + public InstFswzadd(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Ftz => (_opcode & 0x100000000000) != 0; + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public bool Ndv => (_opcode & 0x4000000000) != 0; + public int PnWord => (int)((_opcode >> 28) & 0xFF); + } + + struct InstGetcrsptr + { + private ulong _opcode; + public InstGetcrsptr(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + } + + struct InstGetlmembase + { + private ulong _opcode; + public InstGetlmembase(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + } + + struct InstHadd2R + { + private ulong _opcode; + public InstHadd2R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle BSwizzle => (HalfSwizzle)((_opcode >> 28) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x80000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000) != 0; + public bool Sat => (_opcode & 0x100000000) != 0; + public bool Ftz => (_opcode & 0x8000000000) != 0; + } + + struct InstHadd2I + { + private ulong _opcode; + public InstHadd2I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int BimmH0 => (int)((_opcode >> 20) & 0x3FF); + public int BimmH1 => (int)((_opcode >> 47) & 0x200) | (int)((_opcode >> 30) & 0x1FF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public bool Ftz => (_opcode & 0x8000000000) != 0; + } + + struct InstHadd2C + { + private ulong _opcode; + public InstHadd2C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x100000000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public bool Ftz => (_opcode & 0x8000000000) != 0; + } + + struct InstHadd232i + { + private ulong _opcode; + public InstHadd232i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm => (int)(_opcode >> 20); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 53) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public bool Ftz => (_opcode & 0x80000000000000) != 0; + } + + struct InstHfma2R + { + private ulong _opcode; + public InstHfma2R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle BSwizzle => (HalfSwizzle)((_opcode >> 28) & 0x3); + public HalfSwizzle CSwizzle => (HalfSwizzle)((_opcode >> 35) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000) != 0; + public bool NegC => (_opcode & 0x40000000) != 0; + public bool Sat => (_opcode & 0x100000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 37) & 0x3); + } + + struct InstHfma2I + { + private ulong _opcode; + public InstHfma2I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int BimmH0 => (int)((_opcode >> 20) & 0x3FF); + public int BimmH1 => (int)((_opcode >> 47) & 0x200) | (int)((_opcode >> 30) & 0x1FF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle CSwizzle => (HalfSwizzle)((_opcode >> 53) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegC => (_opcode & 0x8000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 57) & 0x3); + } + + struct InstHfma2C + { + private ulong _opcode; + public InstHfma2C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle CSwizzle => (HalfSwizzle)((_opcode >> 53) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public bool NegC => (_opcode & 0x8000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 57) & 0x3); + } + + struct InstHfma2Rc + { + private ulong _opcode; + public InstHfma2Rc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle CSwizzle => (HalfSwizzle)((_opcode >> 53) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public bool NegC => (_opcode & 0x8000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 57) & 0x3); + } + + struct InstHfma232i + { + private ulong _opcode; + public InstHfma232i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm => (int)(_opcode >> 20); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegC => (_opcode & 0x8000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 57) & 0x3); + } + + struct InstHmul2R + { + private ulong _opcode; + public InstHmul2R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle BSwizzle => (HalfSwizzle)((_opcode >> 28) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000) != 0; + public bool Sat => (_opcode & 0x100000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 39) & 0x3); + } + + struct InstHmul2I + { + private ulong _opcode; + public InstHmul2I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int BimmH0 => (int)((_opcode >> 20) & 0x3FF); + public int BimmH1 => (int)((_opcode >> 47) & 0x200) | (int)((_opcode >> 30) & 0x1FF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 39) & 0x3); + } + + struct InstHmul2C + { + private ulong _opcode; + public InstHmul2C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public OFmt OFmt => (OFmt)((_opcode >> 49) & 0x3); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000000000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 39) & 0x3); + } + + struct InstHmul232i + { + private ulong _opcode; + public InstHmul232i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm32 => (int)(_opcode >> 20); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 53) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Sat => (_opcode & 0x10000000000000) != 0; + public Fmz Fmz => (Fmz)((_opcode >> 55) & 0x3); + } + + struct InstHset2R + { + private ulong _opcode; + public InstHset2R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle BSwizzle => (HalfSwizzle)((_opcode >> 28) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool NegB => (_opcode & 0x80000000) != 0; + public bool AbsB => (_opcode & 0x40000000) != 0; + public bool Bval => (_opcode & 0x2000000000000) != 0; + public FComp Cmp => (FComp)((_opcode >> 35) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool Ftz => (_opcode & 0x4000000000000) != 0; + } + + struct InstHset2I + { + private ulong _opcode; + public InstHset2I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int BimmH0 => (int)((_opcode >> 20) & 0x3FF); + public int BimmH1 => (int)((_opcode >> 47) & 0x200) | (int)((_opcode >> 30) & 0x1FF); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool Bval => (_opcode & 0x20000000000000) != 0; + public FComp Cmp => (FComp)((_opcode >> 49) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool Ftz => (_opcode & 0x40000000000000) != 0; + } + + struct InstHset2C + { + private ulong _opcode; + public InstHset2C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool NegB => (_opcode & 0x100000000000000) != 0; + public bool Bval => (_opcode & 0x20000000000000) != 0; + public FComp Cmp => (FComp)((_opcode >> 49) & 0xF); + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool Ftz => (_opcode & 0x40000000000000) != 0; + } + + struct InstHsetp2R + { + private ulong _opcode; + public InstHsetp2R(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x80000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000) != 0; + public FComp FComp2 => (FComp)((_opcode >> 35) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x40) != 0; + public bool HAnd => (_opcode & 0x2000000000000) != 0; + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + public HalfSwizzle BSwizzle => (HalfSwizzle)((_opcode >> 28) & 0x3); + } + + struct InstHsetp2I + { + private ulong _opcode; + public InstHsetp2I(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int BimmH0 => (int)((_opcode >> 20) & 0x3FF); + public int BimmH1 => (int)((_opcode >> 47) & 0x200) | (int)((_opcode >> 30) & 0x1FF); + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 49) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x40) != 0; + public bool HAnd => (_opcode & 0x20000000000000) != 0; + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + } + + struct InstHsetp2C + { + private ulong _opcode; + public InstHsetp2C(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegA => (_opcode & 0x80000000000) != 0; + public bool NegB => (_opcode & 0x100000000000000) != 0; + public bool AbsA => (_opcode & 0x100000000000) != 0; + public bool AbsB => (_opcode & 0x40000000000000) != 0; + public FComp FComp => (FComp)((_opcode >> 49) & 0xF); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool Ftz => (_opcode & 0x40) != 0; + public bool HAnd => (_opcode & 0x20000000000000) != 0; + public HalfSwizzle ASwizzle => (HalfSwizzle)((_opcode >> 47) & 0x3); + } + + struct InstI2fR + { + private ulong _opcode; + public InstI2fR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public ISrcFmt ISrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + } + + struct InstI2fI + { + private ulong _opcode; + public InstI2fI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public ISrcFmt ISrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + } + + struct InstI2fC + { + private ulong _opcode; + public InstI2fC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public RoundMode RoundMode => (RoundMode)((_opcode >> 39) & 0x3); + public ISrcFmt ISrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + public DstFmt DstFmt => (DstFmt)((_opcode >> 8) & 0x3); + } + + struct InstI2iR + { + private ulong _opcode; + public InstI2iR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + } + + struct InstI2iI + { + private ulong _opcode; + public InstI2iI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + } + + struct InstI2iC + { + private ulong _opcode; + public InstI2iC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public IDstFmt IDstFmt => (IDstFmt)((int)((_opcode >> 10) & 0x4) | (int)((_opcode >> 8) & 0x3)); + public ISrcFmt SrcFmt => (ISrcFmt)((int)((_opcode >> 11) & 0x4) | (int)((_opcode >> 10) & 0x3)); + } + + struct InstIaddR + { + private ulong _opcode; + public InstIaddR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIaddI + { + private ulong _opcode; + public InstIaddI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIaddC + { + private ulong _opcode; + public InstIaddC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIadd32i + { + private ulong _opcode; + public InstIadd32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public AvgMode AvgMode => (AvgMode)((_opcode >> 55) & 0x3); + public bool Sat => (_opcode & 0x40000000000000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public bool X => (_opcode & 0x20000000000000) != 0; + } + + struct InstIadd3R + { + private ulong _opcode; + public InstIadd3R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x8000000000000) != 0; + public bool NegB => (_opcode & 0x4000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool X => (_opcode & 0x1000000000000) != 0; + public Lrs Lrs => (Lrs)((_opcode >> 37) & 0x3); + public HalfSelect Apart => (HalfSelect)((_opcode >> 35) & 0x3); + public HalfSelect Bpart => (HalfSelect)((_opcode >> 33) & 0x3); + public HalfSelect Cpart => (HalfSelect)((_opcode >> 31) & 0x3); + } + + struct InstIadd3I + { + private ulong _opcode; + public InstIadd3I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x8000000000000) != 0; + public bool NegB => (_opcode & 0x4000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool X => (_opcode & 0x1000000000000) != 0; + } + + struct InstIadd3C + { + private ulong _opcode; + public InstIadd3C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool NegA => (_opcode & 0x8000000000000) != 0; + public bool NegB => (_opcode & 0x4000000000000) != 0; + public bool NegC => (_opcode & 0x2000000000000) != 0; + public bool X => (_opcode & 0x1000000000000) != 0; + } + + struct InstIcmpR + { + private ulong _opcode; + public InstIcmpR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + } + + struct InstIcmpI + { + private ulong _opcode; + public InstIcmpI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + } + + struct InstIcmpC + { + private ulong _opcode; + public InstIcmpC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + } + + struct InstIcmpRc + { + private ulong _opcode; + public InstIcmpRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + } + + struct InstIde + { + private ulong _opcode; + public InstIde(ulong opcode) => _opcode = opcode; + public int Imm16 => (int)((_opcode >> 20) & 0xFFFF); + public bool Di => (_opcode & 0x20) != 0; + } + + struct InstIdpR + { + private ulong _opcode; + public InstIdpR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool IsHi => (_opcode & 0x4000000000000) != 0; + public bool SrcASign => (_opcode & 0x2000000000000) != 0; + public bool IsDp => (_opcode & 0x1000000000000) != 0; + public bool SrcBSign => (_opcode & 0x800000000000) != 0; + } + + struct InstIdpC + { + private ulong _opcode; + public InstIdpC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool IsHi => (_opcode & 0x4000000000000) != 0; + public bool SrcASign => (_opcode & 0x2000000000000) != 0; + public bool IsDp => (_opcode & 0x1000000000000) != 0; + public bool SrcBSign => (_opcode & 0x800000000000) != 0; + } + + struct InstImadR + { + private ulong _opcode; + public InstImadR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Hilo => (_opcode & 0x40000000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 51) & 0x3); + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool X => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } + + struct InstImadI + { + private ulong _opcode; + public InstImadI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Hilo => (_opcode & 0x40000000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 51) & 0x3); + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool X => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } + + struct InstImadC + { + private ulong _opcode; + public InstImadC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Hilo => (_opcode & 0x40000000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 51) & 0x3); + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool X => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } + + struct InstImadRc + { + private ulong _opcode; + public InstImadRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Hilo => (_opcode & 0x40000000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 51) & 0x3); + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool X => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } + + struct InstImad32i + { + private ulong _opcode; + public InstImad32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool BSigned => (_opcode & 0x200000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 55) & 0x3); + public bool ASigned => (_opcode & 0x40000000000000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public bool Hilo => (_opcode & 0x20000000000000) != 0; + } + + struct InstImadspR + { + private ulong _opcode; + public InstImadspR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ImadspASelect ASelect => (ImadspASelect)((_opcode >> 48) & 0x7); + public ImadspBSelect BSelect => (ImadspBSelect)((_opcode >> 53) & 0x3); + public ImadspASelect CSelect => (ImadspASelect)((int)((_opcode >> 50) & 0x6) | (int)((_opcode >> 48) & 0x1)); + } + + struct InstImadspI + { + private ulong _opcode; + public InstImadspI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ImadspASelect ASelect => (ImadspASelect)((_opcode >> 48) & 0x7); + public ImadspBSelect BSelect => (ImadspBSelect)((_opcode >> 53) & 0x3); + public ImadspASelect CSelect => (ImadspASelect)((int)((_opcode >> 50) & 0x6) | (int)((_opcode >> 48) & 0x1)); + } + + struct InstImadspC + { + private ulong _opcode; + public InstImadspC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ImadspASelect ASelect => (ImadspASelect)((_opcode >> 48) & 0x7); + public ImadspBSelect BSelect => (ImadspBSelect)((_opcode >> 53) & 0x3); + public ImadspASelect CSelect => (ImadspASelect)((int)((_opcode >> 50) & 0x6) | (int)((_opcode >> 48) & 0x1)); + } + + struct InstImadspRc + { + private ulong _opcode; + public InstImadspRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ImadspASelect ASelect => (ImadspASelect)((_opcode >> 48) & 0x7); + public ImadspBSelect BSelect => (ImadspBSelect)((_opcode >> 53) & 0x3); + public ImadspASelect CSelect => (ImadspASelect)((int)((_opcode >> 50) & 0x6) | (int)((_opcode >> 48) & 0x1)); + } + + struct InstImnmxR + { + private ulong _opcode; + public InstImnmxR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstImnmxI + { + private ulong _opcode; + public InstImnmxI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstImnmxC + { + private ulong _opcode; + public InstImnmxC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstImulR + { + private ulong _opcode; + public InstImulR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool ASigned => (_opcode & 0x10000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000) != 0; + public bool Hilo => (_opcode & 0x8000000000) != 0; + } + + struct InstImulI + { + private ulong _opcode; + public InstImulI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool ASigned => (_opcode & 0x10000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000) != 0; + public bool Hilo => (_opcode & 0x8000000000) != 0; + } + + struct InstImulC + { + private ulong _opcode; + public InstImulC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool ASigned => (_opcode & 0x10000000000) != 0; + public bool BSigned => (_opcode & 0x20000000000) != 0; + public bool Hilo => (_opcode & 0x8000000000) != 0; + } + + struct InstImul32i + { + private ulong _opcode; + public InstImul32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool ASigned => (_opcode & 0x40000000000000) != 0; + public bool BSigned => (_opcode & 0x80000000000000) != 0; + public bool Hilo => (_opcode & 0x20000000000000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + } + + struct InstIpa + { + private ulong _opcode; + public InstIpa(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IpaOp IpaOp => (IpaOp)((_opcode >> 54) & 0x3); + public int Msi => (int)((_opcode >> 52) & 0x3); + public bool Sat => (_opcode & 0x8000000000000) != 0; + public bool Idx => (_opcode & 0x4000000000) != 0; + public int Imm10 => (int)((_opcode >> 28) & 0x3FF); + public int SrcPred => (int)((_opcode >> 47) & 0x7); + public bool SrcPredInv => (_opcode & 0x4000000000000) != 0; + } + + struct InstIsberd + { + private ulong _opcode; + public InstIsberd(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public AlSize AlSize => (AlSize)((_opcode >> 47) & 0x3); + public IBase IBase => (IBase)((_opcode >> 33) & 0x3); + public bool O => (_opcode & 0x100000000) != 0; + public bool P => (_opcode & 0x80000000) != 0; + } + + struct InstIscaddR + { + private ulong _opcode; + public InstIscaddR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int Imm5 => (int)((_opcode >> 39) & 0x1F); + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + } + + struct InstIscaddI + { + private ulong _opcode; + public InstIscaddI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int Imm5 => (int)((_opcode >> 39) & 0x1F); + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + } + + struct InstIscaddC + { + private ulong _opcode; + public InstIscaddC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int Imm5 => (int)((_opcode >> 39) & 0x1F); + public AvgMode AvgMode => (AvgMode)((_opcode >> 48) & 0x3); + } + + struct InstIscadd32i + { + private ulong _opcode; + public InstIscadd32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public int Imm5 => (int)((_opcode >> 53) & 0x1F); + } + + struct InstIsetR + { + private ulong _opcode; + public InstIsetR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool BVal => (_opcode & 0x100000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIsetI + { + private ulong _opcode; + public InstIsetI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool BVal => (_opcode & 0x100000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIsetC + { + private ulong _opcode; + public InstIsetC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public bool BVal => (_opcode & 0x100000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + } + + struct InstIsetpR + { + private ulong _opcode; + public InstIsetpR(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstIsetpI + { + private ulong _opcode; + public InstIsetpI(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstIsetpC + { + private ulong _opcode; + public InstIsetpC(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public IComp IComp => (IComp)((_opcode >> 49) & 0x7); + public bool Signed => (_opcode & 0x1000000000000) != 0; + public BoolOp Bop => (BoolOp)((_opcode >> 45) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + } + + struct InstJcal + { + private ulong _opcode; + public InstJcal(ulong opcode) => _opcode = opcode; + public int Imm32 => (int)(_opcode >> 20); + public bool Ca => (_opcode & 0x20) != 0; + public bool Inc => (_opcode & 0x40) != 0; + } + + struct InstJmp + { + private ulong _opcode; + public InstJmp(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + public bool Ca => (_opcode & 0x20) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool Lmt => (_opcode & 0x40) != 0; + public bool U => (_opcode & 0x80) != 0; + } + + struct InstJmx + { + private ulong _opcode; + public InstJmx(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + public bool Ca => (_opcode & 0x20) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool Lmt => (_opcode & 0x40) != 0; + } + + struct InstKil + { + private ulong _opcode; + public InstKil(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstLd + { + private ulong _opcode; + public InstLd(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 58) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 56) & 0x3); + public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7); + public bool E => (_opcode & 0x10000000000000) != 0; + public int Imm32 => (int)(_opcode >> 20); + } + + struct InstLdc + { + private ulong _opcode; + public InstLdc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public AddressMode AddressMode => (AddressMode)((_opcode >> 44) & 0x3); + public int CbufSlot => (int)((_opcode >> 36) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0xFFFF); + } + + struct InstLdg + { + private ulong _opcode; + public InstLdg(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize LsSize => (LsSize)((_opcode >> 48) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 46) & 0x3); + public bool E => (_opcode & 0x200000000000) != 0; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstLdl + { + private ulong _opcode; + public InstLdl(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public CacheOp2 CacheOp => (CacheOp2)((_opcode >> 44) & 0x3); + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstLds + { + private ulong _opcode; + public InstLds(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public bool U => (_opcode & 0x100000000000) != 0; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstLeaR + { + private ulong _opcode; + public InstLeaR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x400000000000) != 0; + public bool NegA => (_opcode & 0x200000000000) != 0; + public int ImmU5 => (int)((_opcode >> 39) & 0x1F); + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstLeaI + { + private ulong _opcode; + public InstLeaI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x400000000000) != 0; + public bool NegA => (_opcode & 0x200000000000) != 0; + public int ImmU5 => (int)((_opcode >> 39) & 0x1F); + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstLeaC + { + private ulong _opcode; + public InstLeaC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x400000000000) != 0; + public bool NegA => (_opcode & 0x200000000000) != 0; + public int ImmU5 => (int)((_opcode >> 39) & 0x1F); + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstLeaHiR + { + private ulong _opcode; + public InstLeaHiR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x4000000000) != 0; + public bool NegA => (_opcode & 0x2000000000) != 0; + public int ImmU5 => (int)((_opcode >> 28) & 0x1F); + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstLeaHiC + { + private ulong _opcode; + public InstLeaHiC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x200000000000000) != 0; + public bool NegA => (_opcode & 0x100000000000000) != 0; + public int ImmU5 => (int)((_opcode >> 51) & 0x1F); + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstLepc + { + private ulong _opcode; + public InstLepc(ulong opcode) => _opcode = opcode; + } + + struct InstLongjmp + { + private ulong _opcode; + public InstLongjmp(ulong opcode) => _opcode = opcode; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstLopR + { + private ulong _opcode; + public InstLopR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int DestPred => (int)((_opcode >> 48) & 0x7); + public PredicateOp PredicateOp => (PredicateOp)((_opcode >> 44) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public LogicOp Lop => (LogicOp)((_opcode >> 41) & 0x3); + public bool NegA => (_opcode & 0x8000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstLopI + { + private ulong _opcode; + public InstLopI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int DestPred => (int)((_opcode >> 48) & 0x7); + public PredicateOp PredicateOp => (PredicateOp)((_opcode >> 44) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public LogicOp LogicOp => (LogicOp)((_opcode >> 41) & 0x3); + public bool NegA => (_opcode & 0x8000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstLopC + { + private ulong _opcode; + public InstLopC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int DestPred => (int)((_opcode >> 48) & 0x7); + public PredicateOp PredicateOp => (PredicateOp)((_opcode >> 44) & 0x3); + public bool X => (_opcode & 0x80000000000) != 0; + public LogicOp LogicOp => (LogicOp)((_opcode >> 41) & 0x3); + public bool NegA => (_opcode & 0x8000000000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstLop3R + { + private ulong _opcode; + public InstLop3R(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int DestPred => (int)((_opcode >> 48) & 0x7); + public PredicateOp PredicateOp => (PredicateOp)((_opcode >> 36) & 0x3); + public bool X => (_opcode & 0x4000000000) != 0; + public int Imm => (int)((_opcode >> 28) & 0xFF); + } + + struct InstLop3I + { + private ulong _opcode; + public InstLop3I(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x200000000000000) != 0; + public int Imm => (int)((_opcode >> 48) & 0xFF); + } + + struct InstLop3C + { + private ulong _opcode; + public InstLop3C(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x100000000000000) != 0; + public int Imm => (int)((_opcode >> 48) & 0xFF); + } + + struct InstLop32i + { + private ulong _opcode; + public InstLop32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x10000000000000) != 0; + public int Imm32 => (int)(_opcode >> 20); + public bool X => (_opcode & 0x200000000000000) != 0; + public LogicOp LogicOp => (LogicOp)((_opcode >> 53) & 0x3); + public bool NegA => (_opcode & 0x80000000000000) != 0; + public bool NegB => (_opcode & 0x100000000000000) != 0; + } + + struct InstMembar + { + private ulong _opcode; + public InstMembar(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Membar Membar => (Membar)((_opcode >> 8) & 0x3); + public Ivall Ivall => (Ivall)((_opcode >> 0) & 0x3); + } + + struct InstMovR + { + private ulong _opcode; + public InstMovR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int QuadMask => (int)((_opcode >> 39) & 0xF); + } + + struct InstMovI + { + private ulong _opcode; + public InstMovI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int QuadMask => (int)((_opcode >> 39) & 0xF); + } + + struct InstMovC + { + private ulong _opcode; + public InstMovC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int QuadMask => (int)((_opcode >> 39) & 0xF); + } + + struct InstMov32i + { + private ulong _opcode; + public InstMov32i(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm32 => (int)(_opcode >> 20); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int QuadMask => (int)((_opcode >> 12) & 0xF); + } + + struct InstMufu + { + private ulong _opcode; + public InstMufu(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public MufuOp MufuOp => (MufuOp)((_opcode >> 20) & 0xF); + public bool AbsA => (_opcode & 0x400000000000) != 0; + public bool NegA => (_opcode & 0x1000000000000) != 0; + public bool Sat => (_opcode & 0x4000000000000) != 0; + } + + struct InstNop + { + private ulong _opcode; + public InstNop(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm16 => (int)((_opcode >> 20) & 0xFFFF); + public bool Trig => (_opcode & 0x2000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 8) & 0x1F); + } + + struct InstOutR + { + private ulong _opcode; + public InstOutR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public OutType OutType => (OutType)((_opcode >> 39) & 0x3); + } + + struct InstOutI + { + private ulong _opcode; + public InstOutI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public OutType OutType => (OutType)((_opcode >> 39) & 0x3); + } + + struct InstOutC + { + private ulong _opcode; + public InstOutC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public OutType OutType => (OutType)((_opcode >> 39) & 0x3); + } + + struct InstP2rR + { + private ulong _opcode; + public InstP2rR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstP2rI + { + private ulong _opcode; + public InstP2rI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstP2rC + { + private ulong _opcode; + public InstP2rC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstPbk + { + private ulong _opcode; + public InstPbk(ulong opcode) => _opcode = opcode; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + } + + struct InstPcnt + { + private ulong _opcode; + public InstPcnt(ulong opcode) => _opcode = opcode; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + } + + struct InstPexit + { + private ulong _opcode; + public InstPexit(ulong opcode) => _opcode = opcode; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstPixld + { + private ulong _opcode; + public InstPixld(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int DestPred => (int)((_opcode >> 45) & 0x7); + public PixMode PixMode => (PixMode)((_opcode >> 31) & 0x7); + public int Imm8 => (int)((_opcode >> 20) & 0xFF); + } + + struct InstPlongjmp + { + private ulong _opcode; + public InstPlongjmp(ulong opcode) => _opcode = opcode; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + } + + struct InstPopcR + { + private ulong _opcode; + public InstPopcR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstPopcI + { + private ulong _opcode; + public InstPopcI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstPopcC + { + private ulong _opcode; + public InstPopcC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool NegB => (_opcode & 0x10000000000) != 0; + } + + struct InstPret + { + private ulong _opcode; + public InstPret(ulong opcode) => _opcode = opcode; + public bool Ca => (_opcode & 0x20) != 0; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Inc => (_opcode & 0x40) != 0; + } + + struct InstPrmtR + { + private ulong _opcode; + public InstPrmtR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public PMode PMode => (PMode)((_opcode >> 48) & 0xF); + } + + struct InstPrmtI + { + private ulong _opcode; + public InstPrmtI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public PMode PMode => (PMode)((_opcode >> 48) & 0xF); + } + + struct InstPrmtC + { + private ulong _opcode; + public InstPrmtC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public PMode PMode => (PMode)((_opcode >> 48) & 0xF); + } + + struct InstPrmtRc + { + private ulong _opcode; + public InstPrmtRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public PMode PMode => (PMode)((_opcode >> 48) & 0xF); + } + + struct InstPset + { + private ulong _opcode; + public InstPset(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int Src2Pred => (int)((_opcode >> 12) & 0x7); + public bool Src2PredInv => (_opcode & 0x8000) != 0; + public int Src1Pred => (int)((_opcode >> 29) & 0x7); + public bool Src1PredInv => (_opcode & 0x100000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp BoolOpAB => (BoolOp)((_opcode >> 24) & 0x3); + public BoolOp BoolOpC => (BoolOp)((_opcode >> 45) & 0x3); + public bool BVal => (_opcode & 0x100000000000) != 0; + } + + struct InstPsetp + { + private ulong _opcode; + public InstPsetp(ulong opcode) => _opcode = opcode; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public int Src2Pred => (int)((_opcode >> 12) & 0x7); + public bool Src2PredInv => (_opcode & 0x8000) != 0; + public int Src1Pred => (int)((_opcode >> 29) & 0x7); + public bool Src1PredInv => (_opcode & 0x100000000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public BoolOp BoolOpAB => (BoolOp)((_opcode >> 24) & 0x3); + public BoolOp BoolOpC => (BoolOp)((_opcode >> 45) & 0x3); + } + + struct InstR2b + { + private ulong _opcode; + public InstR2b(ulong opcode) => _opcode = opcode; + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public BarMode Mode => (BarMode)((_opcode >> 32) & 0x3); + public int Name => (int)((_opcode >> 28) & 0xF); + } + + struct InstR2pR + { + private ulong _opcode; + public InstR2pR(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstR2pI + { + private ulong _opcode; + public InstR2pI(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstR2pC + { + private ulong _opcode; + public InstR2pC(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ByteSel ByteSel => (ByteSel)((_opcode >> 41) & 0x3); + public bool Ccpr => (_opcode & 0x10000000000) != 0; + } + + struct InstRam + { + private ulong _opcode; + public InstRam(ulong opcode) => _opcode = opcode; + } + + struct InstRed + { + private ulong _opcode; + public InstRed(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int Imm20 => (int)((_opcode >> 28) & 0xFFFFF); + public AtomSize RedSize => (AtomSize)((_opcode >> 20) & 0x7); + public RedOp RedOp => (RedOp)((_opcode >> 23) & 0x7); + public bool E => (_opcode & 0x1000000000000) != 0; + } + + struct InstRet + { + private ulong _opcode; + public InstRet(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstRroR + { + private ulong _opcode; + public InstRroR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool RroOp => (_opcode & 0x8000000000) != 0; + } + + struct InstRroI + { + private ulong _opcode; + public InstRroI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool RroOp => (_opcode & 0x8000000000) != 0; + } + + struct InstRroC + { + private ulong _opcode; + public InstRroC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool AbsB => (_opcode & 0x2000000000000) != 0; + public bool NegB => (_opcode & 0x200000000000) != 0; + public bool RroOp => (_opcode & 0x8000000000) != 0; + } + + struct InstRtt + { + private ulong _opcode; + public InstRtt(ulong opcode) => _opcode = opcode; + } + + struct InstS2r + { + private ulong _opcode; + public InstS2r(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public SReg SReg => (SReg)((_opcode >> 20) & 0xFF); + } + + struct InstSam + { + private ulong _opcode; + public InstSam(ulong opcode) => _opcode = opcode; + } + + struct InstSelR + { + private ulong _opcode; + public InstSelR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstSelI + { + private ulong _opcode; + public InstSelI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstSelC + { + private ulong _opcode; + public InstSelC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + } + + struct InstSetcrsptr + { + private ulong _opcode; + public InstSetcrsptr(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + } + + struct InstSetlmembase + { + private ulong _opcode; + public InstSetlmembase(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + } + + struct InstShfLR + { + private ulong _opcode; + public InstShfLR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool M => (_opcode & 0x4000000000000) != 0; + public XModeShf XModeShf => (XModeShf)((_opcode >> 48) & 0x3); + public MaxShift MaxShift => (MaxShift)((_opcode >> 37) & 0x3); + } + + struct InstShfRR + { + private ulong _opcode; + public InstShfRR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool M => (_opcode & 0x4000000000000) != 0; + public XModeShf XModeShf => (XModeShf)((_opcode >> 48) & 0x3); + public MaxShift MaxShift => (MaxShift)((_opcode >> 37) & 0x3); + } + + struct InstShfLI + { + private ulong _opcode; + public InstShfLI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool M => (_opcode & 0x4000000000000) != 0; + public XModeShf XModeShf => (XModeShf)((_opcode >> 48) & 0x3); + public MaxShift MaxShift => (MaxShift)((_opcode >> 37) & 0x3); + public int Imm6 => (int)((_opcode >> 20) & 0x3F); + } + + struct InstShfRI + { + private ulong _opcode; + public InstShfRI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool M => (_opcode & 0x4000000000000) != 0; + public XModeShf XModeShf => (XModeShf)((_opcode >> 48) & 0x3); + public MaxShift MaxShift => (MaxShift)((_opcode >> 37) & 0x3); + public int Imm6 => (int)((_opcode >> 20) & 0x3F); + } + + struct InstShfl + { + private ulong _opcode; + public InstShfl(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int SrcBImm => (int)((_opcode >> 20) & 0x1F); + public int SrcCImm => (int)((_opcode >> 34) & 0x1FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public ShflMode ShflMode => (ShflMode)((_opcode >> 30) & 0x3); + public bool CFixShfl => (_opcode & 0x20000000) != 0; + public bool BFixShfl => (_opcode & 0x10000000) != 0; + public int DestPred => (int)((_opcode >> 48) & 0x7); + } + + struct InstShlR + { + private ulong _opcode; + public InstShlR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x80000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstShlI + { + private ulong _opcode; + public InstShlI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x80000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstShlC + { + private ulong _opcode; + public InstShlC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x80000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstShrR + { + private ulong _opcode; + public InstShrR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public bool Brev => (_opcode & 0x10000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstShrI + { + private ulong _opcode; + public InstShrI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Imm20 => (int)((_opcode >> 37) & 0x80000) | (int)((_opcode >> 20) & 0x7FFFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public bool Brev => (_opcode & 0x10000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstShrC + { + private ulong _opcode; + public InstShrC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Signed => (_opcode & 0x1000000000000) != 0; + public XMode XMode => (XMode)((_opcode >> 43) & 0x3); + public bool Brev => (_opcode & 0x10000000000) != 0; + public bool M => (_opcode & 0x8000000000) != 0; + } + + struct InstSsy + { + private ulong _opcode; + public InstSsy(ulong opcode) => _opcode = opcode; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + public bool Ca => (_opcode & 0x20) != 0; + } + + struct InstSt + { + private ulong _opcode; + public InstSt(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 58) & 0x7); + public CacheOp Cop => (CacheOp)((_opcode >> 56) & 0x3); + public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7); + public bool E => (_opcode & 0x10000000000000) != 0; + public int Imm32 => (int)(_opcode >> 20); + } + + struct InstStg + { + private ulong _opcode; + public InstStg(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 46) & 0x3); + public bool E => (_opcode & 0x200000000000) != 0; + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstStl + { + private ulong _opcode; + public InstStl(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public CacheOp2 CacheOp => (CacheOp2)((_opcode >> 44) & 0x3); + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstStp + { + private ulong _opcode; + public InstStp(ulong opcode) => _opcode = opcode; + public bool Wait => (_opcode & 0x80000000) != 0; + public int Imm8 => (int)((_opcode >> 20) & 0xFF); + } + + struct InstSts + { + private ulong _opcode; + public InstSts(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7); + public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF); + } + + struct InstSuatomB + { + private ulong _opcode; + public InstSuatomB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuatomSize Size => (SuatomSize)((_opcode >> 36) & 0x7); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public SuatomOp Op => (SuatomOp)((_opcode >> 29) & 0xF); + public bool Ba => (_opcode & 0x10000000) != 0; + } + + struct InstSuatom + { + private ulong _opcode; + public InstSuatom(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public SuatomSize Size => (SuatomSize)((_opcode >> 51) & 0x7); + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public SuatomOp Op => (SuatomOp)((_opcode >> 29) & 0xF); + public bool Ba => (_opcode & 0x10000000) != 0; + } + + struct InstSuatomB2 + { + private ulong _opcode; + public InstSuatomB2(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuatomSize Size => (SuatomSize)((_opcode >> 36) & 0x7); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public SuatomOp Op => (SuatomOp)((_opcode >> 29) & 0xF); + public bool Ba => (_opcode & 0x10000000) != 0; + } + + struct InstSuatomCasB + { + private ulong _opcode; + public InstSuatomCasB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuatomSize Size => (SuatomSize)((_opcode >> 36) & 0x7); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred => (int)((_opcode >> 30) & 0x7); + public bool Ba => (_opcode & 0x10000000) != 0; + } + + struct InstSuatomCas + { + private ulong _opcode; + public InstSuatomCas(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public SuatomSize Size => (SuatomSize)((_opcode >> 51) & 0x7); + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred => (int)((_opcode >> 30) & 0x7); + public bool Ba => (_opcode & 0x10000000) != 0; + } + + struct InstSuldDB + { + private ulong _opcode; + public InstSuldDB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred2 => (int)((_opcode >> 30) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public bool Ba => (_opcode & 0x800000) != 0; + public SuSize Size => (SuSize)((_opcode >> 20) & 0x7); + } + + struct InstSuldD + { + private ulong _opcode; + public InstSuldD(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred2 => (int)((_opcode >> 30) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public bool Ba => (_opcode & 0x800000) != 0; + public SuSize Size => (SuSize)((_opcode >> 20) & 0x7); + } + + struct InstSuldB + { + private ulong _opcode; + public InstSuldB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred2 => (int)((_opcode >> 30) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF); + } + + struct InstSuld + { + private ulong _opcode; + public InstSuld(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public int DestPred2 => (int)((_opcode >> 30) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF); + } + + struct InstSuredB + { + private ulong _opcode; + public InstSuredB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public RedOp Op => (RedOp)((_opcode >> 24) & 0x7); + public bool Ba => (_opcode & 0x800000) != 0; + public SuatomSize Size => (SuatomSize)((_opcode >> 20) & 0x7); + } + + struct InstSured + { + private ulong _opcode; + public InstSured(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public RedOp Op => (RedOp)((_opcode >> 24) & 0x7); + public bool Ba => (_opcode & 0x800000) != 0; + public SuatomSize Size => (SuatomSize)((_opcode >> 20) & 0x7); + } + + struct InstSustDB + { + private ulong _opcode; + public InstSustDB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public bool Ba => (_opcode & 0x800000) != 0; + public SuSize Size => (SuSize)((_opcode >> 20) & 0x7); + } + + struct InstSustD + { + private ulong _opcode; + public InstSustD(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public bool Ba => (_opcode & 0x800000) != 0; + public SuSize Size => (SuSize)((_opcode >> 20) & 0x7); + } + + struct InstSustB + { + private ulong _opcode; + public InstSustB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF); + } + + struct InstSust + { + private ulong _opcode; + public InstSust(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7); + public CacheOp CacheOp => (CacheOp)((_opcode >> 24) & 0x3); + public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF); + } + + struct InstSync + { + private ulong _opcode; + public InstSync(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F); + } + + struct InstTex + { + private ulong _opcode; + public InstTex(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Lc => (_opcode & 0x400000000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public Lod Lod => (Lod)((_opcode >> 55) & 0x7); + public bool Aoffi => (_opcode & 0x40000000000000) != 0; + public bool Dc => (_opcode & 0x4000000000000) != 0; + public bool Ndv => (_opcode & 0x800000000) != 0; + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + } + + struct InstTexB + { + private ulong _opcode; + public InstTexB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Lcb => (_opcode & 0x10000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public Lod Lodb => (Lod)((_opcode >> 37) & 0x7); + public bool Aoffib => (_opcode & 0x1000000000) != 0; + public bool Dc => (_opcode & 0x4000000000000) != 0; + public bool Ndv => (_opcode & 0x800000000) != 0; + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + } + + struct InstTexs + { + private ulong _opcode; + public InstTexs(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public TexsTarget Target => (TexsTarget)((_opcode >> 53) & 0xF); + public int WMask => (int)((_opcode >> 50) & 0x7); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int Dest2 => (int)((_opcode >> 28) & 0xFF); + } + + struct InstTld + { + private ulong _opcode; + public InstTld(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Lod => (_opcode & 0x80000000000000) != 0; + public bool Toff => (_opcode & 0x800000000) != 0; + public bool Ms => (_opcode & 0x4000000000000) != 0; + public bool Cl => (_opcode & 0x40000000000000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTldB + { + private ulong _opcode; + public InstTldB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Lod => (_opcode & 0x80000000000000) != 0; + public bool Toff => (_opcode & 0x800000000) != 0; + public bool Ms => (_opcode & 0x4000000000000) != 0; + public bool Cl => (_opcode & 0x40000000000000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTlds + { + private ulong _opcode; + public InstTlds(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public TldsTarget Target => (TldsTarget)((_opcode >> 53) & 0xF); + public int WMask => (int)((_opcode >> 50) & 0x7); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int Dest2 => (int)((_opcode >> 28) & 0xFF); + } + + struct InstTld4 + { + private ulong _opcode; + public InstTld4(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Lc => (_opcode & 0x400000000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public TexComp TexComp => (TexComp)((_opcode >> 56) & 0x3); + public TexOffset Toff => (TexOffset)((_opcode >> 54) & 0x3); + public bool Dc => (_opcode & 0x4000000000000) != 0; + public bool Ndv => (_opcode & 0x800000000) != 0; + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + } + + struct InstTld4B + { + private ulong _opcode; + public InstTld4B(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Lc => (_opcode & 0x10000000000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public TexComp TexComp => (TexComp)((_opcode >> 38) & 0x3); + public TexOffset Toff => (TexOffset)((_opcode >> 36) & 0x3); + public bool Dc => (_opcode & 0x4000000000000) != 0; + public bool Ndv => (_opcode & 0x800000000) != 0; + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + public int WMask => (int)((_opcode >> 31) & 0xF); + public bool Nodep => (_opcode & 0x2000000000000) != 0; + } + + struct InstTld4s + { + private ulong _opcode; + public InstTld4s(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public TexComp TexComp => (TexComp)((_opcode >> 52) & 0x3); + public bool Aoffi => (_opcode & 0x8000000000000) != 0; + public bool Dc => (_opcode & 0x4000000000000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int Dest2 => (int)((_opcode >> 28) & 0xFF); + } + + struct InstTmml + { + private ulong _opcode; + public InstTmml(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public bool Ndv => (_opcode & 0x800000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTmmlB + { + private ulong _opcode; + public InstTmmlB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public bool Ndv => (_opcode & 0x800000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTxa + { + private ulong _opcode; + public InstTxa(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public bool Ndv => (_opcode & 0x800000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + } + + struct InstTxd + { + private ulong _opcode; + public InstTxd(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public bool Lc => (_opcode & 0x4000000000000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public bool Toff => (_opcode & 0x800000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTxdB + { + private ulong _opcode; + public InstTxdB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int DestPred => (int)((_opcode >> 51) & 0x7); + public bool Lc => (_opcode & 0x4000000000000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public bool Toff => (_opcode & 0x800000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexDim Dim => (TexDim)((_opcode >> 28) & 0x7); + } + + struct InstTxq + { + private ulong _opcode; + public InstTxq(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int TidB => (int)((_opcode >> 36) & 0x1FFF); + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexQuery TexQuery => (TexQuery)((_opcode >> 22) & 0x3F); + } + + struct InstTxqB + { + private ulong _opcode; + public InstTxqB(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool Nodep => (_opcode & 0x2000000000000) != 0; + public int WMask => (int)((_opcode >> 31) & 0xF); + public TexQuery TexQuery => (TexQuery)((_opcode >> 22) & 0x3F); + } + + struct InstVabsdiff + { + private ulong _opcode; + public InstVabsdiff(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool DFormat => (_opcode & 0x40000000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVabsdiff4 + { + private ulong _opcode; + public InstVabsdiff4(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public VideoRed VRed => (VideoRed)((_opcode >> 53) & 0x3); + public LaneMask4 LaneMask4 => (LaneMask4)((int)((_opcode >> 49) & 0xC) | (int)((_opcode >> 36) & 0x3)); + public bool Sat => (_opcode & 0x4000000000000) != 0; + public bool SrcBFmt => (_opcode & 0x2000000000000) != 0; + public bool SrcAFmt => (_opcode & 0x1000000000000) != 0; + public bool DFormat => (_opcode & 0x4000000000) != 0; + public ASelect4 Asel4 => (ASelect4)((_opcode >> 32) & 0xF); + public BSelect4 Bsel4 => (BSelect4)((_opcode >> 28) & 0xF); + } + + struct InstVadd + { + private ulong _opcode; + public InstVadd(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 56) & 0x3); + public bool DFormat => (_opcode & 0x40000000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVmad + { + private ulong _opcode; + public InstVmad(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public AvgMode AvgMode => (AvgMode)((_opcode >> 53) & 0x3); + public VideoScale VideoScale => (VideoScale)((_opcode >> 51) & 0x3); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVmnmx + { + private ulong _opcode; + public InstVmnmx(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public int Imm16 => (int)((_opcode >> 20) & 0xFFFF); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool DFormat => (_opcode & 0x40000000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool Mn => (_opcode & 0x100000000000000) != 0; + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVote + { + private ulong _opcode; + public InstVote(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public VoteMode VoteMode => (VoteMode)((_opcode >> 48) & 0x3); + public int VpDest => (int)((_opcode >> 45) & 0x7); + } + + struct InstVotevtg + { + private ulong _opcode; + public InstVotevtg(ulong opcode) => _opcode = opcode; + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public VoteMode VoteMode => (VoteMode)((_opcode >> 48) & 0x3); + public int Imm28 => (int)((_opcode >> 20) & 0xFFFFFFF); + } + + struct InstVset + { + private ulong _opcode; + public InstVset(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public IComp VComp => (IComp)((_opcode >> 54) & 0x7); + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVsetp + { + private ulong _opcode; + public InstVsetp(ulong opcode) => _opcode = opcode; + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((int)((_opcode >> 46) & 0x8) | (int)((_opcode >> 28) & 0x7)); + public IComp VComp => (IComp)((int)((_opcode >> 45) & 0x4) | (int)((_opcode >> 43) & 0x3)); + public BoolOp BoolOp => (BoolOp)((_opcode >> 45) & 0x3); + public int SrcPred => (int)((_opcode >> 39) & 0x7); + public bool SrcPredInv => (_opcode & 0x40000000000) != 0; + public int DestPred => (int)((_opcode >> 3) & 0x7); + public int DestPredInv => (int)((_opcode >> 0) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVshl + { + private ulong _opcode; + public InstVshl(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Mv => (_opcode & 0x2000000000000) != 0; + public bool DFormat => (_opcode & 0x40000000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((_opcode >> 28) & 0x7); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstVshr + { + private ulong _opcode; + public InstVshr(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Mv => (_opcode & 0x2000000000000) != 0; + public bool DFormat => (_opcode & 0x40000000000000) != 0; + public VectorSelect ASelect => (VectorSelect)((int)((_opcode >> 45) & 0x8) | (int)((_opcode >> 36) & 0x7)); + public VectorSelect BSelect => (VectorSelect)((_opcode >> 28) & 0x7); + public bool Sat => (_opcode & 0x80000000000000) != 0; + public VideoOp VideoOp => (VideoOp)((_opcode >> 51) & 0x7); + public bool BVideo => (_opcode & 0x4000000000000) != 0; + } + + struct InstXmadR + { + private ulong _opcode; + public InstXmadR(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcB => (int)((_opcode >> 20) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool HiloA => (_opcode & 0x20000000000000) != 0; + public XmadCop XmadCop => (XmadCop)((_opcode >> 50) & 0x7); + public bool BSigned => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + public bool X => (_opcode & 0x4000000000) != 0; + public bool Mrg => (_opcode & 0x2000000000) != 0; + public bool Psl => (_opcode & 0x1000000000) != 0; + public bool HiloB => (_opcode & 0x800000000) != 0; + } + + struct InstXmadI + { + private ulong _opcode; + public InstXmadI(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public int Imm16 => (int)((_opcode >> 20) & 0xFFFF); + public bool HiloA => (_opcode & 0x20000000000000) != 0; + public XmadCop XmadCop => (XmadCop)((_opcode >> 50) & 0x7); + public bool BSigned => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + public bool X => (_opcode & 0x4000000000) != 0; + public bool Mrg => (_opcode & 0x2000000000) != 0; + public bool Psl => (_opcode & 0x1000000000) != 0; + } + + struct InstXmadC + { + private ulong _opcode; + public InstXmadC(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool Mrg => (_opcode & 0x100000000000000) != 0; + public bool Psl => (_opcode & 0x80000000000000) != 0; + public bool X => (_opcode & 0x40000000000000) != 0; + public bool HiloA => (_opcode & 0x20000000000000) != 0; + public bool HiloB => (_opcode & 0x10000000000000) != 0; + public XmadCop2 XmadCop => (XmadCop2)((_opcode >> 50) & 0x3); + public bool BSigned => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } + + struct InstXmadRc + { + private ulong _opcode; + public InstXmadRc(ulong opcode) => _opcode = opcode; + public int Dest => (int)((_opcode >> 0) & 0xFF); + public int SrcA => (int)((_opcode >> 8) & 0xFF); + public int SrcC => (int)((_opcode >> 39) & 0xFF); + public int CbufSlot => (int)((_opcode >> 34) & 0x1F); + public int CbufOffset => (int)((_opcode >> 20) & 0x3FFF); + public int Pred => (int)((_opcode >> 16) & 0x7); + public bool PredInv => (_opcode & 0x80000) != 0; + public bool WriteCC => (_opcode & 0x800000000000) != 0; + public bool X => (_opcode & 0x40000000000000) != 0; + public bool HiloA => (_opcode & 0x20000000000000) != 0; + public bool HiloB => (_opcode & 0x10000000000000) != 0; + public XmadCop2 XmadCop => (XmadCop2)((_opcode >> 50) & 0x3); + public bool BSigned => (_opcode & 0x2000000000000) != 0; + public bool ASigned => (_opcode & 0x1000000000000) != 0; + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InstName.cs b/Ryujinx.Graphics.Shader/Decoders/InstName.cs new file mode 100644 index 00000000..9c79b7a5 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/InstName.cs @@ -0,0 +1,188 @@ +namespace Ryujinx.Graphics.Shader.Decoders +{ + enum InstName : byte + { + Invalid = 0, + + Al2p, + Ald, + Ast, + Atom, + AtomCas, + Atoms, + AtomsCas, + B2r, + Bar, + Bfe, + Bfi, + Bpt, + Bra, + Brk, + Brx, + Cal, + Cctl, + Cctll, + Cctlt, + Cont, + Cset, + Csetp, + Cs2r, + Dadd, + Depbar, + Dfma, + Dmnmx, + Dmul, + Dset, + Dsetp, + Exit, + F2f, + F2i, + Fadd, + Fadd32i, + Fchk, + Fcmp, + Ffma, + Ffma32i, + Flo, + Fmnmx, + Fmul, + Fmul32i, + Fset, + Fsetp, + Fswzadd, + Getcrsptr, + Getlmembase, + Hadd2, + Hadd232i, + Hfma2, + Hmul2, + Hmul232i, + Hset2, + Hsetp2, + I2f, + I2i, + Iadd, + Iadd32i, + Iadd3, + Icmp, + Ide, + Idp, + Imad, + Imad32i, + Imadsp, + Imnmx, + Imul, + Imul32i, + Ipa, + Isberd, + Iscadd, + Iscadd32i, + Iset, + Isetp, + Jcal, + Jmp, + Jmx, + Kil, + Ld, + Ldc, + Ldg, + Ldl, + Lds, + Lea, + LeaHi, + Lepc, + Longjmp, + Lop, + Lop3, + Lop32i, + Membar, + Mov, + Mov32i, + Mufu, + Nop, + Out, + P2r, + Pbk, + Pcnt, + Pexit, + Pixld, + Plongjmp, + Popc, + Pret, + Prmt, + Pset, + Psetp, + R2b, + R2p, + Ram, + Red, + Ret, + Rro, + Rtt, + S2r, + Sam, + Sel, + Setcrsptr, + Setlmembase, + Shf, + Shf_2, + Shf_3, + Shf_4, + Shfl, + Shl, + Shr, + Ssy, + St, + Stg, + Stl, + Stp, + Sts, + SuatomB, + Suatom, + SuatomB2, + SuatomCasB, + SuatomCas, + SuldDB, + SuldD, + SuldB, + Suld, + SuredB, + Sured, + SustDB, + SustD, + SustB, + Sust, + Sync, + Tex, + TexB, + Texs, + TexsF16, + Tld, + TldB, + Tlds, + TldsF16, + Tld4, + Tld4B, + Tld4s, + Tld4sF16, + Tmml, + TmmlB, + Txa, + Txd, + TxdB, + Txq, + TxqB, + Vabsdiff, + Vabsdiff4, + Vadd, + Vmad, + Vmnmx, + Vote, + Votevtg, + Vset, + Vsetp, + Vshl, + Vshr, + Xmad, + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InstOp.cs b/Ryujinx.Graphics.Shader/Decoders/InstOp.cs new file mode 100644 index 00000000..39244e64 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/InstOp.cs @@ -0,0 +1,27 @@ +using Ryujinx.Graphics.Shader.Instructions; + +namespace Ryujinx.Graphics.Shader.Decoders +{ + readonly struct InstOp + { + public readonly ulong Address; + public readonly ulong RawOpCode; + public readonly InstEmitter Emitter; + public readonly InstProps Props; + public readonly InstName Name; + + public InstOp(ulong address, ulong rawOpCode, InstName name, InstEmitter emitter, InstProps props) + { + Address = address; + RawOpCode = rawOpCode; + Name = name; + Emitter = emitter; + Props = props; + } + + public ulong GetAbsoluteAddress() + { + return (ulong)((long)Address + (((int)(RawOpCode >> 20) << 8) >> 8) + 8); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InstProps.cs b/Ryujinx.Graphics.Shader/Decoders/InstProps.cs new file mode 100644 index 00000000..7d329a81 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/InstProps.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Graphics.Shader.Decoders +{ + enum InstProps : ushort + { + None = 0, + Rd = 1 << 0, + Rd2 = 1 << 1, + Ra = 1 << 2, + Rb = 1 << 3, + Ib = 1 << 4, + Rc = 1 << 5, + Pd = 1 << 6, + Pd2 = 1 << 7, + Pdn = 1 << 8, + Tex = 1 << 9, + TexB = 1 << 10, + Bra = 1 << 11, + NoPred = 1 << 12 + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InstTable.cs b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs new file mode 100644 index 00000000..c971d646 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Decoders/InstTable.cs @@ -0,0 +1,388 @@ +using Ryujinx.Graphics.Shader.Instructions; + +namespace Ryujinx.Graphics.Shader.Decoders +{ + static class InstTable + { + private const int EncodingBits = 14; + + private struct TableEntry + { + public InstName Name { get; } + public InstEmitter Emitter { get; } + public InstProps Props { get; } + + public int XBits { get; } + + public TableEntry(InstName name, InstEmitter emitter, InstProps props, int xBits) + { + Name = name; + Emitter = emitter; + Props = props; + XBits = xBits; + } + } + + private static TableEntry[] _opCodes; + + static InstTable() + { + _opCodes = new TableEntry[1 << EncodingBits]; + + #region Instructions + Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra); + Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra); + Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rc); + Add("11101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atom, InstEmit.Atom, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("111011101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomCas, InstEmit.AtomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("11101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atoms, InstEmit.Atoms, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("111011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomsCas, InstEmit.AtomsCas, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("1111000010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B2r, InstEmit.B2r, InstProps.Rd | InstProps.Ra); + Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra); + Add("0101110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeC, InstProps.Rd | InstProps.Ra); + Add("0101101111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfi, InstEmit.BfiR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x11110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfi, InstEmit.BfiI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("0100101111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfi, InstEmit.BfiC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101001111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfi, InstEmit.BfiRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("111000111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bpt, InstEmit.Bpt, InstProps.NoPred); + Add("111000100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bra, InstEmit.Bra, InstProps.Bra); + Add("111000110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Brk, InstEmit.Brk, InstProps.Bra); + Add("111000100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Brx, InstEmit.Brx, InstProps.Ra | InstProps.Bra); + Add("111000100110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cal, InstEmit.Cal, InstProps.Bra | InstProps.NoPred); + Add("11101111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctl, InstEmit.Cctl, InstProps.Ra); + Add("1110111110000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctll, InstEmit.Cctll, InstProps.Ra); + Add("1110101111110xx0000000000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt); + Add("1110101111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt, InstProps.Rc); + Add("111000110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cont, InstEmit.Cont); + Add("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd); + Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn); + Add("0101000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cs2r, InstEmit.Cs2r, InstProps.Rd); + Add("0101110001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddC, InstProps.Rd | InstProps.Ra); + Add("1111000011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Depbar, InstEmit.Depbar); + Add("010110110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x0111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxC, InstProps.Rd | InstProps.Ra); + Add("0101110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x10000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulC, InstProps.Rd | InstProps.Ra); + Add("010110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011001x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("010010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetC, InstProps.Rd | InstProps.Ra); + Add("010110111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn); + Add("0011011x1000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn); + Add("010010111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn); + Add("111000110000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Exit, InstEmit.Exit, InstProps.Bra); + Add("0101110010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fR, InstProps.Rd | InstProps.Rb); + Add("0011100x10101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fI, InstProps.Rd | InstProps.Ib); + Add("0100110010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fC, InstProps.Rd); + Add("0101110010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2i, InstEmit.F2iR, InstProps.Rd | InstProps.Rb); + Add("0011100x10110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2i, InstEmit.F2iI, InstProps.Rd | InstProps.Ib); + Add("0100110010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2i, InstEmit.F2iC, InstProps.Rd); + Add("0101110001011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fadd, InstEmit.FaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fadd, InstEmit.FaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fadd, InstEmit.FaddC, InstProps.Rd | InstProps.Ra); + Add("000010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fadd32i, InstEmit.Fadd32i, InstProps.Rd | InstProps.Ra); + Add("0101110010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fchk, InstEmit.FchkR, InstProps.Ra | InstProps.Rb | InstProps.Pd); + Add("0011100x10001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fchk, InstEmit.FchkI, InstProps.Ra | InstProps.Ib | InstProps.Pd); + Add("0100110010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fchk, InstEmit.FchkC, InstProps.Ra | InstProps.Pd); + Add("010110111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fcmp, InstEmit.FcmpR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x1010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fcmp, InstEmit.FcmpI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fcmp, InstEmit.FcmpC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fcmp, InstEmit.FcmpRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ffma, InstEmit.FfmaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ffma, InstEmit.FfmaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ffma, InstEmit.FfmaC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ffma, InstEmit.FfmaRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ffma32i, InstEmit.Ffma32i, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloR, InstProps.Rd | InstProps.Rb); + Add("0011100x00110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloI, InstProps.Rd | InstProps.Ib); + Add("0100110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloC, InstProps.Rd); + Add("0101110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxC, InstProps.Rd | InstProps.Ra); + Add("0101110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulC, InstProps.Rd | InstProps.Ra); + Add("00011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul32i, InstEmit.Fmul32i, InstProps.Rd | InstProps.Ra); + Add("01011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("01001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetC, InstProps.Rd | InstProps.Ra); + Add("010110111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn); + Add("0011011x1011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn); + Add("010010111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn); + Add("0101000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fswzadd, InstEmit.Fswzadd, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("111000101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getcrsptr, InstEmit.Getcrsptr, InstProps.Rd | InstProps.NoPred); + Add("111000101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getlmembase, InstEmit.Getlmembase, InstProps.Rd | InstProps.NoPred); + Add("0101110100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hadd2, InstEmit.Hadd2R, InstProps.Rd | InstProps.Ra); + Add("0111101x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hadd2, InstEmit.Hadd2I, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0111101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hadd2, InstEmit.Hadd2C, InstProps.Rd | InstProps.Ra); + Add("0010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hadd232i, InstEmit.Hadd232i, InstProps.Rd | InstProps.Ra); + Add("0101110100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hfma2, InstEmit.Hfma2R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("01110xxx0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hfma2, InstEmit.Hfma2I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("01110xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hfma2, InstEmit.Hfma2C, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("01100xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hfma2, InstEmit.Hfma2Rc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101110100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2R, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0111100x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2I, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0111100x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2C, InstProps.Rd | InstProps.Ra); + Add("0010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul232i, InstEmit.Hmul232i, InstProps.Rd | InstProps.Ra); + Add("0101110100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2R, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0111110x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2I, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0111110x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2C, InstProps.Rd | InstProps.Ra); + Add("0101110100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2R, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn); + Add("0111111x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2I, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn); + Add("0111111x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2C, InstProps.Ra | InstProps.Pd | InstProps.Pdn); + Add("0101110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fR, InstProps.Rd | InstProps.Rb); + Add("0011100x10111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fI, InstProps.Rd | InstProps.Ib); + Add("0100110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fC, InstProps.Rd); + Add("0101110011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2i, InstEmit.I2iR, InstProps.Rd | InstProps.Rb); + Add("0011100x11100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2i, InstEmit.I2iI, InstProps.Rd | InstProps.Ib); + Add("0100110011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2i, InstEmit.I2iC, InstProps.Rd); + Add("0101110000010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd, InstEmit.IaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd, InstEmit.IaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd, InstEmit.IaddC, InstProps.Rd | InstProps.Ra); + Add("0001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd32i, InstEmit.Iadd32i, InstProps.Rd | InstProps.Ra); + Add("010111001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd3, InstEmit.Iadd3R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011100x1100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd3, InstEmit.Iadd3I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010011001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iadd3, InstEmit.Iadd3C, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010110110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Icmp, InstEmit.IcmpR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x0100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Icmp, InstEmit.IcmpI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Icmp, InstEmit.IcmpC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Icmp, InstEmit.IcmpRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("111000111001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ide, InstEmit.Ide, InstProps.NoPred); + Add("0101001111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Idp, InstEmit.IdpR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0101001111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Idp, InstEmit.IdpC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imad, InstEmit.ImadR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011010x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imad, InstEmit.ImadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imad, InstEmit.ImadC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imad, InstEmit.ImadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imad32i, InstEmit.Imad32i, InstProps.Rd | InstProps.Ra); + Add("010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011010x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxC, InstProps.Rd | InstProps.Ra); + Add("0101110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulC, InstProps.Rd | InstProps.Ra); + Add("00011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul32i, InstEmit.Imul32i, InstProps.Rd | InstProps.Ra); + Add("11100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ipa, InstEmit.Ipa, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("1110111111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isberd, InstEmit.Isberd, InstProps.Rd | InstProps.Ra); + Add("0101110000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddC, InstProps.Rd | InstProps.Ra); + Add("000101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd32i, InstEmit.Iscadd32i, InstProps.Rd | InstProps.Ra); + Add("010110110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011011x0101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("010010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetC, InstProps.Rd | InstProps.Ra); + Add("010110110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn); + Add("0011011x0110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn); + Add("010010110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn); + Add("111000100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jcal, InstEmit.Jcal, InstProps.Bra); + Add("111000100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmp, InstEmit.Jmp, InstProps.Ra | InstProps.Bra); + Add("111000100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmx, InstEmit.Jmx, InstProps.Ra | InstProps.Bra); + Add("111000110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Kil, InstEmit.Kil, InstProps.Bra); + Add("100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ld, InstEmit.Ld, InstProps.Rd | InstProps.Ra); + Add("1110111110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldc, InstEmit.Ldc, InstProps.Rd | InstProps.Ra); + Add("1110111011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldg, InstEmit.Ldg, InstProps.Rd | InstProps.Ra); + Add("1110111101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldl, InstEmit.Ldl, InstProps.Rd | InstProps.Ra); + Add("1110111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lds, InstEmit.Lds, InstProps.Rd | InstProps.Ra); + Add("0101101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd); + Add("0011011x11010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Pd); + Add("0100101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaC, InstProps.Rd | InstProps.Ra | InstProps.Pd); + Add("0101101111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd); + Add("000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiC, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd); + Add("0101000011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lepc, InstEmit.Lepc); + Add("111000110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Longjmp, InstEmit.Longjmp, InstProps.Bra); + Add("0101110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd); + Add("0011100x01000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Pd); + Add("0100110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopC, InstProps.Rd | InstProps.Ra | InstProps.Pd); + Add("0101101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd); + Add("001111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("0000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3C, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop32i, InstEmit.Lop32i, InstProps.Rd | InstProps.Ra); + Add("1110111110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Membar, InstEmit.Membar); + Add("0101110010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit.MovR, InstProps.Rd | InstProps.Ra); + Add("0011100x10011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit.MovI, InstProps.Rd | InstProps.Ib); + Add("0100110010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit.MovC, InstProps.Rd); + Add("000000010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Mov32i, InstEmit.Mov32i, InstProps.Rd); + Add("0101000010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Mufu, InstEmit.Mufu, InstProps.Rd | InstProps.Ra); + Add("0101000010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Nop, InstEmit.Nop); + Add("1111101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Out, InstEmit.OutR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("1111011x11100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Out, InstEmit.OutI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("1110101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Out, InstEmit.OutC, InstProps.Rd | InstProps.Ra); + Add("0101110011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.P2r, InstEmit.P2rR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x11101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.P2r, InstEmit.P2rI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.P2r, InstEmit.P2rC, InstProps.Rd | InstProps.Ra); + Add("111000101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pbk, InstEmit.Pbk, InstProps.NoPred); + Add("111000101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pcnt, InstEmit.Pcnt, InstProps.NoPred); + Add("111000100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pexit, InstEmit.Pexit); + Add("1110111111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pixld, InstEmit.Pixld, InstProps.Rd | InstProps.Ra); + Add("111000101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Plongjmp, InstEmit.Plongjmp, InstProps.Bra | InstProps.NoPred); + Add("0101110000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcR, InstProps.Rd | InstProps.Rb); + Add("0011100x00001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcI, InstProps.Rd | InstProps.Ib); + Add("0100110000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcC, InstProps.Rd); + Add("111000100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pret, InstEmit.Pret, InstProps.NoPred); + Add("010110111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x1100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("010010111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("0101000010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pset, InstEmit.Pset, InstProps.Rd); + Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn); + Add("1111000011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2b, InstEmit.R2b, InstProps.Rb); + Add("0101110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pR, InstProps.Ra | InstProps.Rb); + Add("0011100x11110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pI, InstProps.Ra | InstProps.Ib); + Add("0100110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pC, InstProps.Ra); + Add("111000111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ram, InstEmit.Ram, InstProps.NoPred); + Add("1110101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Red, InstEmit.Red, InstProps.Ra); + Add("111000110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ret, InstEmit.Ret, InstProps.Bra); + Add("0101110010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroR, InstProps.Rd | InstProps.Rb); + Add("0011100x10010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroI, InstProps.Rd | InstProps.Ib); + Add("0100110010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroC, InstProps.Rd); + Add("111000110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rtt, InstEmit.Rtt, InstProps.NoPred); + Add("1111000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.S2r, InstEmit.S2r, InstProps.Rd); + Add("111000110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sam, InstEmit.Sam, InstProps.NoPred); + Add("0101110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x10100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra); + Add("111000101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setcrsptr, InstEmit.Setcrsptr, InstProps.Ra | InstProps.NoPred); + Add("111000101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setlmembase, InstEmit.Setlmembase, InstProps.Ra | InstProps.NoPred); + Add("0101101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfLR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0101110011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfRR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x11111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfLI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("0011100x11111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shf, InstEmit.ShfRI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("1110111100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shfl, InstEmit.Shfl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd); + Add("0101110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x01001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlC, InstProps.Rd | InstProps.Ra); + Add("0101110000101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shr, InstEmit.ShrR, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("0011100x00101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shr, InstEmit.ShrI, InstProps.Rd | InstProps.Ra | InstProps.Ib); + Add("0100110000101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shr, InstEmit.ShrC, InstProps.Rd | InstProps.Ra); + Add("111000101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ssy, InstEmit.Ssy, InstProps.NoPred); + Add("101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.St, InstEmit.St, InstProps.Rd | InstProps.Ra); + Add("1110111011011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Stg, InstEmit.Stg, InstProps.Rd | InstProps.Ra); + Add("1110111101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Stl, InstEmit.Stl, InstProps.Rd | InstProps.Ra); + Add("1110111010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Stp, InstEmit.Stp, InstProps.NoPred); + Add("1110111101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sts, InstEmit.Sts, InstProps.Rd | InstProps.Ra); + Add("1110101001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB, InstEmit.SuatomB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("11101010x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suatom, InstEmit.Suatom, InstProps.Rd | InstProps.Ra | InstProps.Rb); + Add("1110101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomB2, InstEmit.SuatomB2, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.Pd2); + Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd2); + Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd2 | InstProps.TexB); + Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.Pd2 | InstProps.Tex); + Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.Pd2 | InstProps.TexB); + Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.Pd2 | InstProps.Tex); + Add("111010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra); + Add("111010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB); + Add("1110101100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustD, InstEmit.SustD, InstProps.Rd | InstProps.Ra | InstProps.Tex); + Add("11101011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustB, InstEmit.SustB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB); + Add("11101011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex); + Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra); + Add("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex); + Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB); + Add("1101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Texs, InstEmit.Texs, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("1101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexsF16, InstEmit.TexsF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("11011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld, InstEmit.Tld, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex); + Add("11011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldB, InstEmit.TldB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB); + Add("1101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tlds, InstEmit.Tlds, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("1101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldsF16, InstEmit.TldsF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4, InstEmit.Tld4, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex); + Add("1101111011xxxxxxxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4B, InstEmit.Tld4B, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB); + Add("1101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4s, InstEmit.Tld4s, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("1101111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4sF16, InstEmit.Tld4sF16, InstProps.Rd | InstProps.Rd2 | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("1101111101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tmml, InstEmit.Tmml, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Tex); + Add("1101111101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TmmlB, InstEmit.TmmlB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TexB); + Add("1101111101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txa, InstEmit.Txa, InstProps.Rd | InstProps.Ra | InstProps.Tex); + Add("110111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txd, InstEmit.Txd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Tex); + Add("1101111001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxdB, InstEmit.TxdB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.TexB); + Add("1101111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txq, InstEmit.Txq, InstProps.Rd | InstProps.Ra | InstProps.Tex); + Add("1101111101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxqB, InstEmit.TxqB, InstProps.Rd | InstProps.Ra | InstProps.TexB); + Add("01010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vabsdiff, InstEmit.Vabsdiff, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("010100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vabsdiff4, InstEmit.Vabsdiff4, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vadd, InstEmit.Vadd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("01011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vmad, InstEmit.Vmad, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vmnmx, InstEmit.Vmnmx, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0101000011011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vote, InstEmit.Vote, InstProps.Rd); + Add("0101000011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Votevtg, InstEmit.Votevtg); + Add("0100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vset, InstEmit.Vset, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0101000011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vsetp, InstEmit.Vsetp, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn); + Add("01010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vshl, InstEmit.Vshl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("01010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vshr, InstEmit.Vshr, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0101101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc); + Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc); + Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc); + Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc); + #endregion + } + + private static void Add(string encoding, InstName name, InstEmitter emitter, InstProps props = InstProps.None) + { + encoding = encoding.Substring(0, EncodingBits); + + int bit = encoding.Length - 1; + int value = 0; + int xMask = 0; + int xBits = 0; + + int[] xPos = new int[encoding.Length]; + + for (int index = 0; index < encoding.Length; index++, bit--) + { + char chr = encoding[index]; + + if (chr == '1') + { + value |= 1 << bit; + } + else if (chr == 'x') + { + xMask |= 1 << bit; + + xPos[xBits++] = bit; + } + } + + xMask = ~xMask; + + TableEntry entry = new TableEntry(name, emitter, props, xBits); + + for (int index = 0; index < (1 << xBits); index++) + { + value &= xMask; + + for (int x = 0; x < xBits; x++) + { + value |= ((index >> x) & 1) << xPos[x]; + } + + if (_opCodes[value].Emitter == null || _opCodes[value].XBits > xBits) + { + _opCodes[value] = entry; + } + } + } + + public static InstOp GetOp(ulong address, ulong opCode) + { + ref TableEntry entry = ref _opCodes[opCode >> (64 - EncodingBits)]; + + if (entry.Emitter != null) + { + return new InstOp(address, opCode, entry.Name, entry.Emitter, entry.Props); + } + + return new InstOp(address, opCode, InstName.Invalid, null, InstProps.None); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IntegerCondition.cs b/Ryujinx.Graphics.Shader/Decoders/IntegerCondition.cs deleted file mode 100644 index a1937c2f..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IntegerCondition.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum IntegerCondition - { - Less = 1 << 0, - Equal = 1 << 1, - Greater = 1 << 2, - - Never = 0, - - LessOrEqual = Less | Equal, - NotEqual = Less | Greater, - GreaterOrEqual = Greater | Equal, - Number = Greater | Equal | Less, - - Always = 7 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IntegerHalfPart.cs b/Ryujinx.Graphics.Shader/Decoders/IntegerHalfPart.cs deleted file mode 100644 index b779f44d..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IntegerHalfPart.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum IntegerHalfPart - { - B32 = 0, - H0 = 1, - H1 = 2 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IntegerShift.cs b/Ryujinx.Graphics.Shader/Decoders/IntegerShift.cs deleted file mode 100644 index ce4d9f3b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IntegerShift.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum IntegerShift - { - NoShift = 0, - ShiftRight = 1, - ShiftLeft = 2 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IntegerSize.cs b/Ryujinx.Graphics.Shader/Decoders/IntegerSize.cs deleted file mode 100644 index d39c2a90..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IntegerSize.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum IntegerSize - { - U8 = 0, - S8 = 1, - U16 = 2, - S16 = 3, - B32 = 4, - B64 = 5, - B128 = 6, - UB128 = 7 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/IntegerType.cs b/Ryujinx.Graphics.Shader/Decoders/IntegerType.cs deleted file mode 100644 index 46734dbe..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/IntegerType.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum IntegerType - { - U8 = 0, - U16 = 1, - U32 = 2, - U64 = 3, - S8 = 4, - S16 = 5, - S32 = 6, - S64 = 7 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/InterpolationMode.cs b/Ryujinx.Graphics.Shader/Decoders/InterpolationMode.cs deleted file mode 100644 index 98ee3b97..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/InterpolationMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum InterpolationMode - { - Pass, - Default, - Constant, - Sc - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/LogicalOperation.cs b/Ryujinx.Graphics.Shader/Decoders/LogicalOperation.cs deleted file mode 100644 index 52214425..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/LogicalOperation.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum LogicalOperation - { - And = 0, - Or = 1, - ExclusiveOr = 2, - Passthrough = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/MufuOperation.cs b/Ryujinx.Graphics.Shader/Decoders/MufuOperation.cs deleted file mode 100644 index 88bd1f5c..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/MufuOperation.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum MufuOperation - { - Cosine = 0, - Sine = 1, - ExponentB2 = 2, - LogarithmB2 = 3, - Reciprocal = 4, - ReciprocalSquareRoot = 5, - Reciprocal64H = 6, - ReciprocalSquareRoot64H = 7, - SquareRoot = 8 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCode.cs b/Ryujinx.Graphics.Shader/Decoders/OpCode.cs deleted file mode 100644 index 27e10f89..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCode.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCode - { - public InstEmitter Emitter { get; } - - public ulong Address { get; } - public long RawOpCode { get; } - - public Register Predicate { get; protected set; } - - public bool InvertPredicate { get; protected set; } - - // When inverted, the always true predicate == always false. - public bool NeverExecute => Predicate.Index == RegisterConsts.PredicateTrueIndex && InvertPredicate; - - public static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCode(emitter, address, opCode); - - public OpCode(InstEmitter emitter, ulong address, long opCode) - { - Emitter = emitter; - Address = address; - RawOpCode = opCode; - - Predicate = new Register(opCode.Extract(16, 3), RegisterType.Predicate); - - InvertPredicate = opCode.Extract(19); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAl2p.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAl2p.cs deleted file mode 100644 index d924b393..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAl2p.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAl2p : OpCode, IOpCodeRd, IOpCodeRa - { - public Register Rd { get; } - public Register Ra { get; } - public Register Predicate44 { get; } - - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAl2p(emitter, address, opCode); - - public OpCodeAl2p(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Predicate44 = new Register(opCode.Extract(44, 3), RegisterType.Predicate); - - Immediate = ((int)opCode << 1) >> 21; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAlu.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAlu.cs deleted file mode 100644 index 035aa730..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAlu.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAlu : OpCode, IOpCodeAlu, IOpCodeRc - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rc { get; } - public Register Predicate39 { get; } - - public int ByteSelection { get; } - - public bool InvertP { get; } - public bool Extended { get; protected set; } - public bool SetCondCode { get; protected set; } - public bool Saturate { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAlu(emitter, address, opCode); - - public OpCodeAlu(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - Predicate39 = new Register(opCode.Extract(39, 3), RegisterType.Predicate); - - ByteSelection = opCode.Extract(41, 2); - - InvertP = opCode.Extract(42); - Extended = opCode.Extract(43); - SetCondCode = opCode.Extract(47); - Saturate = opCode.Extract(50); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluCbuf.cs deleted file mode 100644 index 04ef64df..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluCbuf.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluCbuf : OpCodeAlu, IOpCodeCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluCbuf(emitter, address, opCode); - - public OpCodeAluCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm.cs deleted file mode 100644 index 7faa0d80..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluImm : OpCodeAlu, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluImm(emitter, address, opCode); - - public OpCodeAluImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeS20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm2x10.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm2x10.cs deleted file mode 100644 index b475c8a9..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm2x10.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluImm2x10 : OpCodeAlu, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluImm2x10(emitter, address, opCode); - - public OpCodeAluImm2x10(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.Decode2xF10Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm32.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm32.cs deleted file mode 100644 index 26b27a3d..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluImm32.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluImm32 : OpCodeAlu, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluImm32(emitter, address, opCode); - - public OpCodeAluImm32(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = opCode.Extract(20, 32); - - SetCondCode = opCode.Extract(52); - Extended = opCode.Extract(53); - Saturate = opCode.Extract(54); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluReg.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluReg.cs deleted file mode 100644 index fe61a51f..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluReg.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluReg : OpCodeAlu, IOpCodeReg - { - public Register Rb { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluReg(emitter, address, opCode); - - public OpCodeAluReg(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluRegCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAluRegCbuf.cs deleted file mode 100644 index 628fb472..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAluRegCbuf.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAluRegCbuf : OpCodeAluReg, IOpCodeRegCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAluRegCbuf(emitter, address, opCode); - - public OpCodeAluRegCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - - Rb = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs deleted file mode 100644 index 006a91f3..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAtom.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAtom : OpCode, IOpCodeRd, IOpCodeRa, IOpCodeReg - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rb { get; } - - public bool Extended { get; } - - public AtomicOp AtomicOp { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAtom(emitter, address, opCode); - - public OpCodeAtom(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - - Extended = opCode.Extract(48); - - AtomicOp = (AtomicOp)opCode.Extract(52, 4); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeAttribute.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeAttribute.cs deleted file mode 100644 index 0a24d4c8..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeAttribute : OpCodeAluReg, IOpCodeAttribute - { - public int AttributeOffset { get; } - public bool Patch { get; } - public int Count { get; } - - public bool Phys => !Patch && AttributeOffset == 0 && !Ra.IsRZ; - public bool Indexed => Phys; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeAttribute(emitter, address, opCode); - - public OpCodeAttribute(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - AttributeOffset = opCode.Extract(20, 10); - Patch = opCode.Extract(31); - Count = opCode.Extract(47, 2) + 1; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs deleted file mode 100644 index 7c82c683..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBarrier.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeBarrier : OpCode - { - public BarrierMode Mode { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeBarrier(emitter, address, opCode); - - public OpCodeBarrier(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Mode = (BarrierMode)((opCode >> 32) & 0x9b); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs deleted file mode 100644 index 9ca437b3..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranch.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeBranch : OpCodeConditional - { - public int Offset { get; } - - public bool PushTarget { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeBranch(emitter, address, opCode); - - public OpCodeBranch(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = ((int)(opCode >> 20) << 8) >> 8; - - PushTarget = false; - } - - public ulong GetAbsoluteAddress() - { - return (ulong)((long)Address + (long)Offset + 8); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchIndir.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchIndir.cs deleted file mode 100644 index b3911d6a..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchIndir.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeBranchIndir : OpCode - { - public HashSet PossibleTargets { get; } - - public Register Ra { get; } - - public int Offset { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeBranchIndir(emitter, address, opCode); - - public OpCodeBranchIndir(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - PossibleTargets = new HashSet(); - - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - - Offset = ((int)(opCode >> 20) << 8) >> 8; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs deleted file mode 100644 index 31804870..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeBranchPop.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeBranchPop : OpCodeConditional - { - public Dictionary Targets { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeBranchPop(emitter, address, opCode); - - public OpCodeBranchPop(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Targets = new Dictionary(); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs deleted file mode 100644 index 219eec89..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeConditional.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeConditional : OpCode - { - public Condition Condition { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeConditional(emitter, address, opCode); - - public OpCodeConditional(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Condition = (Condition)opCode.Extract(0, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeDArithImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeDArithImm.cs deleted file mode 100644 index f13bfc47..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeDArithImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeDArithImm : OpCodeFArith, IOpCodeImmF - { - public float Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeDArithImm(emitter, address, opCode); - - public OpCodeDArithImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeD20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs deleted file mode 100644 index f63d5d11..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeExit.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeExit : OpCodeConditional - { - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeExit(emitter, address, opCode); - - public OpCodeExit(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArith.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArith.cs deleted file mode 100644 index d262f157..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArith.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArith : OpCodeAlu, IOpCodeFArith - { - public RoundingMode RoundingMode { get; } - - public FPMultiplyScale Scale { get; } - - public bool FlushToZero { get; } - public bool AbsoluteA { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArith(emitter, address, opCode); - - public OpCodeFArith(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - RoundingMode = (RoundingMode)opCode.Extract(39, 2); - - Scale = (FPMultiplyScale)opCode.Extract(41, 3); - - FlushToZero = opCode.Extract(44); - AbsoluteA = opCode.Extract(46); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithCbuf.cs deleted file mode 100644 index 1475f11b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithCbuf.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArithCbuf : OpCodeFArith, IOpCodeCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArithCbuf(emitter, address, opCode); - - public OpCodeFArithCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm.cs deleted file mode 100644 index 91a6561b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArithImm : OpCodeFArith, IOpCodeImmF - { - public float Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArithImm(emitter, address, opCode); - - public OpCodeFArithImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeF20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm32.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm32.cs deleted file mode 100644 index 09d0a13d..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithImm32.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; -using System; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArithImm32 : OpCodeAlu, IOpCodeFArith, IOpCodeImmF - { - public RoundingMode RoundingMode => RoundingMode.ToNearest; - - public FPMultiplyScale Scale => FPMultiplyScale.None; - - public bool FlushToZero { get; } - public bool AbsoluteA { get; } - - public float Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArithImm32(emitter, address, opCode); - - public OpCodeFArithImm32(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - int imm = opCode.Extract(20, 32); - - Immediate = BitConverter.Int32BitsToSingle(imm); - - SetCondCode = opCode.Extract(52); - AbsoluteA = opCode.Extract(54); - FlushToZero = opCode.Extract(55); - - Saturate = false; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithReg.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithReg.cs deleted file mode 100644 index f4b64584..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithReg.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArithReg : OpCodeFArith, IOpCodeReg - { - public Register Rb { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArithReg(emitter, address, opCode); - - public OpCodeFArithReg(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithRegCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithRegCbuf.cs deleted file mode 100644 index c1b5cca6..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFArithRegCbuf.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFArithRegCbuf : OpCodeFArith, IOpCodeRegCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFArithRegCbuf(emitter, address, opCode); - - public OpCodeFArithRegCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeFsetImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeFsetImm.cs deleted file mode 100644 index aa216db2..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeFsetImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeFsetImm : OpCodeSet, IOpCodeImmF - { - public float Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeFsetImm(emitter, address, opCode); - - public OpCodeFsetImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeF20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfma.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfma.cs deleted file mode 100644 index 9123cb97..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfma.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfma : OpCode, IOpCodeRd, IOpCodeRa, IOpCodeRc - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rc { get; protected set; } - - public FPHalfSwizzle SwizzleA { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfma(emitter, address, opCode); - - public OpCodeHfma(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - SwizzleA = (FPHalfSwizzle)opCode.Extract(47, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaCbuf.cs deleted file mode 100644 index d73223ab..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaCbuf.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfmaCbuf : OpCodeHfma, IOpCodeHfma, IOpCodeCbuf - { - public int Offset { get; } - public int Slot { get; } - - public bool NegateB { get; } - public bool NegateC { get; } - public bool Saturate { get; } - - public FPHalfSwizzle SwizzleB => FPHalfSwizzle.FP32; - public FPHalfSwizzle SwizzleC { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfmaCbuf(emitter, address, opCode); - - public OpCodeHfmaCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - - NegateC = opCode.Extract(51); - Saturate = opCode.Extract(52); - - SwizzleC = (FPHalfSwizzle)opCode.Extract(53, 2); - - NegateB = opCode.Extract(56); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm2x10.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm2x10.cs deleted file mode 100644 index c847be0f..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm2x10.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfmaImm2x10 : OpCodeHfma, IOpCodeHfma, IOpCodeImm - { - public int Immediate { get; } - - public bool NegateB => false; - public bool NegateC { get; } - public bool Saturate { get; } - - public FPHalfSwizzle SwizzleB => FPHalfSwizzle.FP16; - public FPHalfSwizzle SwizzleC { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfmaImm2x10(emitter, address, opCode); - - public OpCodeHfmaImm2x10(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.Decode2xF10Immediate(opCode); - - NegateC = opCode.Extract(51); - Saturate = opCode.Extract(52); - - SwizzleC = (FPHalfSwizzle)opCode.Extract(53, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm32.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm32.cs deleted file mode 100644 index 6d1ab265..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaImm32.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfmaImm32 : OpCodeHfma, IOpCodeHfma, IOpCodeImm - { - public int Immediate { get; } - - public bool NegateB => false; - public bool NegateC { get; } - public bool Saturate => false; - - public FPHalfSwizzle SwizzleB => FPHalfSwizzle.FP16; - public FPHalfSwizzle SwizzleC => FPHalfSwizzle.FP16; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfmaImm32(emitter, address, opCode); - - public OpCodeHfmaImm32(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = opCode.Extract(20, 32); - - NegateC = opCode.Extract(52); - - Rc = Rd; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaReg.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaReg.cs deleted file mode 100644 index ebb1fec9..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaReg.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfmaReg : OpCodeHfma, IOpCodeHfma, IOpCodeReg - { - public Register Rb { get; } - - public bool NegateB { get; } - public bool NegateC { get; } - public bool Saturate { get; } - - public FPHalfSwizzle SwizzleB { get; } - public FPHalfSwizzle SwizzleC { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfmaReg(emitter, address, opCode); - - public OpCodeHfmaReg(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - - SwizzleB = (FPHalfSwizzle)opCode.Extract(28, 2); - - NegateC = opCode.Extract(30); - NegateB = opCode.Extract(31); - Saturate = opCode.Extract(32); - - SwizzleC = (FPHalfSwizzle)opCode.Extract(35, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaRegCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaRegCbuf.cs deleted file mode 100644 index dc5d2fe9..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHfmaRegCbuf.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHfmaRegCbuf : OpCodeHfma, IOpCodeHfma, IOpCodeRegCbuf - { - public int Offset { get; } - public int Slot { get; } - - public bool NegateB { get; } - public bool NegateC { get; } - public bool Saturate { get; } - - public FPHalfSwizzle SwizzleB { get; } - public FPHalfSwizzle SwizzleC => FPHalfSwizzle.FP32; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHfmaRegCbuf(emitter, address, opCode); - - public OpCodeHfmaRegCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - - NegateC = opCode.Extract(51); - Saturate = opCode.Extract(52); - - SwizzleB = (FPHalfSwizzle)opCode.Extract(53, 2); - - NegateB = opCode.Extract(56); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeHsetImm2x10.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeHsetImm2x10.cs deleted file mode 100644 index d5af5049..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeHsetImm2x10.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeHsetImm2x10 : OpCodeSet, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeHsetImm2x10(emitter, address, opCode); - - public OpCodeHsetImm2x10(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.Decode2xF10Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeImage.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeImage.cs deleted file mode 100644 index 36f0b164..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeImage.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeImage : OpCodeTextureBase - { - public Register Ra { get; } - public Register Rb { get; } - public Register Rc { get; } - - public ImageComponents Components { get; } - public IntegerSize Size { get; } - - public bool ByteAddress { get; } - - public ImageDimensions Dimensions { get; } - - public bool UseComponents { get; } - public bool IsBindless { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeImage(emitter, address, opCode); - - public OpCodeImage(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - UseComponents = !opCode.Extract(52); - - if (UseComponents) - { - Components = (ImageComponents)opCode.Extract(20, 4); - } - else - { - Size = (IntegerSize)opCode.Extract(20, 4); - } - - ByteAddress = opCode.Extract(23); - - Dimensions = (ImageDimensions)opCode.Extract(33, 3); - - IsBindless = !opCode.Extract(51); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeIpa.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeIpa.cs deleted file mode 100644 index d38a1b3a..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeIpa.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeIpa : OpCodeAluReg, IOpCodeAttribute - { - public int AttributeOffset { get; } - public int Count => 1; - - public bool Idx { get; } - public bool Indexed => Idx; - - public InterpolationMode Mode { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeIpa(emitter, address, opCode); - - public OpCodeIpa(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - AttributeOffset = opCode.Extract(28, 10); - - Idx = opCode.Extract(38); - - Saturate = opCode.Extract(51); - - Mode = (InterpolationMode)opCode.Extract(54, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLdc.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLdc.cs deleted file mode 100644 index 28d34d5a..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLdc.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLdc : OpCode, IOpCodeRd, IOpCodeRa, IOpCodeCbuf - { - public Register Rd { get; } - public Register Ra { get; } - - public int Offset { get; } - public int Slot { get; } - - public CbIndexMode IndexMode { get; } - public IntegerSize Size { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLdc(emitter, address, opCode); - - public OpCodeLdc(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - - Offset = (opCode.Extract(20, 16) << 16) >> 16; - Slot = opCode.Extract(36, 5); - - IndexMode = (CbIndexMode)opCode.Extract(44, 2); - Size = (IntegerSize)opCode.Extract(48, 3); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLop.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLop.cs deleted file mode 100644 index c774523b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLop.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLop : OpCodeAlu, IOpCodeLop - { - public bool InvertA { get; protected set; } - public bool InvertB { get; protected set; } - - public LogicalOperation LogicalOp { get; } - - public Register Predicate48 { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLop(emitter, address, opCode); - - public OpCodeLop(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - InvertA = opCode.Extract(39); - InvertB = opCode.Extract(40); - - LogicalOp = (LogicalOperation)opCode.Extract(41, 2); - - Predicate48 = new Register(opCode.Extract(48, 3), RegisterType.Predicate); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLopCbuf.cs deleted file mode 100644 index 7a32382a..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopCbuf.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLopCbuf : OpCodeLop, IOpCodeCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLopCbuf(emitter, address, opCode); - - public OpCodeLopCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm.cs deleted file mode 100644 index b2443688..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLopImm : OpCodeLop, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLopImm(emitter, address, opCode); - - public OpCodeLopImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeS20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm32.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm32.cs deleted file mode 100644 index a751c2cd..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopImm32.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLopImm32 : OpCodeAluImm32, IOpCodeLop, IOpCodeImm - { - public LogicalOperation LogicalOp { get; } - - public bool InvertA { get; } - public bool InvertB { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLopImm32(emitter, address, opCode); - - public OpCodeLopImm32(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - LogicalOp = (LogicalOperation)opCode.Extract(53, 2); - - InvertA = opCode.Extract(55); - InvertB = opCode.Extract(56); - - Extended = opCode.Extract(57); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopReg.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeLopReg.cs deleted file mode 100644 index d14e4920..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeLopReg.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeLopReg : OpCodeLop, IOpCodeReg - { - public Register Rb { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeLopReg(emitter, address, opCode); - - public OpCodeLopReg(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeMemory.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeMemory.cs deleted file mode 100644 index 65da3aed..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeMemory.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeMemory : OpCode, IOpCodeRd, IOpCodeRa - { - public Register Rd { get; } - public Register Ra { get; } - - public int Offset { get; } - - public bool Extended { get; } - - public IntegerSize Size { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeMemory(emitter, address, opCode); - - public OpCodeMemory(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - - Offset = (opCode.Extract(20, 24) << 8) >> 8; - - Extended = opCode.Extract(45); - - Size = (IntegerSize)opCode.Extract(48, 3); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs deleted file mode 100644 index c086b460..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeMemoryBarrier.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeMemoryBarrier : OpCode - { - public BarrierLevel Level { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeMemoryBarrier(emitter, address, opCode); - - public OpCodeMemoryBarrier(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Level = (BarrierLevel)opCode.Extract(8, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodePset.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodePset.cs deleted file mode 100644 index 9d88b863..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodePset.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodePset : OpCodeSet - { - public Register Predicate12 { get; } - public Register Predicate29 { get; } - - public bool InvertA { get; } - public bool InvertB { get; } - - public LogicalOperation LogicalOpAB { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodePset(emitter, address, opCode); - - public OpCodePset(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Predicate12 = new Register(opCode.Extract(12, 3), RegisterType.Predicate); - Predicate29 = new Register(opCode.Extract(29, 3), RegisterType.Predicate); - - InvertA = opCode.Extract(15); - InvertB = opCode.Extract(32); - - LogicalOpAB = (LogicalOperation)opCode.Extract(24, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodePush.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodePush.cs deleted file mode 100644 index 4f00a069..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodePush.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodePush : OpCodeBranch - { - public Dictionary PopOps { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodePush(emitter, address, opCode); - - public OpCodePush(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - PopOps = new Dictionary(); - - Predicate = new Register(RegisterConsts.PredicateTrueIndex, RegisterType.Predicate); - - InvertPredicate = false; - - PushTarget = true; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeRed.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeRed.cs deleted file mode 100644 index 98bf9939..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeRed.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeRed : OpCode, IOpCodeRd, IOpCodeRa - { - public Register Rd { get; } - public Register Ra { get; } - - public AtomicOp AtomicOp { get; } - - public ReductionType Type { get; } - - public int Offset { get; } - - public bool Extended { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeRed(emitter, address, opCode); - - public OpCodeRed(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - - Type = (ReductionType)opCode.Extract(20, 3); - - AtomicOp = (AtomicOp)opCode.Extract(23, 3); - - Offset = (opCode.Extract(28, 20) << 12) >> 12; - - Extended = opCode.Extract(48); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSet.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSet.cs deleted file mode 100644 index 94ed0bee..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSet.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeSet : OpCodeAlu - { - public Register Predicate0 { get; } - public Register Predicate3 { get; } - - public bool NegateP { get; } - - public LogicalOperation LogicalOp { get; } - - public bool FlushToZero { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSet(emitter, address, opCode); - - public OpCodeSet(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Predicate0 = new Register(opCode.Extract(0, 3), RegisterType.Predicate); - Predicate3 = new Register(opCode.Extract(3, 3), RegisterType.Predicate); - - LogicalOp = (LogicalOperation)opCode.Extract(45, 2); - - FlushToZero = opCode.Extract(47); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetCbuf.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSetCbuf.cs deleted file mode 100644 index 4e0eccf9..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetCbuf.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeSetCbuf : OpCodeSet, IOpCodeCbuf - { - public int Offset { get; } - public int Slot { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSetCbuf(emitter, address, opCode); - - public OpCodeSetCbuf(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Offset = opCode.Extract(20, 14); - Slot = opCode.Extract(34, 5); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetImm.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSetImm.cs deleted file mode 100644 index 7c82c07c..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetImm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeSetImm : OpCodeSet, IOpCodeImm - { - public int Immediate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSetImm(emitter, address, opCode); - - public OpCodeSetImm(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Immediate = DecoderHelper.DecodeS20Immediate(opCode); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetReg.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSetReg.cs deleted file mode 100644 index 8ef0d7e4..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSetReg.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeSetReg : OpCodeSet, IOpCodeReg - { - public Register Rb { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSetReg(emitter, address, opCode); - - public OpCodeSetReg(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeShuffle.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeShuffle.cs deleted file mode 100644 index f9f42433..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeShuffle.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeShuffle : OpCode, IOpCodeRd, IOpCodeRa - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rb { get; } - public Register Rc { get; } - - public int ImmediateB { get; } - public int ImmediateC { get; } - - public bool IsBImmediate { get; } - public bool IsCImmediate { get; } - - public ShuffleType ShuffleType { get; } - - public Register Predicate48 { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeShuffle(emitter, address, opCode); - - public OpCodeShuffle(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - ImmediateB = opCode.Extract(20, 5); - ImmediateC = opCode.Extract(34, 13); - - IsBImmediate = opCode.Extract(28); - IsCImmediate = opCode.Extract(29); - - ShuffleType = (ShuffleType)opCode.Extract(30, 2); - - Predicate48 = new Register(opCode.Extract(48, 3), RegisterType.Predicate); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSuatom.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSuatom.cs deleted file mode 100644 index 7c807b36..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSuatom.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeSuatom : OpCodeTextureBase - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rb { get; } - public Register Rc { get; } - - public ReductionType Type { get; } - public AtomicOp AtomicOp { get; } - public ImageDimensions Dimensions { get; } - public ClampMode ClampMode { get; } - - public bool ByteAddress { get; } - public bool UseType { get; } - public bool IsBindless { get; } - - public bool CompareAndSwap { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSuatom(emitter, address, opCode); - - public OpCodeSuatom(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - bool supportsBindless = opCode.Extract(54); - - Type = (ReductionType)opCode.Extract(supportsBindless ? 36 : 51, 3); - ByteAddress = opCode.Extract(28); - AtomicOp = (AtomicOp)opCode.Extract(29, 4); // Only useful if CAS is not true. - Dimensions = (ImageDimensions)opCode.Extract(33, 3); - ClampMode = (ClampMode)opCode.Extract(49, 2); - - IsBindless = supportsBindless && !opCode.Extract(51); - UseType = !supportsBindless || opCode.Extract(52); - - CompareAndSwap = opCode.Extract(55); - } - } -} diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeSured.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeSured.cs deleted file mode 100644 index 57b8ec78..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeSured.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ClampMode - { - Ignore = 0, - Trap = 2 - } - - class OpCodeSured : OpCodeTextureBase - { - public Register Ra { get; } - public Register Rb { get; } - public Register Rc { get; } - - public ReductionType Type { get; } - public AtomicOp AtomicOp { get; } - public ImageDimensions Dimensions { get; } - public ClampMode ClampMode { get; } - - public bool UseType { get; } - public bool IsBindless { get; } - public bool ByteAddress { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeSured(emitter, address, opCode); - - public OpCodeSured(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - Type = (ReductionType)opCode.Extract(20, 3); - ByteAddress = opCode.Extract(23); - AtomicOp = (AtomicOp)opCode.Extract(24, 3); - Dimensions = (ImageDimensions)opCode.Extract(33, 3); - ClampMode = (ClampMode)opCode.Extract(49, 2); - - IsBindless = !opCode.Extract(51); - UseType = opCode.Extract(52); - } - } -} diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs deleted file mode 100644 index df09d907..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs +++ /dev/null @@ -1,304 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; -using System; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - static class OpCodeTable - { - public delegate OpCode MakeOp(InstEmitter emitter, ulong address, long opCode); - - private const int EncodingBits = 14; - - private class TableEntry - { - public InstEmitter Emitter { get; } - - public MakeOp MakeOp { get; } - - public int XBits { get; } - - public TableEntry(InstEmitter emitter, MakeOp makeOp, int xBits) - { - Emitter = emitter; - MakeOp = makeOp; - XBits = xBits; - } - } - - private static TableEntry[] _opCodes; - - static OpCodeTable() - { - _opCodes = new TableEntry[1 << EncodingBits]; - -#region Instructions - Set("1110111110100x", InstEmit.Al2p, OpCodeAl2p.Create); - Set("1110111111011x", InstEmit.Ald, OpCodeAttribute.Create); - Set("1110111111110x", InstEmit.Ast, OpCodeAttribute.Create); - Set("11101101xxxxxx", InstEmit.Atom, OpCodeAtom.Create); - Set("11101100xxxxxx", InstEmit.Atoms, OpCodeAtom.Create); - Set("1111000010101x", InstEmit.Bar, OpCodeBarrier.Create); - Set("0100110000000x", InstEmit.Bfe, OpCodeAluCbuf.Create); - Set("0011100x00000x", InstEmit.Bfe, OpCodeAluImm.Create); - Set("0101110000000x", InstEmit.Bfe, OpCodeAluReg.Create); - Set("0100101111110x", InstEmit.Bfi, OpCodeAluCbuf.Create); - Set("0011011x11110x", InstEmit.Bfi, OpCodeAluImm.Create); - Set("0101001111110x", InstEmit.Bfi, OpCodeAluRegCbuf.Create); - Set("0101101111110x", InstEmit.Bfi, OpCodeAluReg.Create); - Set("111000100100xx", InstEmit.Bra, OpCodeBranch.Create); - Set("111000110100xx", InstEmit.Brk, OpCodeBranchPop.Create); - Set("111000100101xx", InstEmit.Brx, OpCodeBranchIndir.Create); - Set("111000100110xx", InstEmit.Cal, OpCodeBranch.Create); - Set("0101000010100x", InstEmit.Csetp, OpCodePset.Create); - Set("0100110001110x", InstEmit.Dadd, OpCodeFArithCbuf.Create); - Set("0011100x01110x", InstEmit.Dadd, OpCodeDArithImm.Create); - Set("0101110001110x", InstEmit.Dadd, OpCodeFArithReg.Create); - Set("1111000011110x", InstEmit.Depbar, OpCode.Create); - Set("010010110111xx", InstEmit.Dfma, OpCodeFArithCbuf.Create); - Set("0011011x0111xx", InstEmit.Dfma, OpCodeDArithImm.Create); - Set("010100110111xx", InstEmit.Dfma, OpCodeFArithRegCbuf.Create); - Set("010110110111xx", InstEmit.Dfma, OpCodeFArithReg.Create); - Set("0100110010000x", InstEmit.Dmul, OpCodeFArithCbuf.Create); - Set("0011100x10000x", InstEmit.Dmul, OpCodeDArithImm.Create); - Set("0101110010000x", InstEmit.Dmul, OpCodeFArithReg.Create); - Set("111000110000xx", InstEmit.Exit, OpCodeExit.Create); - Set("0100110010101x", InstEmit.F2F, OpCodeFArithCbuf.Create); - Set("0011100x10101x", InstEmit.F2F, OpCodeFArithImm.Create); - Set("0101110010101x", InstEmit.F2F, OpCodeFArithReg.Create); - Set("0100110010110x", InstEmit.F2I, OpCodeFArithCbuf.Create); - Set("0011100x10110x", InstEmit.F2I, OpCodeFArithImm.Create); - Set("0101110010110x", InstEmit.F2I, OpCodeFArithReg.Create); - Set("0100110001011x", InstEmit.Fadd, OpCodeFArithCbuf.Create); - Set("0011100x01011x", InstEmit.Fadd, OpCodeFArithImm.Create); - Set("000010xxxxxxxx", InstEmit.Fadd, OpCodeFArithImm32.Create); - Set("0101110001011x", InstEmit.Fadd, OpCodeFArithReg.Create); - Set("010010111010xx", InstEmit.Fcmp, OpCodeFArithCbuf.Create); - Set("0011011x1010xx", InstEmit.Fcmp, OpCodeFArithImm.Create); - Set("010110111010xx", InstEmit.Fcmp, OpCodeFArithReg.Create); - Set("010100111010xx", InstEmit.Fcmp, OpCodeFArithRegCbuf.Create); - Set("010010011xxxxx", InstEmit.Ffma, OpCodeFArithCbuf.Create); - Set("0011001x1xxxxx", InstEmit.Ffma, OpCodeFArithImm.Create); - Set("000011xxxxxxxx", InstEmit.Ffma32i, OpCodeFArithImm32.Create); - Set("010100011xxxxx", InstEmit.Ffma, OpCodeFArithRegCbuf.Create); - Set("010110011xxxxx", InstEmit.Ffma, OpCodeFArithReg.Create); - Set("0100110000110x", InstEmit.Flo, OpCodeAluCbuf.Create); - Set("0011100x00110x", InstEmit.Flo, OpCodeAluImm.Create); - Set("0101110000110x", InstEmit.Flo, OpCodeAluReg.Create); - Set("0100110001100x", InstEmit.Fmnmx, OpCodeFArithCbuf.Create); - Set("0011100x01100x", InstEmit.Fmnmx, OpCodeFArithImm.Create); - Set("0101110001100x", InstEmit.Fmnmx, OpCodeFArithReg.Create); - Set("0100110001101x", InstEmit.Fmul, OpCodeFArithCbuf.Create); - Set("0011100x01101x", InstEmit.Fmul, OpCodeFArithImm.Create); - Set("00011110xxxxxx", InstEmit.Fmul, OpCodeFArithImm32.Create); - Set("0101110001101x", InstEmit.Fmul, OpCodeFArithReg.Create); - Set("0100100xxxxxxx", InstEmit.Fset, OpCodeSetCbuf.Create); - Set("0011000xxxxxxx", InstEmit.Fset, OpCodeFsetImm.Create); - Set("01011000xxxxxx", InstEmit.Fset, OpCodeSetReg.Create); - Set("010010111011xx", InstEmit.Fsetp, OpCodeSetCbuf.Create); - Set("0011011x1011xx", InstEmit.Fsetp, OpCodeFsetImm.Create); - Set("010110111011xx", InstEmit.Fsetp, OpCodeSetReg.Create); - Set("0101000011111x", InstEmit.Fswzadd, OpCodeAluReg.Create); - Set("0111101x1xxxxx", InstEmit.Hadd2, OpCodeAluCbuf.Create); - Set("0111101x0xxxxx", InstEmit.Hadd2, OpCodeAluImm2x10.Create); - Set("0010110xxxxxxx", InstEmit.Hadd2, OpCodeAluImm32.Create); - Set("0101110100010x", InstEmit.Hadd2, OpCodeAluReg.Create); - Set("01110xxx1xxxxx", InstEmit.Hfma2, OpCodeHfmaCbuf.Create); - Set("01110xxx0xxxxx", InstEmit.Hfma2, OpCodeHfmaImm2x10.Create); - Set("0010100xxxxxxx", InstEmit.Hfma2, OpCodeHfmaImm32.Create); - Set("0101110100000x", InstEmit.Hfma2, OpCodeHfmaReg.Create); - Set("01100xxx1xxxxx", InstEmit.Hfma2, OpCodeHfmaRegCbuf.Create); - Set("0111100x1xxxxx", InstEmit.Hmul2, OpCodeAluCbuf.Create); - Set("0111100x0xxxxx", InstEmit.Hmul2, OpCodeAluImm2x10.Create); - Set("0010101xxxxxxx", InstEmit.Hmul2, OpCodeAluImm32.Create); - Set("0101110100001x", InstEmit.Hmul2, OpCodeAluReg.Create); - Set("0111110x1xxxxx", InstEmit.Hset2, OpCodeSetCbuf.Create); - Set("0111110x0xxxxx", InstEmit.Hset2, OpCodeHsetImm2x10.Create); - Set("0101110100011x", InstEmit.Hset2, OpCodeSetReg.Create); - Set("0111111x1xxxxx", InstEmit.Hsetp2, OpCodeSetCbuf.Create); - Set("0111111x0xxxxx", InstEmit.Hsetp2, OpCodeHsetImm2x10.Create); - Set("0101110100100x", InstEmit.Hsetp2, OpCodeSetReg.Create); - Set("0100110010111x", InstEmit.I2F, OpCodeAluCbuf.Create); - Set("0011100x10111x", InstEmit.I2F, OpCodeAluImm.Create); - Set("0101110010111x", InstEmit.I2F, OpCodeAluReg.Create); - Set("0100110011100x", InstEmit.I2I, OpCodeAluCbuf.Create); - Set("0011100x11100x", InstEmit.I2I, OpCodeAluImm.Create); - Set("0101110011100x", InstEmit.I2I, OpCodeAluReg.Create); - Set("0100110000010x", InstEmit.Iadd, OpCodeAluCbuf.Create); - Set("0011100x00010x", InstEmit.Iadd, OpCodeAluImm.Create); - Set("0001110x0xxxxx", InstEmit.Iadd, OpCodeAluImm32.Create); - Set("0101110000010x", InstEmit.Iadd, OpCodeAluReg.Create); - Set("010011001100xx", InstEmit.Iadd3, OpCodeAluCbuf.Create); - Set("0011100x1100xx", InstEmit.Iadd3, OpCodeAluImm.Create); - Set("010111001100xx", InstEmit.Iadd3, OpCodeAluReg.Create); - Set("010010110100xx", InstEmit.Icmp, OpCodeAluCbuf.Create); - Set("0011011x0100xx", InstEmit.Icmp, OpCodeAluImm.Create); - Set("010110110100xx", InstEmit.Icmp, OpCodeAluReg.Create); - Set("010100110100xx", InstEmit.Icmp, OpCodeAluRegCbuf.Create); - Set("010010100xxxxx", InstEmit.Imad, OpCodeAluCbuf.Create); - Set("0011010x0xxxxx", InstEmit.Imad, OpCodeAluImm.Create); - Set("010110100xxxxx", InstEmit.Imad, OpCodeAluReg.Create); - Set("010100100xxxxx", InstEmit.Imad, OpCodeAluRegCbuf.Create); - Set("0100110000100x", InstEmit.Imnmx, OpCodeAluCbuf.Create); - Set("0011100x00100x", InstEmit.Imnmx, OpCodeAluImm.Create); - Set("0101110000100x", InstEmit.Imnmx, OpCodeAluReg.Create); - Set("11100000xxxxxx", InstEmit.Ipa, OpCodeIpa.Create); - Set("1110111111010x", InstEmit.Isberd, OpCodeAlu.Create); - Set("0100110000011x", InstEmit.Iscadd, OpCodeAluCbuf.Create); - Set("0011100x00011x", InstEmit.Iscadd, OpCodeAluImm.Create); - Set("000101xxxxxxxx", InstEmit.Iscadd, OpCodeAluImm32.Create); - Set("0101110000011x", InstEmit.Iscadd, OpCodeAluReg.Create); - Set("010010110101xx", InstEmit.Iset, OpCodeSetCbuf.Create); - Set("0011011x0101xx", InstEmit.Iset, OpCodeSetImm.Create); - Set("010110110101xx", InstEmit.Iset, OpCodeSetReg.Create); - Set("010010110110xx", InstEmit.Isetp, OpCodeSetCbuf.Create); - Set("0011011x0110xx", InstEmit.Isetp, OpCodeSetImm.Create); - Set("010110110110xx", InstEmit.Isetp, OpCodeSetReg.Create); - Set("111000110011xx", InstEmit.Kil, OpCodeExit.Create); - Set("1110111101000x", InstEmit.Ld, OpCodeMemory.Create); - Set("1110111110010x", InstEmit.Ldc, OpCodeLdc.Create); - Set("1110111011010x", InstEmit.Ldg, OpCodeMemory.Create); - Set("1110111101001x", InstEmit.Lds, OpCodeMemory.Create); - Set("010010111101xx", InstEmit.Lea, OpCodeAluCbuf.Create); - Set("0011011x11010x", InstEmit.Lea, OpCodeAluImm.Create); - Set("0101101111010x", InstEmit.Lea, OpCodeAluReg.Create); - Set("000110xxxxxxxx", InstEmit.Lea_Hi, OpCodeAluCbuf.Create); - Set("0101101111011x", InstEmit.Lea_Hi, OpCodeAluReg.Create); - Set("0100110001000x", InstEmit.Lop, OpCodeLopCbuf.Create); - Set("0011100001000x", InstEmit.Lop, OpCodeLopImm.Create); - Set("000001xxxxxxxx", InstEmit.Lop, OpCodeLopImm32.Create); - Set("0101110001000x", InstEmit.Lop, OpCodeLopReg.Create); - Set("0000001xxxxxxx", InstEmit.Lop3, OpCodeLopCbuf.Create); - Set("001111xxxxxxxx", InstEmit.Lop3, OpCodeLopImm.Create); - Set("0101101111100x", InstEmit.Lop3, OpCodeLopReg.Create); - Set("1110111110011x", InstEmit.Membar, OpCodeMemoryBarrier.Create); - Set("0100110010011x", InstEmit.Mov, OpCodeAluCbuf.Create); - Set("0011100x10011x", InstEmit.Mov, OpCodeAluImm.Create); - Set("000000010000xx", InstEmit.Mov, OpCodeAluImm32.Create); - Set("0101110010011x", InstEmit.Mov, OpCodeAluReg.Create); - Set("0101000010000x", InstEmit.Mufu, OpCodeFArith.Create); - Set("0101000010110x", InstEmit.Nop, OpCode.Create); - Set("1111101111100x", InstEmit.Out, OpCode.Create); - Set("111000101010xx", InstEmit.Pbk, OpCodePush.Create); - Set("0100110000001x", InstEmit.Popc, OpCodeAluCbuf.Create); - Set("0011100x00001x", InstEmit.Popc, OpCodeAluImm.Create); - Set("0101110000001x", InstEmit.Popc, OpCodeAluReg.Create); - Set("0101000010001x", InstEmit.Pset, OpCodePset.Create); - Set("0101000010010x", InstEmit.Psetp, OpCodePset.Create); - Set("0100110011110x", InstEmit.R2p, OpCodeAluCbuf.Create); - Set("0011100x11110x", InstEmit.R2p, OpCodeAluImm.Create); - Set("0101110011110x", InstEmit.R2p, OpCodeAluReg.Create); - Set("1110101111111x", InstEmit.Red, OpCodeRed.Create); - Set("111000110010xx", InstEmit.Ret, OpCodeExit.Create); - Set("0100110010010x", InstEmit.Rro, OpCodeFArithCbuf.Create); - Set("0011100x10010x", InstEmit.Rro, OpCodeFArithImm.Create); - Set("0101110010010x", InstEmit.Rro, OpCodeFArithReg.Create); - Set("1111000011001x", InstEmit.S2r, OpCodeAlu.Create); - Set("0100110010100x", InstEmit.Sel, OpCodeAluCbuf.Create); - Set("0011100x10100x", InstEmit.Sel, OpCodeAluImm.Create); - Set("0101110010100x", InstEmit.Sel, OpCodeAluReg.Create); - Set("1110111100010x", InstEmit.Shfl, OpCodeShuffle.Create); - Set("0100110001001x", InstEmit.Shl, OpCodeAluCbuf.Create); - Set("0011100x01001x", InstEmit.Shl, OpCodeAluImm.Create); - Set("0101110001001x", InstEmit.Shl, OpCodeAluReg.Create); - Set("0100110000101x", InstEmit.Shr, OpCodeAluCbuf.Create); - Set("0011100x00101x", InstEmit.Shr, OpCodeAluImm.Create); - Set("0101110000101x", InstEmit.Shr, OpCodeAluReg.Create); - Set("111000101001xx", InstEmit.Ssy, OpCodePush.Create); - Set("1110111101010x", InstEmit.St, OpCodeMemory.Create); - Set("1110111011011x", InstEmit.Stg, OpCodeMemory.Create); - Set("1110111101011x", InstEmit.Sts, OpCodeMemory.Create); - Set("11101011000xxx", InstEmit.Suld, OpCodeImage.Create); - Set("11101011001xxx", InstEmit.Sust, OpCodeImage.Create); - Set("11101011010xxx", InstEmit.Sured, OpCodeSured.Create); - Set("11101010110xxx", InstEmit.Suatom, OpCodeSuatom.Create); - Set("1110101010xxxx", InstEmit.Suatom, OpCodeSuatom.Create); - Set("11101010011xxx", InstEmit.Suatom, OpCodeSuatom.Create); - Set("1110101000xxxx", InstEmit.Suatom, OpCodeSuatom.Create); - Set("1111000011111x", InstEmit.Sync, OpCodeBranchPop.Create); - Set("110000xxxx111x", InstEmit.Tex, OpCodeTex.Create); - Set("1101111010111x", InstEmit.TexB, OpCodeTexB.Create); - Set("1101x00xxxxxxx", InstEmit.Texs, OpCodeTexs.Create); - Set("1101x01xxxxxxx", InstEmit.Texs, OpCodeTlds.Create); - Set("11011111x0xxxx", InstEmit.Texs, OpCodeTld4s.Create); - Set("11011100xx111x", InstEmit.Tld, OpCodeTld.Create); - Set("11011101xx111x", InstEmit.TldB, OpCodeTld.Create); - Set("110010xxxx111x", InstEmit.Tld4, OpCodeTld4.Create); - Set("1101111011111x", InstEmit.Tld4, OpCodeTld4B.Create); - Set("11011111011000", InstEmit.TmmlB, OpCodeTexture.Create); - Set("11011111010110", InstEmit.Tmml, OpCodeTexture.Create); - Set("110111100x1110", InstEmit.Txd, OpCodeTxd.Create); - Set("1101111101001x", InstEmit.Txq, OpCodeTex.Create); - Set("1101111101010x", InstEmit.TxqB, OpCodeTex.Create); - Set("01011111xxxxxx", InstEmit.Vmad, OpCodeVideo.Create); - Set("0011101xxxxxxx", InstEmit.Vmnmx, OpCodeVideo.Create); - Set("0101000011011x", InstEmit.Vote, OpCodeVote.Create); - Set("0100111xxxxxxx", InstEmit.Xmad, OpCodeAluCbuf.Create); - Set("0011011x00xxxx", InstEmit.Xmad, OpCodeAluImm.Create); - Set("010100010xxxxx", InstEmit.Xmad, OpCodeAluRegCbuf.Create); - Set("0101101100xxxx", InstEmit.Xmad, OpCodeAluReg.Create); -#endregion - } - - private static void Set(string encoding, InstEmitter emitter, MakeOp makeOp) - { - if (encoding.Length != EncodingBits) - { - throw new ArgumentException(nameof(encoding)); - } - - int bit = encoding.Length - 1; - int value = 0; - int xMask = 0; - int xBits = 0; - - int[] xPos = new int[encoding.Length]; - - for (int index = 0; index < encoding.Length; index++, bit--) - { - char chr = encoding[index]; - - if (chr == '1') - { - value |= 1 << bit; - } - else if (chr == 'x') - { - xMask |= 1 << bit; - - xPos[xBits++] = bit; - } - } - - xMask = ~xMask; - - TableEntry entry = new TableEntry(emitter, makeOp, xBits); - - for (int index = 0; index < (1 << xBits); index++) - { - value &= xMask; - - for (int x = 0; x < xBits; x++) - { - value |= ((index >> x) & 1) << xPos[x]; - } - - if (_opCodes[value] == null || _opCodes[value].XBits > xBits) - { - _opCodes[value] = entry; - } - } - } - - public static (InstEmitter Emitter, MakeOp MakeOp) GetEmitter(long opCode) - { - TableEntry entry = _opCodes[(ulong)opCode >> (64 - EncodingBits)]; - - if (entry != null) - { - return (entry.Emitter, entry.MakeOp); - } - - return (null, null); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTex.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTex.cs deleted file mode 100644 index c0e4da02..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTex.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTex : OpCodeTexture - { - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTex(emitter, address, opCode); - - public OpCodeTex(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasDepthCompare = opCode.Extract(50); - - HasOffset = opCode.Extract(54); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexB.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTexB.cs deleted file mode 100644 index 33434ae1..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexB.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTexB : OpCodeTex - { - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTexB(emitter, address, opCode); - - public OpCodeTexB(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - switch (opCode.Extract(37, 3)) - { - case 0: LodMode = TextureLodMode.None; break; - case 1: LodMode = TextureLodMode.LodZero; break; - case 2: LodMode = TextureLodMode.LodBias; break; - case 3: LodMode = TextureLodMode.LodLevel; break; - case 6: LodMode = TextureLodMode.LodBiasA; break; - case 7: LodMode = TextureLodMode.LodLevelA; break; - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexs.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTexs.cs deleted file mode 100644 index ea3057c8..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexs.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTexs : OpCodeTextureScalar - { - public TextureTarget Target => (TextureTarget)RawType; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTexs(emitter, address, opCode); - - public OpCodeTexs(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) { } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexture.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTexture.cs deleted file mode 100644 index 55e66f41..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTexture.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTexture : OpCodeTextureBase, IOpCodeTexture - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rb { get; } - - public bool IsArray { get; } - - public TextureDimensions Dimensions { get; } - - public int ComponentMask { get; } - - public TextureLodMode LodMode { get; protected set; } - - public bool HasOffset { get; protected set; } - public bool HasDepthCompare { get; protected set; } - public bool IsMultisample { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTexture(emitter, address, opCode); - - public OpCodeTexture(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - - IsArray = opCode.Extract(28); - - Dimensions = (TextureDimensions)opCode.Extract(29, 2); - - ComponentMask = opCode.Extract(31, 4); - - LodMode = (TextureLodMode)opCode.Extract(55, 3); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureBase.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureBase.cs deleted file mode 100644 index 0da1ca76..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureBase.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTextureBase : OpCode - { - public int HandleOffset { get; } - - public OpCodeTextureBase(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HandleOffset = opCode.Extract(36, 13); - } - } -} diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureScalar.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureScalar.cs deleted file mode 100644 index be33a6f0..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTextureScalar.cs +++ /dev/null @@ -1,60 +0,0 @@ -// ReSharper disable InconsistentNaming -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTextureScalar : OpCodeTextureBase - { -#region "Component mask LUT" - private const int ____ = 0x0; - private const int R___ = 0x1; - private const int _G__ = 0x2; - private const int RG__ = 0x3; - private const int __B_ = 0x4; - private const int RGB_ = 0x7; - private const int ___A = 0x8; - private const int R__A = 0x9; - private const int _G_A = 0xa; - private const int RG_A = 0xb; - private const int __BA = 0xc; - private const int R_BA = 0xd; - private const int _GBA = 0xe; - private const int RGBA = 0xf; - - private static int[,] _maskLut = new int[,] - { - { R___, _G__, __B_, ___A, RG__, R__A, _G_A, __BA }, - { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } - }; -#endregion - - public Register Rd0 { get; } - public Register Ra { get; } - public Register Rb { get; } - public Register Rd1 { get; } - - public int ComponentMask { get; protected set; } - - protected int RawType; - - public bool IsFp16 { get; protected set; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTextureScalar(emitter, address, opCode); - - public OpCodeTextureScalar(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd0 = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - Rd1 = new Register(opCode.Extract(28, 8), RegisterType.Gpr); - - int compSel = opCode.Extract(50, 3); - - RawType = opCode.Extract(53, 4); - - IsFp16 = !opCode.Extract(59); - - ComponentMask = _maskLut[Rd1.IsRZ ? 0 : 1, compSel]; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTld.cs deleted file mode 100644 index 199cf234..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTld : OpCodeTexture - { - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTld(emitter, address, opCode); - - public OpCodeTld(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasOffset = opCode.Extract(35); - - IsMultisample = opCode.Extract(50); - - bool isLL = opCode.Extract(55); - - LodMode = isLL - ? TextureLodMode.LodLevel - : TextureLodMode.LodZero; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4.cs deleted file mode 100644 index db6572ad..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTld4 : OpCodeTexture, IOpCodeTld4 - { - public TextureGatherOffset Offset { get; } - - public int GatherCompIndex { get; } - - public bool Bindless => false; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTld4(emitter, address, opCode); - - public OpCodeTld4(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasDepthCompare = opCode.Extract(50); - - Offset = (TextureGatherOffset)opCode.Extract(54, 2); - - GatherCompIndex = opCode.Extract(56, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4B.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4B.cs deleted file mode 100644 index a3988d00..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4B.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTld4B : OpCodeTexture, IOpCodeTld4 - { - public TextureGatherOffset Offset { get; } - - public int GatherCompIndex { get; } - - public bool Bindless => true; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTld4B(emitter, address, opCode); - - public OpCodeTld4B(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasDepthCompare = opCode.Extract(50); - - Offset = (TextureGatherOffset)opCode.Extract(36, 2); - - GatherCompIndex = opCode.Extract(38, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4s.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4s.cs deleted file mode 100644 index 442d36da..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTld4s.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTld4s : OpCodeTextureScalar - { - public bool HasDepthCompare { get; } - public bool HasOffset { get; } - - public int GatherCompIndex { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTld4s(emitter, address, opCode); - - public OpCodeTld4s(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasDepthCompare = opCode.Extract(50); - HasOffset = opCode.Extract(51); - - GatherCompIndex = opCode.Extract(52, 2); - - IsFp16 = opCode.Extract(55); - - ComponentMask = Rd1.IsRZ ? 3 : 0xf; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTlds.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTlds.cs deleted file mode 100644 index 97b328c4..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTlds.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTlds : OpCodeTextureScalar - { - public TexelLoadTarget Target => (TexelLoadTarget)RawType; - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTlds(emitter, address, opCode); - - public OpCodeTlds(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) { } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTxd.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTxd.cs deleted file mode 100644 index 63185a1b..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTxd.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeTxd : OpCodeTexture - { - public bool IsBindless { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeTxd(emitter, address, opCode); - - public OpCodeTxd(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - HasOffset = opCode.Extract(35); - - IsBindless = opCode.Extract(54); - - LodMode = TextureLodMode.None; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeVideo.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeVideo.cs deleted file mode 100644 index 786b81dc..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeVideo.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeVideo : OpCode, IOpCodeRd, IOpCodeRa, IOpCodeRc - { - public Register Rd { get; } - public Register Ra { get; } - public Register Rb { get; } - public Register Rc { get; } - - public int Immediate { get; } - - public int RaSelection { get; } - public int RbSelection { get; } - - public bool SetCondCode { get; } - - public bool HasRb { get; } - - public VideoType RaType { get; } - public VideoType RbType { get; } - - public VideoPostOp PostOp { get; } - - public bool DstSigned { get; } - public bool Saturate { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeVideo(emitter, address, opCode); - - public OpCodeVideo(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Ra = new Register(opCode.Extract(8, 8), RegisterType.Gpr); - Rb = new Register(opCode.Extract(20, 8), RegisterType.Gpr); - Rc = new Register(opCode.Extract(39, 8), RegisterType.Gpr); - - RaSelection = opCode.Extract(36, 2); - RbSelection = opCode.Extract(28, 2); - - RaType = opCode.Extract(37, 2) switch - { - 2 => VideoType.U16, - 3 => VideoType.U32, - _ => VideoType.U8 - }; - - RbType = opCode.Extract(29, 2) switch - { - 2 => VideoType.U16, - 3 => VideoType.U32, - _ => VideoType.U8 - }; - - if (opCode.Extract(48)) - { - RaType |= VideoType.Signed; - } - - if (!opCode.Extract(50)) - { - // Immediate variant. - Immediate = opCode.Extract(16, 20); - - RbType = opCode.Extract(49) ? VideoType.S16 : VideoType.U16; - - if (RbType == VideoType.S16) - { - Immediate = (Immediate << 12) >> 12; - } - } - else if (opCode.Extract(49)) - { - RbType |= VideoType.Signed; - } - - if (RaType == VideoType.U16) - { - RaSelection &= 1; - } - else if (RaType == VideoType.U32) - { - RaSelection = 0; - } - - if (RbType == VideoType.U16) - { - RbSelection &= 1; - } - else if (RbType == VideoType.U32) - { - RbSelection = 0; - } - - SetCondCode = opCode.Extract(47); - - HasRb = opCode.Extract(50); - - PostOp = (VideoPostOp)opCode.Extract(51, 3); - - DstSigned = opCode.Extract(54); - Saturate = opCode.Extract(55); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeVote.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeVote.cs deleted file mode 100644 index 4fc988bc..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeVote.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Ryujinx.Graphics.Shader.Instructions; - -namespace Ryujinx.Graphics.Shader.Decoders -{ - class OpCodeVote : OpCode, IOpCodeRd, IOpCodePredicate39 - { - public Register Rd { get; } - public Register Predicate39 { get; } - public Register Predicate45 { get; } - - public VoteOp VoteOp { get; } - - public bool InvertP { get; } - - public new static OpCode Create(InstEmitter emitter, ulong address, long opCode) => new OpCodeVote(emitter, address, opCode); - - public OpCodeVote(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode) - { - Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr); - Predicate39 = new Register(opCode.Extract(39, 3), RegisterType.Predicate); - Predicate45 = new Register(opCode.Extract(45, 3), RegisterType.Predicate); - - InvertP = opCode.Extract(42); - - VoteOp = (VoteOp)opCode.Extract(48, 2); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs b/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs deleted file mode 100644 index 90814c69..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/ReductionType.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ReductionType - { - U32 = 0, - S32 = 1, - U64 = 2, - FP32FtzRn = 3, - FP16x2FtzRn = 4, - S64 = 5, - SD32 = 6, - SD64 = 7 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/RoundingMode.cs b/Ryujinx.Graphics.Shader/Decoders/RoundingMode.cs deleted file mode 100644 index 13bb08dc..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/RoundingMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum RoundingMode - { - ToNearest = 0, - TowardsNegativeInfinity = 1, - TowardsPositiveInfinity = 2, - TowardsZero = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/ShuffleType.cs b/Ryujinx.Graphics.Shader/Decoders/ShuffleType.cs deleted file mode 100644 index 2892c8dd..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/ShuffleType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum ShuffleType - { - Indexed = 0, - Up = 1, - Down = 2, - Butterfly = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs b/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs deleted file mode 100644 index 9eaa7a28..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/SystemRegister.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum SystemRegister - { - LaneId = 0, - YDirection = 0x12, - ThreadKill = 0x13, - ThreadId = 0x20, - ThreadIdX = 0x21, - ThreadIdY = 0x22, - ThreadIdZ = 0x23, - CtaIdX = 0x25, - CtaIdY = 0x26, - CtaIdZ = 0x27, - EqMask = 0x38, - LtMask = 0x39, - LeMask = 0x3a, - GtMask = 0x3b, - GeMask = 0x3c - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TexelLoadTarget.cs b/Ryujinx.Graphics.Shader/Decoders/TexelLoadTarget.cs deleted file mode 100644 index e5a0c004..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TexelLoadTarget.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TexelLoadTarget - { - Texture1DLodZero = 0x0, - Texture1DLodLevel = 0x1, - Texture2DLodZero = 0x2, - Texture2DLodZeroOffset = 0x4, - Texture2DLodLevel = 0x5, - Texture2DLodZeroMultisample = 0x6, - Texture3DLodZero = 0x7, - Texture2DArrayLodZero = 0x8, - Texture2DLodLevelOffset = 0xc - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TextureDimensions.cs b/Ryujinx.Graphics.Shader/Decoders/TextureDimensions.cs deleted file mode 100644 index dbdf1927..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TextureDimensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TextureDimensions - { - Texture1D = 0, - Texture2D = 1, - Texture3D = 2, - TextureCube = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TextureGatherOffset.cs b/Ryujinx.Graphics.Shader/Decoders/TextureGatherOffset.cs deleted file mode 100644 index 4e9ade26..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TextureGatherOffset.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TextureGatherOffset - { - None = 0, - Offset = 1, - Offsets = 2 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TextureLodMode.cs b/Ryujinx.Graphics.Shader/Decoders/TextureLodMode.cs deleted file mode 100644 index 0cc6f714..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TextureLodMode.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TextureLodMode - { - None = 0, - LodZero = 1, - LodBias = 2, - LodLevel = 3, - LodBiasA = 4, //? - LodLevelA = 5 //? - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TextureProperty.cs b/Ryujinx.Graphics.Shader/Decoders/TextureProperty.cs deleted file mode 100644 index ea35b1d1..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TextureProperty.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TextureProperty - { - Dimensions = 0x1, - Type = 0x2, - SamplePos = 0x5, - Filter = 0xa, - Lod = 0xc, - Wrap = 0xe, - BorderColor = 0x10 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/TextureTarget.cs b/Ryujinx.Graphics.Shader/Decoders/TextureTarget.cs deleted file mode 100644 index 181a0a0d..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/TextureTarget.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum TextureTarget - { - Texture1DLodZero = 0x0, - Texture2D = 0x1, - Texture2DLodZero = 0x2, - Texture2DLodLevel = 0x3, - Texture2DDepthCompare = 0x4, - Texture2DLodLevelDepthCompare = 0x5, - Texture2DLodZeroDepthCompare = 0x6, - Texture2DArray = 0x7, - Texture2DArrayLodZero = 0x8, - Texture2DArrayLodZeroDepthCompare = 0x9, - Texture3D = 0xa, - Texture3DLodZero = 0xb, - TextureCube = 0xc, - TextureCubeLodLevel = 0xd - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/VideoPostOp.cs b/Ryujinx.Graphics.Shader/Decoders/VideoPostOp.cs deleted file mode 100644 index 65891789..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/VideoPostOp.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum VideoPostOp - { - Mrg16h, - Mrg16l, - Mrg8b0, - Mrg8b2, - Acc, - Min, - Max, - Pass - } -} diff --git a/Ryujinx.Graphics.Shader/Decoders/VideoType.cs b/Ryujinx.Graphics.Shader/Decoders/VideoType.cs deleted file mode 100644 index 7186e7c3..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/VideoType.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum VideoType - { - U8 = 0, - U16 = 1, - U32 = 2, - - Signed = 1 << 2, - - S8 = Signed | U8, - S16 = Signed | U16, - S32 = Signed | U32 - } -} diff --git a/Ryujinx.Graphics.Shader/Decoders/VoteOp.cs b/Ryujinx.Graphics.Shader/Decoders/VoteOp.cs deleted file mode 100644 index 2fe937c8..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/VoteOp.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum VoteOp - { - All = 0, - Any = 1, - AllEqual = 2 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Decoders/XmadCMode.cs b/Ryujinx.Graphics.Shader/Decoders/XmadCMode.cs deleted file mode 100644 index 949a2ef7..00000000 --- a/Ryujinx.Graphics.Shader/Decoders/XmadCMode.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Ryujinx.Graphics.Shader.Decoders -{ - enum XmadCMode - { - Cfull = 0, - Clo = 1, - Chi = 2, - Csfu = 3, - Cbcc = 4 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs index a74782c8..6af42cf2 100644 --- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs +++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs @@ -1,4 +1,6 @@ -namespace Ryujinx.Graphics.Shader +using System; + +namespace Ryujinx.Graphics.Shader { public interface IGpuAccessor { @@ -12,12 +14,7 @@ return 0; } - T MemoryRead(ulong address) where T : unmanaged; - - bool MemoryMapped(ulong address) - { - return true; - } + ReadOnlySpan GetCode(ulong address, int minimumSize); int QueryComputeLocalSizeX() { diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs new file mode 100644 index 00000000..8214c9f4 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs @@ -0,0 +1,526 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.Translation; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void AtomCas(EmitterContext context) + { + InstAtomCas op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented."); + } + + public static void AtomsCas(EmitterContext context) + { + InstAtomsCas op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented."); + } + + public static void B2r(EmitterContext context) + { + InstB2r op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented."); + } + + public static void Bpt(EmitterContext context) + { + InstBpt op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented."); + } + + public static void Cctl(EmitterContext context) + { + InstCctl op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented."); + } + + public static void Cctll(EmitterContext context) + { + InstCctll op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented."); + } + + public static void Cctlt(EmitterContext context) + { + InstCctlt op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented."); + } + + public static void Cont(EmitterContext context) + { + InstContUnsup op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ContUnsup is not implemented."); + } + + public static void Cset(EmitterContext context) + { + InstCsetUnsup op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction CsetUnsup is not implemented."); + } + + public static void Cs2r(EmitterContext context) + { + InstCs2r op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented."); + } + + public static void DmnmxR(EmitterContext context) + { + InstDmnmxR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DmnmxR is not implemented."); + } + + public static void DmnmxI(EmitterContext context) + { + InstDmnmxI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DmnmxI is not implemented."); + } + + public static void DmnmxC(EmitterContext context) + { + InstDmnmxC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DmnmxC is not implemented."); + } + + public static void DsetR(EmitterContext context) + { + InstDsetR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetR is not implemented."); + } + + public static void DsetI(EmitterContext context) + { + InstDsetI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetI is not implemented."); + } + + public static void DsetC(EmitterContext context) + { + InstDsetC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetC is not implemented."); + } + + public static void DsetpR(EmitterContext context) + { + InstDsetpR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetpR is not implemented."); + } + + public static void DsetpI(EmitterContext context) + { + InstDsetpI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetpI is not implemented."); + } + + public static void DsetpC(EmitterContext context) + { + InstDsetpC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction DsetpC is not implemented."); + } + + public static void FchkR(EmitterContext context) + { + InstFchkR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented."); + } + + public static void FchkI(EmitterContext context) + { + InstFchkI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented."); + } + + public static void FchkC(EmitterContext context) + { + InstFchkC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented."); + } + + public static void Getcrsptr(EmitterContext context) + { + InstGetcrsptr op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented."); + } + + public static void Getlmembase(EmitterContext context) + { + InstGetlmembase op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented."); + } + + public static void Ide(EmitterContext context) + { + InstIde op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented."); + } + + public static void IdpR(EmitterContext context) + { + InstIdpR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented."); + } + + public static void IdpC(EmitterContext context) + { + InstIdpC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented."); + } + + public static void ImadspR(EmitterContext context) + { + InstImadspR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented."); + } + + public static void ImadspI(EmitterContext context) + { + InstImadspI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented."); + } + + public static void ImadspC(EmitterContext context) + { + InstImadspC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented."); + } + + public static void ImadspRc(EmitterContext context) + { + InstImadspRc op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented."); + } + + public static void ImulR(EmitterContext context) + { + InstImulR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImulR is not implemented."); + } + + public static void ImulI(EmitterContext context) + { + InstImulI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImulI is not implemented."); + } + + public static void ImulC(EmitterContext context) + { + InstImulC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ImulC is not implemented."); + } + + public static void Imul32i(EmitterContext context) + { + InstImul32i op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Imul32i is not implemented."); + } + + public static void Jcal(EmitterContext context) + { + InstJcal op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented."); + } + + public static void Jmp(EmitterContext context) + { + InstJmp op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented."); + } + + public static void Jmx(EmitterContext context) + { + InstJmx op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented."); + } + + public static void Ld(EmitterContext context) + { + InstLd op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented."); + } + + public static void Lepc(EmitterContext context) + { + InstLepc op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented."); + } + + public static void Longjmp(EmitterContext context) + { + InstLongjmp op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented."); + } + + public static void P2rR(EmitterContext context) + { + InstP2rR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction P2rR is not implemented."); + } + + public static void P2rI(EmitterContext context) + { + InstP2rI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction P2rI is not implemented."); + } + + public static void P2rC(EmitterContext context) + { + InstP2rC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction P2rC is not implemented."); + } + + public static void Pcnt(EmitterContext context) + { + InstPcnt op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Pcnt is not implemented."); + } + + public static void Pexit(EmitterContext context) + { + InstPexit op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented."); + } + + public static void Pixld(EmitterContext context) + { + InstPixld op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented."); + } + + public static void Plongjmp(EmitterContext context) + { + InstPlongjmp op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented."); + } + + public static void Pret(EmitterContext context) + { + InstPret op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented."); + } + + public static void PrmtR(EmitterContext context) + { + InstPrmtR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented."); + } + + public static void PrmtI(EmitterContext context) + { + InstPrmtI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented."); + } + + public static void PrmtC(EmitterContext context) + { + InstPrmtC op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented."); + } + + public static void PrmtRc(EmitterContext context) + { + InstPrmtRc op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented."); + } + + public static void R2b(EmitterContext context) + { + InstR2b op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented."); + } + + public static void Ram(EmitterContext context) + { + InstRam op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented."); + } + + public static void Rtt(EmitterContext context) + { + InstRtt op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented."); + } + + public static void Sam(EmitterContext context) + { + InstSam op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented."); + } + + public static void Setcrsptr(EmitterContext context) + { + InstSetcrsptr op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented."); + } + + public static void Setlmembase(EmitterContext context) + { + InstSetlmembase op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented."); + } + + public static void ShfLR(EmitterContext context) + { + InstShfLR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ShfLR is not implemented."); + } + + public static void ShfRR(EmitterContext context) + { + InstShfRR op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ShfRR is not implemented."); + } + + public static void ShfLI(EmitterContext context) + { + InstShfLI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ShfLI is not implemented."); + } + + public static void ShfRI(EmitterContext context) + { + InstShfRI op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction ShfRI is not implemented."); + } + + public static void St(EmitterContext context) + { + InstSt op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction St is not implemented."); + } + + public static void Stp(EmitterContext context) + { + InstStp op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented."); + } + + public static void Txa(EmitterContext context) + { + InstTxa op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented."); + } + + public static void Vabsdiff(EmitterContext context) + { + InstVabsdiff op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented."); + } + + public static void Vabsdiff4(EmitterContext context) + { + InstVabsdiff4 op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented."); + } + + public static void Vadd(EmitterContext context) + { + InstVadd op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented."); + } + + public static void Votevtg(EmitterContext context) + { + InstVotevtg op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented."); + } + + public static void Vset(EmitterContext context) + { + InstVset op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented."); + } + + public static void Vsetp(EmitterContext context) + { + InstVsetp op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vsetp is not implemented."); + } + + public static void Vshl(EmitterContext context) + { + InstVshl op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented."); + } + + public static void Vshr(EmitterContext context) + { + InstVshr op = context.GetOp(); + + context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented."); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs deleted file mode 100644 index 734d3aa7..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs +++ /dev/null @@ -1,984 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Bfe(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool isReverse = op.RawOpCode.Extract(40); - bool isSigned = op.RawOpCode.Extract(48); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - if (isReverse) - { - srcA = context.BitfieldReverse(srcA); - } - - Operand position = context.BitwiseAnd(srcB, Const(0xff)); - - Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); - - Operand res = isSigned - ? context.BitfieldExtractS32(srcA, position, size) - : context.BitfieldExtractU32(srcA, position, size); - - context.Copy(GetDest(context), res); - - // TODO: CC, X, corner cases - } - - public static void Bfi(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - Operand position = context.BitwiseAnd(srcB, Const(0xff)); - - Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); - - Operand res = context.BitfieldInsert(srcC, srcA, position, size); - - context.Copy(GetDest(context), res); - } - - public static void Csetp(EmitterContext context) - { - OpCodePset op = (OpCodePset)context.CurrOp; - - // TODO: Implement that properly - - Operand p0Res = Const(IrConsts.True); - - Operand p1Res = context.BitwiseNot(p0Res); - - Operand pred = GetPredicate39(context); - - p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred); - - context.Copy(Register(op.Predicate3), p0Res); - context.Copy(Register(op.Predicate0), p1Res); - } - - public static void Flo(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool invert = op.RawOpCode.Extract(40); - bool countZeros = op.RawOpCode.Extract(41); - bool isSigned = op.RawOpCode.Extract(48); - - Operand srcB = context.BitwiseNot(GetSrcB(context), invert); - - Operand res = isSigned - ? context.FindFirstSetS32(srcB) - : context.FindFirstSetU32(srcB); - - if (countZeros) - { - res = context.BitwiseExclusiveOr(res, Const(31)); - } - - context.Copy(GetDest(context), res); - } - - public static void Iadd(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool negateA = false, negateB = false; - - if (!(op is OpCodeAluImm32)) - { - negateB = op.RawOpCode.Extract(48); - negateA = op.RawOpCode.Extract(49); - } - else - { - // TODO: Other IADD32I variant without the negate. - negateA = op.RawOpCode.Extract(56); - } - - Operand srcA = context.INegate(GetSrcA(context), negateA); - Operand srcB = context.INegate(GetSrcB(context), negateB); - - Operand res = context.IAdd(srcA, srcB); - - if (op.Extended) - { - res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); - } - - SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, op.Extended); - - context.Copy(GetDest(context), res); - } - - public static void Iadd3(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - IntegerHalfPart partC = (IntegerHalfPart)op.RawOpCode.Extract(31, 2); - IntegerHalfPart partB = (IntegerHalfPart)op.RawOpCode.Extract(33, 2); - IntegerHalfPart partA = (IntegerHalfPart)op.RawOpCode.Extract(35, 2); - - IntegerShift mode = (IntegerShift)op.RawOpCode.Extract(37, 2); - - bool negateC = op.RawOpCode.Extract(49); - bool negateB = op.RawOpCode.Extract(50); - bool negateA = op.RawOpCode.Extract(51); - - Operand Extend(Operand src, IntegerHalfPart part) - { - if (!(op is OpCodeAluReg) || part == IntegerHalfPart.B32) - { - return src; - } - - if (part == IntegerHalfPart.H0) - { - return context.BitwiseAnd(src, Const(0xffff)); - } - else if (part == IntegerHalfPart.H1) - { - return context.ShiftRightU32(src, Const(16)); - } - else - { - // TODO: Warning. - } - - return src; - } - - Operand srcA = context.INegate(Extend(GetSrcA(context), partA), negateA); - Operand srcB = context.INegate(Extend(GetSrcB(context), partB), negateB); - Operand srcC = context.INegate(Extend(GetSrcC(context), partC), negateC); - - Operand res = context.IAdd(srcA, srcB); - - if (op is OpCodeAluReg && mode != IntegerShift.NoShift) - { - if (mode == IntegerShift.ShiftLeft) - { - res = context.ShiftLeft(res, Const(16)); - } - else if (mode == IntegerShift.ShiftRight) - { - res = context.ShiftRightU32(res, Const(16)); - } - else - { - // TODO: Warning. - } - } - - res = context.IAdd(res, srcC); - - context.Copy(GetDest(context), res); - - // TODO: CC, X, corner cases - } - - public static void Icmp(EmitterContext context) - { - OpCode op = context.CurrOp; - - bool isSigned = op.RawOpCode.Extract(48); - - IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - Operand cmpRes = GetIntComparison(context, cmpOp, srcC, Const(0), isSigned); - - Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); - - context.Copy(GetDest(context), res); - } - - public static void Imad(EmitterContext context) - { - bool signedA = context.CurrOp.RawOpCode.Extract(48); - bool signedB = context.CurrOp.RawOpCode.Extract(53); - bool high = context.CurrOp.RawOpCode.Extract(54); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - Operand res; - - if (high) - { - if (signedA && signedB) - { - res = context.MultiplyHighS32(srcA, srcB); - } - else - { - res = context.MultiplyHighU32(srcA, srcB); - - if (signedA) - { - res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31)))); - } - else if (signedB) - { - res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31)))); - } - } - } - else - { - res = context.IMultiply(srcA, srcB); - } - - res = context.IAdd(res, srcC); - - // TODO: CC, X, SAT, and more? - - context.Copy(GetDest(context), res); - } - - public static void Imnmx(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool isSignedInt = op.RawOpCode.Extract(48); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - Operand resMin = isSignedInt - ? context.IMinimumS32(srcA, srcB) - : context.IMinimumU32(srcA, srcB); - - Operand resMax = isSignedInt - ? context.IMaximumS32(srcA, srcB) - : context.IMaximumU32(srcA, srcB); - - Operand pred = GetPredicate39(context); - Operand res = context.ConditionalSelect(pred, resMin, resMax); - - context.Copy(GetDest(context), res); - - SetZnFlags(context, res, op.SetCondCode); - - // TODO: X flags. - } - - public static void Iscadd(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool negateA = false, negateB = false; - - if (!(op is OpCodeAluImm32)) - { - negateB = op.RawOpCode.Extract(48); - negateA = op.RawOpCode.Extract(49); - } - - int shift = op is OpCodeAluImm32 - ? op.RawOpCode.Extract(53, 5) - : op.RawOpCode.Extract(39, 5); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - srcA = context.ShiftLeft(srcA, Const(shift)); - - srcA = context.INegate(srcA, negateA); - srcB = context.INegate(srcB, negateB); - - Operand res = context.IAdd(srcA, srcB); - - SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, false); - - context.Copy(GetDest(context), res); - } - - public static void Iset(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - bool boolFloat = op.RawOpCode.Extract(44); - bool isSigned = op.RawOpCode.Extract(48); - - IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, op.Extended); - - Operand pred = GetPredicate39(context); - - res = GetPredLogicalOp(context, op.LogicalOp, res, pred); - - Operand dest = GetDest(context); - - if (boolFloat) - { - res = context.ConditionalSelect(res, ConstF(1), Const(0)); - - context.Copy(dest, res); - - SetFPZnFlags(context, res, op.SetCondCode); - } - else - { - context.Copy(dest, res); - - SetZnFlags(context, res, op.SetCondCode, op.Extended); - } - } - - public static void Isetp(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - bool isSigned = op.RawOpCode.Extract(48); - - IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, op.Extended); - - Operand p1Res = context.BitwiseNot(p0Res); - - Operand pred = GetPredicate39(context); - - p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred); - - context.Copy(Register(op.Predicate3), p0Res); - context.Copy(Register(op.Predicate0), p1Res); - } - - public static void Lea(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool negateA = op.RawOpCode.Extract(45); - - int shift = op.RawOpCode.Extract(39, 5); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - srcA = context.ShiftLeft(srcA, Const(shift)); - srcA = context.INegate(srcA, negateA); - - Operand res = context.IAdd(srcA, srcB); - - context.Copy(GetDest(context), res); - - // TODO: CC, X - } - - public static void Lea_Hi(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool isReg = op is OpCodeAluReg; - bool negateA; - int shift; - - if (isReg) - { - negateA = op.RawOpCode.Extract(37); - shift = op.RawOpCode.Extract(28, 5); - } - else - { - negateA = op.RawOpCode.Extract(56); - shift = op.RawOpCode.Extract(51, 5); - } - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - Operand aLow = context.ShiftLeft(srcA, Const(shift)); - Operand aHigh = shift == 0 ? Const(0) : context.ShiftRightU32(srcA, Const(32 - shift)); - aHigh = context.BitwiseOr(aHigh, context.ShiftLeft(srcC, Const(shift))); - - if (negateA) - { - // Perform 64-bit negation by doing bitwise not of the value, - // then adding 1 and carrying over from low to high. - aLow = context.BitwiseNot(aLow); - aHigh = context.BitwiseNot(aHigh); - - aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut); - aHigh = context.IAdd(aHigh, aLowCOut); - } - - Operand res = context.IAdd(aHigh, srcB); - - context.Copy(GetDest(context), res); - - // TODO: CC, X - } - - public static void Lop(EmitterContext context) - { - IOpCodeLop op = (IOpCodeLop)context.CurrOp; - - Operand srcA = context.BitwiseNot(GetSrcA(context), op.InvertA); - Operand srcB = context.BitwiseNot(GetSrcB(context), op.InvertB); - - Operand res = srcB; - - switch (op.LogicalOp) - { - case LogicalOperation.And: res = context.BitwiseAnd (srcA, srcB); break; - case LogicalOperation.Or: res = context.BitwiseOr (srcA, srcB); break; - case LogicalOperation.ExclusiveOr: res = context.BitwiseExclusiveOr(srcA, srcB); break; - } - - EmitLopPredWrite(context, op, res, (ConditionalOperation)context.CurrOp.RawOpCode.Extract(44, 2)); - - context.Copy(GetDest(context), res); - - SetZnFlags(context, res, op.SetCondCode, op.Extended); - } - - public static void Lop3(EmitterContext context) - { - IOpCodeLop op = (IOpCodeLop)context.CurrOp; - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - bool regVariant = op is OpCodeLopReg; - - int truthTable = regVariant - ? op.RawOpCode.Extract(28, 8) - : op.RawOpCode.Extract(48, 8); - - Operand res = Lop3Expression.GetFromTruthTable(context, srcA, srcB, srcC, truthTable); - - if (regVariant) - { - EmitLopPredWrite(context, op, res, (ConditionalOperation)context.CurrOp.RawOpCode.Extract(36, 2)); - } - - context.Copy(GetDest(context), res); - - SetZnFlags(context, res, op.SetCondCode, op.Extended); - } - - public static void Popc(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool invert = op.RawOpCode.Extract(40); - - Operand srcB = context.BitwiseNot(GetSrcB(context), invert); - - Operand res = context.BitCount(srcB); - - context.Copy(GetDest(context), res); - } - - public static void Pset(EmitterContext context) - { - OpCodePset op = (OpCodePset)context.CurrOp; - - bool boolFloat = op.RawOpCode.Extract(44); - - Operand srcA = context.BitwiseNot(Register(op.Predicate12), op.InvertA); - Operand srcB = context.BitwiseNot(Register(op.Predicate29), op.InvertB); - Operand srcC = context.BitwiseNot(Register(op.Predicate39), op.InvertP); - - Operand res = GetPredLogicalOp(context, op.LogicalOpAB, srcA, srcB); - - res = GetPredLogicalOp(context, op.LogicalOp, res, srcC); - - Operand dest = GetDest(context); - - if (boolFloat) - { - context.Copy(dest, context.ConditionalSelect(res, ConstF(1), Const(0))); - } - else - { - context.Copy(dest, res); - } - } - - public static void Psetp(EmitterContext context) - { - OpCodePset op = (OpCodePset)context.CurrOp; - - Operand srcA = context.BitwiseNot(Register(op.Predicate12), op.InvertA); - Operand srcB = context.BitwiseNot(Register(op.Predicate29), op.InvertB); - - Operand p0Res = GetPredLogicalOp(context, op.LogicalOpAB, srcA, srcB); - - Operand p1Res = context.BitwiseNot(p0Res); - - Operand pred = GetPredicate39(context); - - p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred); - - context.Copy(Register(op.Predicate3), p0Res); - context.Copy(Register(op.Predicate0), p1Res); - } - - public static void Rro(EmitterContext context) - { - // This is the range reduction operator, - // we translate it as a simple move, as it - // should be always followed by a matching - // MUFU instruction. - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool negateB = op.RawOpCode.Extract(45); - bool absoluteB = op.RawOpCode.Extract(49); - - Operand srcB = GetSrcB(context); - - srcB = context.FPAbsNeg(srcB, absoluteB, negateB); - - context.Copy(GetDest(context), srcB); - } - - public static void Shl(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool isMasked = op.RawOpCode.Extract(39); - - Operand srcB = GetSrcB(context); - - if (isMasked) - { - srcB = context.BitwiseAnd(srcB, Const(0x1f)); - } - - Operand res = context.ShiftLeft(GetSrcA(context), srcB); - - if (!isMasked) - { - // Clamped shift value. - Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); - - res = context.ConditionalSelect(isLessThan32, res, Const(0)); - } - - // TODO: X, CC - - context.Copy(GetDest(context), res); - } - - public static void Shr(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool isMasked = op.RawOpCode.Extract(39); - bool isReverse = op.RawOpCode.Extract(40); - bool isSigned = op.RawOpCode.Extract(48); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - if (isReverse) - { - srcA = context.BitfieldReverse(srcA); - } - - if (isMasked) - { - srcB = context.BitwiseAnd(srcB, Const(0x1f)); - } - - Operand res = isSigned - ? context.ShiftRightS32(srcA, srcB) - : context.ShiftRightU32(srcA, srcB); - - if (!isMasked) - { - // Clamped shift value. - Operand resShiftBy32; - - if (isSigned) - { - resShiftBy32 = context.ShiftRightS32(srcA, Const(31)); - } - else - { - resShiftBy32 = Const(0); - } - - Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); - - res = context.ConditionalSelect(isLessThan32, res, resShiftBy32); - } - - // TODO: X, CC - - context.Copy(GetDest(context), res); - } - - public static void Xmad(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - bool signedA = context.CurrOp.RawOpCode.Extract(48); - bool signedB = context.CurrOp.RawOpCode.Extract(49); - bool highA = context.CurrOp.RawOpCode.Extract(53); - - bool isReg = (op is OpCodeAluReg) && !(op is OpCodeAluRegCbuf); - bool isImm = (op is OpCodeAluImm); - - XmadCMode mode = isReg || isImm - ? (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 3) - : (XmadCMode)context.CurrOp.RawOpCode.Extract(50, 2); - - bool highB = false; - - if (isReg) - { - highB = context.CurrOp.RawOpCode.Extract(35); - } - else if (!isImm) - { - highB = context.CurrOp.RawOpCode.Extract(52); - } - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - // XMAD immediates are 16-bits unsigned integers. - if (srcB.Type == OperandType.Constant) - { - srcB = Const(srcB.Value & 0xffff); - } - - Operand Extend16To32(Operand src, bool high, bool signed) - { - if (signed && high) - { - return context.ShiftRightS32(src, Const(16)); - } - else if (signed) - { - return context.BitfieldExtractS32(src, Const(0), Const(16)); - } - else if (high) - { - return context.ShiftRightU32(src, Const(16)); - } - else - { - return context.BitwiseAnd(src, Const(0xffff)); - } - } - - srcA = Extend16To32(srcA, highA, signedA); - srcB = Extend16To32(srcB, highB, signedB); - - bool productShiftLeft = false; - bool merge = false; - - if (op is OpCodeAluCbuf) - { - productShiftLeft = context.CurrOp.RawOpCode.Extract(55); - merge = context.CurrOp.RawOpCode.Extract(56); - } - else if (!(op is OpCodeAluRegCbuf)) - { - productShiftLeft = context.CurrOp.RawOpCode.Extract(36); - merge = context.CurrOp.RawOpCode.Extract(37); - } - - bool extended; - - if ((op is OpCodeAluReg) || (op is OpCodeAluImm)) - { - extended = context.CurrOp.RawOpCode.Extract(38); - } - else - { - extended = context.CurrOp.RawOpCode.Extract(54); - } - - Operand res = context.IMultiply(srcA, srcB); - - if (productShiftLeft) - { - res = context.ShiftLeft(res, Const(16)); - } - - switch (mode) - { - case XmadCMode.Cfull: break; - - case XmadCMode.Clo: srcC = Extend16To32(srcC, high: false, signed: false); break; - case XmadCMode.Chi: srcC = Extend16To32(srcC, high: true, signed: false); break; - - case XmadCMode.Cbcc: - { - srcC = context.IAdd(srcC, context.ShiftLeft(GetSrcB(context), Const(16))); - - break; - } - - case XmadCMode.Csfu: - { - Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16)); - Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16)); - - srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB)); - - break; - } - - default: /* TODO: Warning */ break; - } - - Operand product = res; - - if (extended) - { - // Add with carry. - res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); - } - else - { - // Add (no carry in). - res = context.IAdd(res, srcC); - } - - SetIaddFlags(context, res, product, srcC, op.SetCondCode, extended); - - if (merge) - { - res = context.BitwiseAnd(res, Const(0xffff)); - res = context.BitwiseOr(res, context.ShiftLeft(GetSrcB(context), Const(16))); - } - - context.Copy(GetDest(context), res); - } - - private static Operand GetIntComparison( - EmitterContext context, - IntegerCondition cond, - Operand srcA, - Operand srcB, - bool isSigned, - bool extended) - { - return extended - ? GetIntComparisonExtended(context, cond, srcA, srcB, isSigned) - : GetIntComparison (context, cond, srcA, srcB, isSigned); - } - - private static Operand GetIntComparisonExtended( - EmitterContext context, - IntegerCondition cond, - Operand srcA, - Operand srcB, - bool isSigned) - { - Operand res; - - if (cond == IntegerCondition.Always) - { - res = Const(IrConsts.True); - } - else if (cond == IntegerCondition.Never) - { - res = Const(IrConsts.False); - } - else - { - res = context.ISubtract(srcA, srcB); - res = context.IAdd(res, context.BitwiseNot(GetCF())); - - switch (cond) - { - case Decoders.IntegerCondition.Equal: // r = xh == yh && xl == yl - res = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetZF()); - break; - case Decoders.IntegerCondition.Less: // r = xh < yh || (xh == yh && xl < yl) - Operand notC = context.BitwiseNot(GetCF()); - Operand prevLt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notC); - res = isSigned - ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLt) - : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLt); - break; - case Decoders.IntegerCondition.LessOrEqual: // r = xh < yh || (xh == yh && xl <= yl) - Operand zOrNotC = context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF())); - Operand prevLe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), zOrNotC); - res = isSigned - ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLe) - : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLe); - break; - case Decoders.IntegerCondition.Greater: // r = xh > yh || (xh == yh && xl > yl) - Operand notZAndC = context.BitwiseAnd(context.BitwiseNot(GetZF()), GetCF()); - Operand prevGt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notZAndC); - res = isSigned - ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGt) - : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGt); - break; - case Decoders.IntegerCondition.GreaterOrEqual: // r = xh > yh || (xh == yh && xl >= yl) - Operand prevGe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetCF()); - res = isSigned - ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGe) - : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGe); - break; - case Decoders.IntegerCondition.NotEqual: // r = xh != yh || xl != yl - context.BitwiseOr(context.ICompareNotEqual(srcA, srcB), context.BitwiseNot(GetZF())); - break; - default: - throw new InvalidOperationException($"Unexpected condition \"{cond}\"."); - } - } - - return res; - } - - private static Operand GetIntComparison( - EmitterContext context, - IntegerCondition cond, - Operand srcA, - Operand srcB, - bool isSigned) - { - Operand res; - - if (cond == IntegerCondition.Always) - { - res = Const(IrConsts.True); - } - else if (cond == IntegerCondition.Never) - { - res = Const(IrConsts.False); - } - else - { - var inst = cond switch - { - IntegerCondition.Less => Instruction.CompareLessU32, - IntegerCondition.Equal => Instruction.CompareEqual, - IntegerCondition.LessOrEqual => Instruction.CompareLessOrEqualU32, - IntegerCondition.Greater => Instruction.CompareGreaterU32, - IntegerCondition.NotEqual => Instruction.CompareNotEqual, - IntegerCondition.GreaterOrEqual => Instruction.CompareGreaterOrEqualU32, - _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".") - }; - - if (isSigned) - { - switch (cond) - { - case IntegerCondition.Less: inst = Instruction.CompareLess; break; - case IntegerCondition.LessOrEqual: inst = Instruction.CompareLessOrEqual; break; - case IntegerCondition.Greater: inst = Instruction.CompareGreater; break; - case IntegerCondition.GreaterOrEqual: inst = Instruction.CompareGreaterOrEqual; break; - } - } - - res = context.Add(inst, Local(), srcA, srcB); - } - - return res; - } - - private static void EmitLopPredWrite(EmitterContext context, IOpCodeLop op, Operand result, ConditionalOperation condOp) - { - if (op is OpCodeLop opLop && !opLop.Predicate48.IsPT) - { - Operand pRes; - - if (condOp == ConditionalOperation.False) - { - pRes = Const(IrConsts.False); - } - else if (condOp == ConditionalOperation.True) - { - pRes = Const(IrConsts.True); - } - else if (condOp == ConditionalOperation.Zero) - { - pRes = context.ICompareEqual(result, Const(0)); - } - else /* if (opLop.CondOp == ConditionalOperation.NotZero) */ - { - pRes = context.ICompareNotEqual(result, Const(0)); - } - - context.Copy(Register(opLop.Predicate48), pRes); - } - } - - private static void SetIaddFlags( - EmitterContext context, - Operand res, - Operand srcA, - Operand srcB, - bool setCC, - bool extended) - { - if (!setCC) - { - return; - } - - if (extended) - { - // C = (d == a && CIn) || d < a - Operand tempC0 = context.ICompareEqual (res, srcA); - Operand tempC1 = context.ICompareLessUnsigned(res, srcA); - - tempC0 = context.BitwiseAnd(tempC0, GetCF()); - - context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1)); - } - else - { - // C = d < a - context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA)); - } - - // V = (d ^ a) & ~(a ^ b) < 0 - Operand tempV0 = context.BitwiseExclusiveOr(res, srcA); - Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB); - - tempV1 = context.BitwiseNot(tempV1); - - Operand tempV = context.BitwiseAnd(tempV0, tempV1); - - context.Copy(GetVF(), context.ICompareLess(tempV, Const(0))); - - SetZnFlags(context, res, setCC: true, extended: extended); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs index 7fe969a0..3dda5316 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAluHelper.cs @@ -10,50 +10,39 @@ namespace Ryujinx.Graphics.Shader.Instructions { static class InstEmitAluHelper { - public static long GetIntMin(IntegerType type) + public static long GetIntMin(IDstFmt type) { - switch (type) + return type switch { - case IntegerType.U8: return byte.MinValue; - case IntegerType.S8: return sbyte.MinValue; - case IntegerType.U16: return ushort.MinValue; - case IntegerType.S16: return short.MinValue; - case IntegerType.U32: return uint.MinValue; - case IntegerType.S32: return int.MinValue; - } - - throw new ArgumentException($"The type \"{type}\" is not a supported int type."); + IDstFmt.U16 => ushort.MinValue, + IDstFmt.S16 => short.MinValue, + IDstFmt.U32 => uint.MinValue, + IDstFmt.S32 => int.MinValue, + _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") + }; } - public static long GetIntMax(IntegerType type) + public static long GetIntMax(IDstFmt type) { - switch (type) + return type switch { - case IntegerType.U8: return byte.MaxValue; - case IntegerType.S8: return sbyte.MaxValue; - case IntegerType.U16: return ushort.MaxValue; - case IntegerType.S16: return short.MaxValue; - case IntegerType.U32: return uint.MaxValue; - case IntegerType.S32: return int.MaxValue; - } - - throw new ArgumentException($"The type \"{type}\" is not a supported int type."); + IDstFmt.U16 => ushort.MaxValue, + IDstFmt.S16 => short.MaxValue, + IDstFmt.U32 => uint.MaxValue, + IDstFmt.S32 => int.MaxValue, + _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.") + }; } - public static Operand GetPredLogicalOp( - EmitterContext context, - LogicalOperation logicalOp, - Operand input, - Operand pred) + public static Operand GetPredLogicalOp(EmitterContext context, BoolOp logicOp, Operand input, Operand pred) { - switch (logicalOp) + return logicOp switch { - case LogicalOperation.And: return context.BitwiseAnd (input, pred); - case LogicalOperation.Or: return context.BitwiseOr (input, pred); - case LogicalOperation.ExclusiveOr: return context.BitwiseExclusiveOr(input, pred); - } - - return input; + BoolOp.And => context.BitwiseAnd(input, pred), + BoolOp.Or => context.BitwiseOr(input, pred), + BoolOp.Xor => context.BitwiseExclusiveOr(input, pred), + _ => input + }; } public static void SetZnFlags(EmitterContext context, Operand dest, bool setCC, bool extended = false) diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs new file mode 100644 index 00000000..e865caf2 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs @@ -0,0 +1,190 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Al2p(EmitterContext context) + { + InstAl2p op = context.GetOp(); + + context.Copy(GetDest(op.Dest), context.IAdd(GetSrcReg(context, op.SrcA), Const(op.Imm11))); + } + + public static void Ald(EmitterContext context) + { + InstAld op = context.GetOp(); + + Operand primVertex = context.Copy(GetSrcReg(context, op.SrcB)); + + for (int index = 0; index < (int)op.AlSize + 1; index++) + { + Register rd = new Register(op.Dest + index, RegisterType.Gpr); + + if (rd.IsRZ) + { + break; + } + + if (op.Phys) + { + Operand userAttrOffset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); + Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); + + context.Copy(Register(rd), context.LoadAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, primVertex)); + + context.Config.SetUsedFeature(FeatureFlags.IaIndexing); + } + else if (op.SrcB == RegisterConsts.RegisterZeroIndex) + { + Operand src = Attribute(op.Imm11 + index * 4); + + context.FlagAttributeRead(src.Value); + + context.Copy(Register(rd), src); + } + else + { + Operand src = Const(op.Imm11 + index * 4); + + context.FlagAttributeRead(src.Value); + + context.Copy(Register(rd), context.LoadAttribute(src, Const(0), primVertex)); + } + } + } + + public static void Ast(EmitterContext context) + { + InstAst op = context.GetOp(); + + for (int index = 0; index < (int)op.AlSize + 1; index++) + { + if (op.SrcB + index > RegisterConsts.RegisterZeroIndex) + { + break; + } + + Register rd = new Register(op.SrcB + index, RegisterType.Gpr); + + if (op.Phys) + { + Operand userAttrOffset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); + Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); + + context.StoreAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, Register(rd)); + + context.Config.SetUsedFeature(FeatureFlags.OaIndexing); + } + else + { + Operand dest = Attribute(op.Imm11 + index * 4); + + context.FlagAttributeWritten(dest.Value); + + context.Copy(dest, Register(rd)); + } + } + } + + public static void Ipa(EmitterContext context) + { + InstIpa op = context.GetOp(); + + context.FlagAttributeRead(op.Imm10); + + Operand res; + + if (op.Idx) + { + Operand userAttrOffset = context.ISubtract(GetSrcReg(context, op.SrcA), Const(AttributeConsts.UserAttributeBase)); + Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); + + res = context.LoadAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, Const(0)); + res = context.FPMultiply(res, Attribute(AttributeConsts.PositionW)); + + context.Config.SetUsedFeature(FeatureFlags.IaIndexing); + } + else + { + res = Attribute(op.Imm10); + + if (op.Imm10 >= AttributeConsts.UserAttributeBase && op.Imm10 < AttributeConsts.UserAttributeEnd) + { + int index = (op.Imm10 - AttributeConsts.UserAttributeBase) >> 4; + + if (context.Config.ImapTypes[index].GetFirstUsedType() == PixelImap.Perspective) + { + res = context.FPMultiply(res, Attribute(AttributeConsts.PositionW)); + } + } + } + + if (op.IpaOp == IpaOp.Multiply) + { + Operand srcB = GetSrcReg(context, op.SrcB); + + res = context.FPMultiply(res, srcB); + } + + res = context.FPSaturate(res, op.Sat); + + context.Copy(GetDest(op.Dest), res); + } + + public static void Isberd(EmitterContext context) + { + InstIsberd op = context.GetOp(); + + // This instruction performs a load from ISBE memory, + // however it seems to be only used to get some vertex + // input data, so we instead propagate the offset so that + // it can be used on the attribute load. + context.Copy(GetDest(op.Dest), GetSrcReg(context, op.SrcA)); + } + + public static void OutR(EmitterContext context) + { + InstOutR op = context.GetOp(); + + EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); + } + + public static void OutI(EmitterContext context) + { + InstOutI op = context.GetOp(); + + EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); + } + + public static void OutC(EmitterContext context) + { + InstOutC op = context.GetOp(); + + EmitOut(context, op.OutType.HasFlag(OutType.Emit), op.OutType.HasFlag(OutType.Cut)); + } + + private static void EmitOut(EmitterContext context, bool emit, bool cut) + { + if (!(emit || cut)) + { + context.Config.GpuAccessor.Log("Invalid OUT encoding."); + } + + if (emit) + { + context.EmitVertex(); + } + + if (cut) + { + context.EndPrimitive(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs new file mode 100644 index 00000000..f3114c6e --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitBarrier.cs @@ -0,0 +1,44 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.Translation; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Bar(EmitterContext context) + { + InstBar op = context.GetOp(); + + // TODO: Support other modes. + if (op.BarOp == BarOp.Sync) + { + context.Barrier(); + } + else + { + context.Config.GpuAccessor.Log($"Invalid barrier mode: {op.BarOp}."); + } + } + + public static void Depbar(EmitterContext context) + { + InstDepbar op = context.GetOp(); + + // No operation. + } + + public static void Membar(EmitterContext context) + { + InstMembar op = context.GetOp(); + + if (op.Membar == Decoders.Membar.Cta) + { + context.GroupMemoryBarrier(); + } + else + { + context.MemoryBarrier(); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs new file mode 100644 index 00000000..7a141bbc --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitBitfield.cs @@ -0,0 +1,190 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void BfeR(EmitterContext context) + { + InstBfeR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); + } + + public static void BfeI(EmitterContext context) + { + InstBfeI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); + } + + public static void BfeC(EmitterContext context) + { + InstBfeC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed); + } + + public static void BfiR(EmitterContext context) + { + InstBfiR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitBfi(context, srcA, srcB, srcC, op.Dest); + } + + public static void BfiI(EmitterContext context) + { + InstBfiI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitBfi(context, srcA, srcB, srcC, op.Dest); + } + + public static void BfiC(EmitterContext context) + { + InstBfiC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitBfi(context, srcA, srcB, srcC, op.Dest); + } + + public static void BfiRc(EmitterContext context) + { + InstBfiRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitBfi(context, srcA, srcB, srcC, op.Dest); + } + + public static void FloR(EmitterContext context) + { + InstFloR op = context.GetOp(); + + EmitFlo(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB, op.Sh, op.Signed); + } + + public static void FloI(EmitterContext context) + { + InstFloI op = context.GetOp(); + + EmitFlo(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB, op.Sh, op.Signed); + } + + public static void FloC(EmitterContext context) + { + InstFloC op = context.GetOp(); + + EmitFlo(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB, op.Sh, op.Signed); + } + + public static void PopcR(EmitterContext context) + { + InstPopcR op = context.GetOp(); + + EmitPopc(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB); + } + + public static void PopcI(EmitterContext context) + { + InstPopcI op = context.GetOp(); + + EmitPopc(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB); + } + + public static void PopcC(EmitterContext context) + { + InstPopcC op = context.GetOp(); + + EmitPopc(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB); + } + + private static void EmitBfe( + EmitterContext context, + Operand srcA, + Operand srcB, + int rd, + bool bitReverse, + bool isSigned) + { + if (bitReverse) + { + srcA = context.BitfieldReverse(srcA); + } + + Operand position = context.BitwiseAnd(srcB, Const(0xff)); + + Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); + + Operand res = isSigned + ? context.BitfieldExtractS32(srcA, position, size) + : context.BitfieldExtractU32(srcA, position, size); + + context.Copy(GetDest(rd), res); + + // TODO: CC, X, corner cases. + } + + private static void EmitBfi(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int rd) + { + Operand position = context.BitwiseAnd(srcB, Const(0xff)); + + Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8)); + + Operand res = context.BitfieldInsert(srcC, srcA, position, size); + + context.Copy(GetDest(rd), res); + } + + private static void EmitFlo(EmitterContext context, Operand src, int rd, bool invert, bool sh, bool isSigned) + { + Operand srcB = context.BitwiseNot(src, invert); + + Operand res = isSigned + ? context.FindFirstSetS32(srcB) + : context.FindFirstSetU32(srcB); + + if (sh) + { + res = context.BitwiseExclusiveOr(res, Const(31)); + } + + context.Copy(GetDest(rd), res); + } + + private static void EmitPopc(EmitterContext context, Operand src, int rd, bool invert) + { + Operand srcB = context.BitwiseNot(src, invert); + + Operand res = context.BitCount(srcB); + + context.Copy(GetDest(rd), res); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index c4c6c55b..43b07cc2 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -1,253 +1,400 @@ using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; +using System; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; namespace Ryujinx.Graphics.Shader.Instructions { static partial class InstEmit { - public static void F2F(EmitterContext context) + public static void F2fR(EmitterContext context) { - OpCodeFArith op = (OpCodeFArith)context.CurrOp; + InstF2fR op = context.GetOp(); - FPType dstType = (FPType)op.RawOpCode.Extract(8, 2); - FPType srcType = (FPType)op.RawOpCode.Extract(10, 2); + var src = UnpackReg(context, op.SrcFmt, op.Sh, op.SrcB); - bool round = op.RawOpCode.Extract(42); - bool negateB = op.RawOpCode.Extract(45); - bool absoluteB = op.RawOpCode.Extract(49); + EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); + } - Operand srcB = context.FPAbsNeg(GetSrcB(context, srcType), absoluteB, negateB, srcType.ToInstFPType()); + public static void F2fI(EmitterContext context) + { + InstF2fI op = context.GetOp(); - if (round && srcType == dstType) + var src = UnpackImm(context, op.SrcFmt, op.Sh, Imm20ToFloat(op.Imm20)); + + EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); + } + + public static void F2fC(EmitterContext context) + { + InstF2fC op = context.GetOp(); + + var src = UnpackCbuf(context, op.SrcFmt, op.Sh, op.CbufSlot, op.CbufOffset); + + EmitF2F(context, op.SrcFmt, op.DstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB, op.Sat); + } + + public static void F2iR(EmitterContext context) + { + InstF2iR op = context.GetOp(); + + var src = UnpackReg(context, op.SrcFmt, op.Sh, op.SrcB); + + EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); + } + + public static void F2iI(EmitterContext context) + { + InstF2iI op = context.GetOp(); + + var src = UnpackImm(context, op.SrcFmt, op.Sh, Imm20ToFloat(op.Imm20)); + + EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); + } + + public static void F2iC(EmitterContext context) + { + InstF2iC op = context.GetOp(); + + var src = UnpackCbuf(context, op.SrcFmt, op.Sh, op.CbufSlot, op.CbufOffset); + + EmitF2I(context, op.SrcFmt, op.IDstFmt, op.RoundMode, src, op.Dest, op.AbsB, op.NegB); + } + + public static void I2fR(EmitterContext context) + { + InstI2fR op = context.GetOp(); + + var src = GetSrcReg(context, op.SrcB); + + EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); + } + + public static void I2fI(EmitterContext context) + { + InstI2fI op = context.GetOp(); + + var src = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); + } + + public static void I2fC(EmitterContext context) + { + InstI2fC op = context.GetOp(); + + var src = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitI2F(context, op.ISrcFmt, op.DstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB); + } + + public static void I2iR(EmitterContext context) + { + InstI2iR op = context.GetOp(); + + var src = GetSrcReg(context, op.SrcB); + + EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + } + + public static void I2iI(EmitterContext context) + { + InstI2iI op = context.GetOp(); + + var src = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + } + + public static void I2iC(EmitterContext context) + { + InstI2iC op = context.GetOp(); + + var src = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitI2I(context, op.SrcFmt, op.IDstFmt, src, op.ByteSel, op.Dest, op.AbsB, op.NegB, op.Sat); + } + + private static void EmitF2F( + EmitterContext context, + DstFmt srcType, + DstFmt dstType, + IntegerRound roundingMode, + Operand src, + int rd, + bool absolute, + bool negate, + bool saturate) + { + Operand srcB = context.FPAbsNeg(src, absolute, negate, srcType.ToInstFPType()); + + if (srcType == dstType) { - switch (op.RoundingMode) + srcB = roundingMode switch { - case RoundingMode.ToNearest: - srcB = context.FPRound(srcB, srcType.ToInstFPType()); - break; - - case RoundingMode.TowardsNegativeInfinity: - srcB = context.FPFloor(srcB, srcType.ToInstFPType()); - break; - - case RoundingMode.TowardsPositiveInfinity: - srcB = context.FPCeiling(srcB, srcType.ToInstFPType()); - break; - - case RoundingMode.TowardsZero: - srcB = context.FPTruncate(srcB, srcType.ToInstFPType()); - break; - } + IntegerRound.Round => context.FPRound(srcB, srcType.ToInstFPType()), + IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()), + IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()), + IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()), + _ => srcB + }; } // We don't need to handle conversions between FP16 <-> FP32 // since we do FP16 operations as FP32 directly. // FP16 <-> FP64 conversions are invalid. - if (srcType == FPType.FP32 && dstType == FPType.FP64) + if (srcType == DstFmt.F32 && dstType == DstFmt.F64) { srcB = context.FP32ConvertToFP64(srcB); } - else if (srcType == FPType.FP64 && dstType == FPType.FP32) + else if (srcType == DstFmt.F64 && dstType == DstFmt.F32) { srcB = context.FP64ConvertToFP32(srcB); } - srcB = context.FPSaturate(srcB, op.Saturate, dstType.ToInstFPType()); + srcB = context.FPSaturate(srcB, saturate, dstType.ToInstFPType()); - WriteFP(context, dstType, srcB); + WriteFP(context, dstType, srcB, rd); // TODO: CC. } - public static void F2I(EmitterContext context) + private static void EmitF2I( + EmitterContext context, + DstFmt srcType, + IDstFmt dstType, + RoundMode2 roundingMode, + Operand src, + int rd, + bool absolute, + bool negate) { - OpCodeFArith op = (OpCodeFArith)context.CurrOp; - - IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2); - - if (intType == IntegerType.U64) + if (dstType == IDstFmt.U64) { context.Config.GpuAccessor.Log("Unimplemented 64-bits F2I."); - return; } - bool isSmallInt = intType <= IntegerType.U16; + bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64; + bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16; - FPType floatType = (FPType)op.RawOpCode.Extract(10, 2); + Operand srcB = context.FPAbsNeg(src, absolute, negate); - bool isSignedInt = op.RawOpCode.Extract(12); - bool negateB = op.RawOpCode.Extract(45); - bool absoluteB = op.RawOpCode.Extract(49); - - if (isSignedInt) + srcB = roundingMode switch { - intType |= IntegerType.S8; - } - - Operand srcB = context.FPAbsNeg(GetSrcB(context, floatType), absoluteB, negateB); - - switch (op.RoundingMode) - { - case RoundingMode.ToNearest: - srcB = context.FPRound(srcB); - break; - - case RoundingMode.TowardsNegativeInfinity: - srcB = context.FPFloor(srcB); - break; - - case RoundingMode.TowardsPositiveInfinity: - srcB = context.FPCeiling(srcB); - break; - - case RoundingMode.TowardsZero: - srcB = context.FPTruncate(srcB); - break; - } + RoundMode2.Round => context.FPRound(srcB), + RoundMode2.Floor => context.FPFloor(srcB), + RoundMode2.Ceil => context.FPCeiling(srcB), + RoundMode2.Trunc => context.FPTruncate(srcB), + _ => srcB + }; if (!isSignedInt) { - // Negative float to uint cast is undefined, so we clamp - // the value before conversion. + // Negative float to uint cast is undefined, so we clamp the value before conversion. srcB = context.FPMaximum(srcB, ConstF(0)); } - srcB = isSignedInt - ? context.FPConvertToS32(srcB) - : context.FPConvertToU32(srcB); + srcB = isSignedInt ? context.FPConvertToS32(srcB) : context.FPConvertToU32(srcB); if (isSmallInt) { - int min = (int)GetIntMin(intType); - int max = (int)GetIntMax(intType); + int min = (int)GetIntMin(dstType); + int max = (int)GetIntMax(dstType); srcB = isSignedInt ? context.IClampS32(srcB, Const(min), Const(max)) : context.IClampU32(srcB, Const(min), Const(max)); } - Operand dest = GetDest(context); + Operand dest = GetDest(rd); context.Copy(dest, srcB); // TODO: CC. } - public static void I2F(EmitterContext context) + private static void EmitI2F( + EmitterContext context, + ISrcFmt srcType, + DstFmt dstType, + Operand src, + ByteSel byteSelection, + int rd, + bool absolute, + bool negate) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - FPType dstType = (FPType)op.RawOpCode.Extract(8, 2); - - IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2); + bool isSignedInt = + srcType == ISrcFmt.S8 || + srcType == ISrcFmt.S16 || + srcType == ISrcFmt.S32 || + srcType == ISrcFmt.S64; + bool isSmallInt = + srcType == ISrcFmt.U16 || + srcType == ISrcFmt.S16 || + srcType == ISrcFmt.U8 || + srcType == ISrcFmt.S8; // TODO: Handle S/U64. - bool isSmallInt = srcType <= IntegerType.U16; - - bool isSignedInt = op.RawOpCode.Extract(13); - bool negateB = op.RawOpCode.Extract(45); - bool absoluteB = op.RawOpCode.Extract(49); - - Operand srcB = context.IAbsNeg(GetSrcB(context), absoluteB, negateB); + Operand srcB = context.IAbsNeg(src, absolute, negate); if (isSmallInt) { - int size = srcType == IntegerType.U16 ? 16 : 8; + int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; srcB = isSignedInt - ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size)) - : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size)); + ? context.BitfieldExtractS32(srcB, Const((int)byteSelection * 8), Const(size)) + : context.BitfieldExtractU32(srcB, Const((int)byteSelection * 8), Const(size)); } - srcB = isSignedInt - ? context.IConvertS32ToFP(srcB) - : context.IConvertU32ToFP(srcB); + srcB = isSignedInt ? context.IConvertS32ToFP(srcB) : context.IConvertU32ToFP(srcB); - WriteFP(context, dstType, srcB); + WriteFP(context, dstType, srcB, rd); // TODO: CC. } - public static void I2I(EmitterContext context) + private static void EmitI2I( + EmitterContext context, + ISrcFmt srcType, + IDstFmt dstType, + Operand src, + ByteSel byteSelection, + int rd, + bool absolute, + bool negate, + bool saturate) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - IntegerType dstType = (IntegerType)op.RawOpCode.Extract(8, 2); - IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2); - - if (srcType == IntegerType.U64 || dstType == IntegerType.U64) + if (srcType == ISrcFmt.U64 || dstType == IDstFmt.U64) { context.Config.GpuAccessor.Log("Invalid I2I encoding."); - return; } - bool srcIsSmallInt = srcType <= IntegerType.U16; - - bool dstIsSignedInt = op.RawOpCode.Extract(12); - bool srcIsSignedInt = op.RawOpCode.Extract(13); - bool negateB = op.RawOpCode.Extract(45); - bool absoluteB = op.RawOpCode.Extract(49); - - Operand srcB = GetSrcB(context); + bool srcIsSignedInt = + srcType == ISrcFmt.S8 || + srcType == ISrcFmt.S16 || + srcType == ISrcFmt.S32 || + srcType == ISrcFmt.S64; + bool dstIsSignedInt = + dstType == IDstFmt.S16 || + dstType == IDstFmt.S32 || + dstType == IDstFmt.S64; + bool srcIsSmallInt = + srcType == ISrcFmt.U16 || + srcType == ISrcFmt.S16 || + srcType == ISrcFmt.U8 || + srcType == ISrcFmt.S8; if (srcIsSmallInt) { - int size = srcType == IntegerType.U16 ? 16 : 8; + int size = srcType == ISrcFmt.U16 || srcType == ISrcFmt.S16 ? 16 : 8; - srcB = srcIsSignedInt - ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size)) - : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size)); + src = srcIsSignedInt + ? context.BitfieldExtractS32(src, Const((int)byteSelection * 8), Const(size)) + : context.BitfieldExtractU32(src, Const((int)byteSelection * 8), Const(size)); } - srcB = context.IAbsNeg(srcB, absoluteB, negateB); + src = context.IAbsNeg(src, absolute, negate); - if (op.Saturate) + if (saturate) { - if (dstIsSignedInt) - { - dstType |= IntegerType.S8; - } - int min = (int)GetIntMin(dstType); int max = (int)GetIntMax(dstType); - srcB = dstIsSignedInt - ? context.IClampS32(srcB, Const(min), Const(max)) - : context.IClampU32(srcB, Const(min), Const(max)); + src = dstIsSignedInt + ? context.IClampS32(src, Const(min), Const(max)) + : context.IClampU32(src, Const(min), Const(max)); } - context.Copy(GetDest(context), srcB); + context.Copy(GetDest(rd), src); // TODO: CC. } - private static void WriteFP(EmitterContext context, FPType type, Operand srcB) + private static Operand UnpackReg(EmitterContext context, DstFmt floatType, bool h, int reg) { - Operand dest = GetDest(context); + if (floatType == DstFmt.F32) + { + return GetSrcReg(context, reg); + } + else if (floatType == DstFmt.F16) + { + return GetHalfUnpacked(context, GetSrcReg(context, reg), HalfSwizzle.F16)[h ? 1 : 0]; + } + else if (floatType == DstFmt.F64) + { + return GetSrcReg(context, reg, isFP64: true); + } - if (type == FPType.FP32) + throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); + } + + private static Operand UnpackCbuf(EmitterContext context, DstFmt floatType, bool h, int cbufSlot, int cbufOffset) + { + if (floatType == DstFmt.F32) + { + return GetSrcCbuf(context, cbufSlot, cbufOffset); + } + else if (floatType == DstFmt.F16) + { + return GetHalfUnpacked(context, GetSrcCbuf(context, cbufSlot, cbufOffset), HalfSwizzle.F16)[h ? 1 : 0]; + } + else if (floatType == DstFmt.F64) + { + return GetSrcCbuf(context, cbufSlot, cbufOffset, isFP64: true); + } + + throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); + } + + private static Operand UnpackImm(EmitterContext context, DstFmt floatType, bool h, int imm) + { + if (floatType == DstFmt.F32) + { + return GetSrcImm(context, imm); + } + else if (floatType == DstFmt.F16) + { + return GetHalfUnpacked(context, GetSrcImm(context, imm), HalfSwizzle.F16)[h ? 1 : 0]; + } + else if (floatType == DstFmt.F64) + { + return GetSrcImm(context, imm, isFP64: true); + } + + throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); + } + + private static void WriteFP(EmitterContext context, DstFmt type, Operand srcB, int rd) + { + Operand dest = GetDest(rd); + + if (type == DstFmt.F32) { context.Copy(dest, srcB); } - else if (type == FPType.FP16) + else if (type == DstFmt.F16) { context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0))); } else /* if (type == FPType.FP64) */ { - Operand dest2 = GetDest2(context); + Operand dest2 = GetDest2(rd); context.Copy(dest, context.UnpackDouble2x32Low(srcB)); context.Copy(dest2, context.UnpackDouble2x32High(srcB)); } } + + private static Instruction ToInstFPType(this DstFmt type) + { + return type == DstFmt.F64 ? Instruction.FP64 : Instruction.FP32; + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs deleted file mode 100644 index 6dc4c093..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs +++ /dev/null @@ -1,547 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; -using System; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Dadd(EmitterContext context) => EmitFPAdd(context, Instruction.FP64); - public static void Dfma(EmitterContext context) => EmitFPFma(context, Instruction.FP64); - public static void Dmul(EmitterContext context) => EmitFPMultiply(context, Instruction.FP64); - - public static void Fadd(EmitterContext context) => EmitFPAdd(context, Instruction.FP32); - - public static void Fcmp(EmitterContext context) - { - OpCode op = context.CurrOp; - - Condition cmpOp = (Condition)op.RawOpCode.Extract(48, 4); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - Operand srcC = GetSrcC(context); - - Operand cmpRes = GetFPComparison(context, cmpOp, srcC, ConstF(0)); - - Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); - - context.Copy(GetDest(context), res); - } - - public static void Ffma(EmitterContext context) => EmitFPFma(context, Instruction.FP32); - - public static void Ffma32i(EmitterContext context) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool saturate = op.RawOpCode.Extract(55); - bool negateA = op.RawOpCode.Extract(56); - bool negateC = op.RawOpCode.Extract(57); - - Operand srcA = context.FPNegate(GetSrcA(context), negateA); - Operand srcC = context.FPNegate(GetDest(context), negateC); - - Operand srcB = GetSrcB(context); - - Operand dest = GetDest(context); - - context.Copy(dest, context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC), saturate)); - - SetFPZnFlags(context, dest, op.SetCondCode); - } - - public static void Fmnmx(EmitterContext context) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool absoluteA = op.AbsoluteA; - bool negateB = op.RawOpCode.Extract(45); - bool negateA = op.RawOpCode.Extract(48); - bool absoluteB = op.RawOpCode.Extract(49); - - Operand srcA = context.FPAbsNeg(GetSrcA(context), absoluteA, negateA); - Operand srcB = context.FPAbsNeg(GetSrcB(context), absoluteB, negateB); - - Operand resMin = context.FPMinimum(srcA, srcB); - Operand resMax = context.FPMaximum(srcA, srcB); - - Operand pred = GetPredicate39(context); - - Operand dest = GetDest(context); - - context.Copy(dest, context.ConditionalSelect(pred, resMin, resMax)); - - SetFPZnFlags(context, dest, op.SetCondCode); - } - - public static void Fmul(EmitterContext context) => EmitFPMultiply(context, Instruction.FP32); - - public static void Fset(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - Condition cmpOp = (Condition)op.RawOpCode.Extract(48, 4); - - bool negateA = op.RawOpCode.Extract(43); - bool absoluteB = op.RawOpCode.Extract(44); - bool boolFloat = op.RawOpCode.Extract(52); - bool negateB = op.RawOpCode.Extract(53); - bool absoluteA = op.RawOpCode.Extract(54); - - Operand srcA = context.FPAbsNeg(GetSrcA(context), absoluteA, negateA); - Operand srcB = context.FPAbsNeg(GetSrcB(context), absoluteB, negateB); - - Operand res = GetFPComparison(context, cmpOp, srcA, srcB); - - Operand pred = GetPredicate39(context); - - res = GetPredLogicalOp(context, op.LogicalOp, res, pred); - - Operand dest = GetDest(context); - - if (boolFloat) - { - res = context.ConditionalSelect(res, ConstF(1), Const(0)); - - context.Copy(dest, res); - - SetFPZnFlags(context, res, op.SetCondCode); - } - else - { - context.Copy(dest, res); - - SetZnFlags(context, res, op.SetCondCode, op.Extended); - } - - // TODO: X - } - - public static void Fsetp(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - Condition cmpOp = (Condition)op.RawOpCode.Extract(48, 4); - - bool negateB = op.RawOpCode.Extract(6); - bool absoluteA = op.RawOpCode.Extract(7); - bool negateA = op.RawOpCode.Extract(43); - bool absoluteB = op.RawOpCode.Extract(44); - - Operand srcA = context.FPAbsNeg(GetSrcA(context), absoluteA, negateA); - Operand srcB = context.FPAbsNeg(GetSrcB(context), absoluteB, negateB); - - Operand p0Res = GetFPComparison(context, cmpOp, srcA, srcB); - - Operand p1Res = context.BitwiseNot(p0Res); - - Operand pred = GetPredicate39(context); - - p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred); - - context.Copy(Register(op.Predicate3), p0Res); - context.Copy(Register(op.Predicate0), p1Res); - } - - public static void Fswzadd(EmitterContext context) - { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - int mask = op.RawOpCode.Extract(28, 8); - - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); - - Operand dest = GetDest(context); - - context.Copy(dest, context.FPSwizzleAdd(srcA, srcB, mask)); - - SetFPZnFlags(context, dest, op.SetCondCode); - } - - public static void Hadd2(EmitterContext context) - { - Hadd2Hmul2Impl(context, isAdd: true); - } - - public static void Hfma2(EmitterContext context) - { - IOpCodeHfma op = (IOpCodeHfma)context.CurrOp; - - Operand[] srcA = GetHfmaSrcA(context); - Operand[] srcB = GetHfmaSrcB(context); - Operand[] srcC = GetHfmaSrcC(context); - - Operand[] res = new Operand[2]; - - for (int index = 0; index < res.Length; index++) - { - res[index] = context.FPFusedMultiplyAdd(srcA[index], srcB[index], srcC[index]); - - res[index] = context.FPSaturate(res[index], op.Saturate); - } - - context.Copy(GetDest(context), GetHalfPacked(context, res)); - } - - public static void Hmul2(EmitterContext context) - { - Hadd2Hmul2Impl(context, isAdd: false); - } - - private static void Hadd2Hmul2Impl(EmitterContext context, bool isAdd) - { - OpCode op = context.CurrOp; - - bool saturate = op.RawOpCode.Extract(op is IOpCodeReg ? 32 : 52); - - Operand[] srcA = GetHalfSrcA(context, isAdd); - Operand[] srcB = GetHalfSrcB(context, !isAdd); - - Operand[] res = new Operand[2]; - - for (int index = 0; index < res.Length; index++) - { - if (isAdd) - { - res[index] = context.FPAdd(srcA[index], srcB[index]); - } - else - { - res[index] = context.FPMultiply(srcA[index], srcB[index]); - } - - res[index] = context.FPSaturate(res[index], saturate); - } - - context.Copy(GetDest(context), GetHalfPacked(context, res)); - } - - public static void Hset2(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - bool isRegVariant = op is IOpCodeReg; - - bool boolFloat = isRegVariant - ? op.RawOpCode.Extract(49) - : op.RawOpCode.Extract(53); - - Condition cmpOp = isRegVariant - ? (Condition)op.RawOpCode.Extract(35, 4) - : (Condition)op.RawOpCode.Extract(49, 4); - - Operand[] srcA = GetHalfSrcA(context); - Operand[] srcB = GetHalfSrcB(context); - - Operand[] res = new Operand[2]; - - res[0] = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); - res[1] = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); - - Operand pred = GetPredicate39(context); - - res[0] = GetPredLogicalOp(context, op.LogicalOp, res[0], pred); - res[1] = GetPredLogicalOp(context, op.LogicalOp, res[1], pred); - - if (boolFloat) - { - res[0] = context.ConditionalSelect(res[0], ConstF(1), Const(0)); - res[1] = context.ConditionalSelect(res[1], ConstF(1), Const(0)); - - context.Copy(GetDest(context), context.PackHalf2x16(res[0], res[1])); - } - else - { - Operand low = context.BitwiseAnd(res[0], Const(0xffff)); - Operand high = context.ShiftLeft (res[1], Const(16)); - - Operand packed = context.BitwiseOr(low, high); - - context.Copy(GetDest(context), packed); - } - } - - public static void Hsetp2(EmitterContext context) - { - OpCodeSet op = (OpCodeSet)context.CurrOp; - - bool isRegVariant = op is IOpCodeReg; - - bool hAnd = isRegVariant - ? op.RawOpCode.Extract(49) - : op.RawOpCode.Extract(53); - - Condition cmpOp = isRegVariant - ? (Condition)op.RawOpCode.Extract(35, 4) - : (Condition)op.RawOpCode.Extract(49, 4); - - Operand[] srcA = GetHalfSrcA(context); - Operand[] srcB = GetHalfSrcB(context); - - Operand p0Res = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); - Operand p1Res = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); - - if (hAnd) - { - p0Res = context.BitwiseAnd(p0Res, p1Res); - p1Res = context.BitwiseNot(p0Res); - } - - Operand pred = GetPredicate39(context); - - p0Res = GetPredLogicalOp(context, op.LogicalOp, p0Res, pred); - p1Res = GetPredLogicalOp(context, op.LogicalOp, p1Res, pred); - - context.Copy(Register(op.Predicate3), p0Res); - context.Copy(Register(op.Predicate0), p1Res); - } - - public static void Mufu(EmitterContext context) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool negateB = op.RawOpCode.Extract(48); - - Operand res = context.FPAbsNeg(GetSrcA(context), op.AbsoluteA, negateB); - - MufuOperation subOp = (MufuOperation)context.CurrOp.RawOpCode.Extract(20, 4); - - switch (subOp) - { - case MufuOperation.Cosine: - res = context.FPCosine(res); - break; - - case MufuOperation.Sine: - res = context.FPSine(res); - break; - - case MufuOperation.ExponentB2: - res = context.FPExponentB2(res); - break; - - case MufuOperation.LogarithmB2: - res = context.FPLogarithmB2(res); - break; - - case MufuOperation.Reciprocal: - res = context.FPReciprocal(res); - break; - - case MufuOperation.ReciprocalSquareRoot: - res = context.FPReciprocalSquareRoot(res); - break; - - case MufuOperation.SquareRoot: - res = context.FPSquareRoot(res); - break; - - default: /* TODO */ break; - } - - context.Copy(GetDest(context), context.FPSaturate(res, op.Saturate)); - } - - private static void EmitFPAdd(EmitterContext context, Instruction fpType) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool isFP64 = fpType == Instruction.FP64; - - bool absoluteA = op.AbsoluteA, absoluteB, negateA, negateB; - - if (op is OpCodeFArithImm32) - { - negateB = op.RawOpCode.Extract(53); - negateA = op.RawOpCode.Extract(56); - absoluteB = op.RawOpCode.Extract(57); - } - else - { - negateB = op.RawOpCode.Extract(45); - negateA = op.RawOpCode.Extract(48); - absoluteB = op.RawOpCode.Extract(49); - } - - Operand srcA = context.FPAbsNeg(GetSrcA(context, isFP64), absoluteA, negateA, fpType); - Operand srcB = context.FPAbsNeg(GetSrcB(context, isFP64), absoluteB, negateB, fpType); - - Operand res = context.FPSaturate(context.FPAdd(srcA, srcB, fpType), op.Saturate, fpType); - - SetDest(context, res, isFP64); - - SetFPZnFlags(context, res, op.SetCondCode, fpType); - } - - private static void EmitFPFma(EmitterContext context, Instruction fpType) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool isFP64 = fpType == Instruction.FP64; - - bool negateB = op.RawOpCode.Extract(48); - bool negateC = op.RawOpCode.Extract(49); - - Operand srcA = GetSrcA(context, isFP64); - - Operand srcB = context.FPNegate(GetSrcB(context, isFP64), negateB, fpType); - Operand srcC = context.FPNegate(GetSrcC(context, isFP64), negateC, fpType); - - Operand res = context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC, fpType), op.Saturate, fpType); - - SetDest(context, res, isFP64); - - SetFPZnFlags(context, res, op.SetCondCode, fpType); - } - - private static void EmitFPMultiply(EmitterContext context, Instruction fpType) - { - IOpCodeFArith op = (IOpCodeFArith)context.CurrOp; - - bool isFP64 = fpType == Instruction.FP64; - - bool isImm32 = op is OpCodeFArithImm32; - - bool negateB = !isImm32 && op.RawOpCode.Extract(48); - - Operand srcA = GetSrcA(context, isFP64); - - Operand srcB = context.FPNegate(GetSrcB(context, isFP64), negateB, fpType); - - if (op.Scale != FPMultiplyScale.None) - { - Operand scale = op.Scale switch - { - FPMultiplyScale.Divide2 => ConstF(0.5f), - FPMultiplyScale.Divide4 => ConstF(0.25f), - FPMultiplyScale.Divide8 => ConstF(0.125f), - FPMultiplyScale.Multiply2 => ConstF(2f), - FPMultiplyScale.Multiply4 => ConstF(4f), - FPMultiplyScale.Multiply8 => ConstF(8f), - _ => ConstF(1) // Invalid, behave as if it had no scale. - }; - - if (scale.AsFloat() == 1) - { - context.Config.GpuAccessor.Log($"Invalid FP multiply scale \"{op.Scale}\"."); - } - - if (isFP64) - { - scale = context.FP32ConvertToFP64(scale); - } - - srcA = context.FPMultiply(srcA, scale, fpType); - } - - bool saturate = isImm32 ? op.RawOpCode.Extract(55) : op.Saturate; - - Operand res = context.FPSaturate(context.FPMultiply(srcA, srcB, fpType), saturate, fpType); - - SetDest(context, res, isFP64); - - SetFPZnFlags(context, res, op.SetCondCode, fpType); - } - - private static Operand GetFPComparison( - EmitterContext context, - Condition cond, - Operand srcA, - Operand srcB) - { - Operand res; - - if (cond == Condition.Always) - { - res = Const(IrConsts.True); - } - else if (cond == Condition.Never) - { - res = Const(IrConsts.False); - } - else if (cond == Condition.Nan || cond == Condition.Number) - { - res = context.BitwiseOr(context.IsNan(srcA), context.IsNan(srcB)); - - if (cond == Condition.Number) - { - res = context.BitwiseNot(res); - } - } - else - { - Instruction inst; - - switch (cond & ~Condition.Nan) - { - case Condition.Less: inst = Instruction.CompareLess; break; - case Condition.Equal: inst = Instruction.CompareEqual; break; - case Condition.LessOrEqual: inst = Instruction.CompareLessOrEqual; break; - case Condition.Greater: inst = Instruction.CompareGreater; break; - case Condition.NotEqual: inst = Instruction.CompareNotEqual; break; - case Condition.GreaterOrEqual: inst = Instruction.CompareGreaterOrEqual; break; - - default: throw new InvalidOperationException($"Unexpected condition \"{cond}\"."); - } - - res = context.Add(inst | Instruction.FP32, Local(), srcA, srcB); - - if ((cond & Condition.Nan) != 0) - { - res = context.BitwiseOr(res, context.IsNan(srcA)); - res = context.BitwiseOr(res, context.IsNan(srcB)); - } - } - - return res; - } - - private static Operand[] GetHfmaSrcA(EmitterContext context) - { - IOpCodeHfma op = (IOpCodeHfma)context.CurrOp; - - return GetHalfUnpacked(context, GetSrcA(context), op.SwizzleA); - } - - private static Operand[] GetHfmaSrcB(EmitterContext context) - { - IOpCodeHfma op = (IOpCodeHfma)context.CurrOp; - - Operand[] operands = GetHalfUnpacked(context, GetSrcB(context), op.SwizzleB); - - return FPAbsNeg(context, operands, false, op.NegateB); - } - - private static Operand[] GetHfmaSrcC(EmitterContext context) - { - IOpCodeHfma op = (IOpCodeHfma)context.CurrOp; - - Operand[] operands = GetHalfUnpacked(context, GetSrcC(context), op.SwizzleC); - - return FPAbsNeg(context, operands, false, op.NegateC); - } - - private static void SetDest(EmitterContext context, Operand value, bool isFP64) - { - if (isFP64) - { - IOpCodeRd op = (IOpCodeRd)context.CurrOp; - - context.Copy(Register(op.Rd.Index, op.Rd.Type), context.UnpackDouble2x32Low(value)); - context.Copy(Register(op.Rd.Index | 1, op.Rd.Type), context.UnpackDouble2x32High(value)); - } - else - { - context.Copy(GetDest(context), value); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs new file mode 100644 index 00000000..2318f2b7 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatArithmetic.cs @@ -0,0 +1,545 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void DaddR(EmitterContext context) + { + InstDaddR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcReg(context, op.SrcB, isFP64: true); + + EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); + } + + public static void DaddI(EmitterContext context) + { + InstDaddI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); + + EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); + } + + public static void DaddC(EmitterContext context) + { + InstDaddC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); + + EmitFadd(context, Instruction.FP64, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); + } + + public static void DfmaR(EmitterContext context) + { + InstDfmaR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcReg(context, op.SrcB, isFP64: true); + var srcC = GetSrcReg(context, op.SrcC, isFP64: true); + + EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); + } + + public static void DfmaI(EmitterContext context) + { + InstDfmaI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); + var srcC = GetSrcReg(context, op.SrcC, isFP64: true); + + EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); + } + + public static void DfmaC(EmitterContext context) + { + InstDfmaC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); + var srcC = GetSrcReg(context, op.SrcC, isFP64: true); + + EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); + } + + public static void DfmaRc(EmitterContext context) + { + InstDfmaRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcReg(context, op.SrcC, isFP64: true); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); + + EmitFfma(context, Instruction.FP64, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, false, op.WriteCC); + } + + public static void DmulR(EmitterContext context) + { + InstDmulR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcReg(context, op.SrcB, isFP64: true); + + EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); + } + + public static void DmulI(EmitterContext context) + { + InstDmulI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20), isFP64: true); + + EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); + } + + public static void DmulC(EmitterContext context) + { + InstDmulC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA, isFP64: true); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset, isFP64: true); + + EmitFmul(context, Instruction.FP64, MultiplyScale.NoScale, srcA, srcB, op.Dest, op.NegA, false, op.WriteCC); + } + + public static void FaddR(EmitterContext context) + { + InstFaddR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); + } + + public static void FaddI(EmitterContext context) + { + InstFaddI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + + EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); + } + + public static void FaddC(EmitterContext context) + { + InstFaddC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, op.Sat, op.WriteCC); + } + + public static void Fadd32i(EmitterContext context) + { + InstFadd32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + + EmitFadd(context, Instruction.FP32, srcA, srcB, op.Dest, op.NegA, op.NegB, op.AbsA, op.AbsB, false, op.WriteCC); + } + + public static void FfmaR(EmitterContext context) + { + InstFfmaR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); + } + + public static void FfmaI(EmitterContext context) + { + InstFfmaI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); + } + + public static void FfmaC(EmitterContext context) + { + InstFfmaC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); + } + + public static void FfmaRc(EmitterContext context) + { + InstFfmaRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); + } + + public static void Ffma32i(EmitterContext context) + { + InstFfma32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFfma(context, Instruction.FP32, srcA, srcB, srcC, op.Dest, op.NegA, op.NegC, op.Sat, op.WriteCC); + } + + public static void FmulR(EmitterContext context) + { + InstFmulR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); + } + + public static void FmulI(EmitterContext context) + { + InstFmulI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + + EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); + } + + public static void FmulC(EmitterContext context) + { + InstFmulC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFmul(context, Instruction.FP32, op.Scale, srcA, srcB, op.Dest, op.NegA, op.Sat, op.WriteCC); + } + + public static void Fmul32i(EmitterContext context) + { + InstFmul32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + + EmitFmul(context, Instruction.FP32, MultiplyScale.NoScale, srcA, srcB, op.Dest, false, op.Sat, op.WriteCC); + } + + public static void Hadd2R(EmitterContext context) + { + InstHadd2R op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); + } + + public static void Hadd2I(EmitterContext context) + { + InstHadd2I op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); + } + + public static void Hadd2C(EmitterContext context) + { + InstHadd2C op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, op.AbsB); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: true, op.Dest, op.Sat); + } + + public static void Hadd232i(EmitterContext context) + { + InstHadd232i op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, false); + var srcB = GetHalfSrc(context, op.Imm); + + EmitHadd2Hmul2(context, OFmt.F16, srcA, srcB, isAdd: true, op.Dest, op.Sat); + } + + public static void Hfma2R(EmitterContext context) + { + InstHfma2R op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegA, false); + var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); + + EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); + } + + public static void Hfma2I(EmitterContext context) + { + InstHfma2I op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); + var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); + + EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); + } + + public static void Hfma2C(EmitterContext context) + { + InstHfma2C op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegA, false); + var srcC = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegC, false); + + EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); + } + + public static void Hfma2Rc(EmitterContext context) + { + InstHfma2Rc op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, op.CSwizzle, op.SrcC, op.NegA, false); + var srcC = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegC, false); + + EmitHfma2(context, op.OFmt, srcA, srcB, srcC, op.Dest, op.Sat); + } + + public static void Hfma232iI(EmitterContext context) + { + InstHfma232i op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, op.Imm); + var srcC = GetHalfSrc(context, HalfSwizzle.F16, op.SrcC, op.NegC, false); + + EmitHfma2(context, OFmt.F16, srcA, srcB, srcC, op.Dest, saturate: false); + } + + public static void Hmul2R(EmitterContext context) + { + InstHmul2R op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, op.AbsA); + var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegA, op.AbsB); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); + } + + public static void Hmul2I(EmitterContext context) + { + InstHmul2I op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); + } + + public static void Hmul2C(EmitterContext context) + { + InstHmul2C op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, op.AbsA); + var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegA, op.AbsB); + + EmitHadd2Hmul2(context, op.OFmt, srcA, srcB, isAdd: false, op.Dest, op.Sat); + } + + public static void Hmul232i(EmitterContext context) + { + InstHmul232i op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, false, false); + var srcB = GetHalfSrc(context, op.Imm32); + + EmitHadd2Hmul2(context, OFmt.F16, srcA, srcB, isAdd: false, op.Dest, op.Sat); + } + + private static void EmitFadd( + EmitterContext context, + Instruction fpType, + Operand srcA, + Operand srcB, + int rd, + bool negateA, + bool negateB, + bool absoluteA, + bool absoluteB, + bool saturate, + bool writeCC) + { + bool isFP64 = fpType == Instruction.FP64; + + srcA = context.FPAbsNeg(srcA, absoluteA, negateA, fpType); + srcB = context.FPAbsNeg(srcB, absoluteB, negateB, fpType); + + Operand res = context.FPSaturate(context.FPAdd(srcA, srcB, fpType), saturate, fpType); + + SetDest(context, res, rd, isFP64); + + SetFPZnFlags(context, res, writeCC, fpType); + } + + private static void EmitFfma( + EmitterContext context, + Instruction fpType, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + bool negateB, + bool negateC, + bool saturate, + bool writeCC) + { + bool isFP64 = fpType == Instruction.FP64; + + srcB = context.FPNegate(srcB, negateB, fpType); + srcC = context.FPNegate(srcC, negateC, fpType); + + Operand res = context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC, fpType), saturate, fpType); + + SetDest(context, res, rd, isFP64); + + SetFPZnFlags(context, res, writeCC, fpType); + } + + private static void EmitFmul( + EmitterContext context, + Instruction fpType, + MultiplyScale scale, + Operand srcA, + Operand srcB, + int rd, + bool negateB, + bool saturate, + bool writeCC) + { + bool isFP64 = fpType == Instruction.FP64; + + srcB = context.FPNegate(srcB, negateB, fpType); + + if (scale != MultiplyScale.NoScale) + { + Operand scaleConst = scale switch + { + MultiplyScale.D2 => ConstF(0.5f), + MultiplyScale.D4 => ConstF(0.25f), + MultiplyScale.D8 => ConstF(0.125f), + MultiplyScale.M2 => ConstF(2f), + MultiplyScale.M4 => ConstF(4f), + MultiplyScale.M8 => ConstF(8f), + _ => ConstF(1f) // Invalid, behave as if it had no scale. + }; + + if (scaleConst.AsFloat() == 1f) + { + context.Config.GpuAccessor.Log($"Invalid FP multiply scale \"{scale}\"."); + } + + if (isFP64) + { + scaleConst = context.FP32ConvertToFP64(scaleConst); + } + + srcA = context.FPMultiply(srcA, scaleConst, fpType); + } + + Operand res = context.FPSaturate(context.FPMultiply(srcA, srcB, fpType), saturate, fpType); + + SetDest(context, res, rd, isFP64); + + SetFPZnFlags(context, res, writeCC, fpType); + } + + private static void EmitHadd2Hmul2( + EmitterContext context, + OFmt swizzle, + Operand[] srcA, + Operand[] srcB, + bool isAdd, + int rd, + bool saturate) + { + Operand[] res = new Operand[2]; + + for (int index = 0; index < res.Length; index++) + { + if (isAdd) + { + res[index] = context.FPAdd(srcA[index], srcB[index]); + } + else + { + res[index] = context.FPMultiply(srcA[index], srcB[index]); + } + + res[index] = context.FPSaturate(res[index], saturate); + } + + context.Copy(GetDest(rd), GetHalfPacked(context, swizzle, res, rd)); + } + + public static void EmitHfma2( + EmitterContext context, + OFmt swizzle, + Operand[] srcA, + Operand[] srcB, + Operand[] srcC, + int rd, + bool saturate) + { + Operand[] res = new Operand[2]; + + for (int index = 0; index < res.Length; index++) + { + res[index] = context.FPFusedMultiplyAdd(srcA[index], srcB[index], srcC[index]); + res[index] = context.FPSaturate(res[index], saturate); + } + + context.Copy(GetDest(rd), GetHalfPacked(context, swizzle, res, rd)); + } + + private static void SetDest(EmitterContext context, Operand value, int rd, bool isFP64) + { + if (isFP64) + { + context.Copy(GetDest(rd), context.UnpackDouble2x32Low(value)); + context.Copy(GetDest2(rd), context.UnpackDouble2x32High(value)); + } + else + { + context.Copy(GetDest(rd), value); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs new file mode 100644 index 00000000..b7b5f9ba --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatComparison.cs @@ -0,0 +1,419 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; +using System; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void FcmpR(EmitterContext context) + { + InstFcmpR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); + } + + public static void FcmpI(EmitterContext context) + { + InstFcmpI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); + } + + public static void FcmpC(EmitterContext context) + { + InstFcmpC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); + } + + public static void FcmpRc(EmitterContext context) + { + InstFcmpRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFcmp(context, op.FComp, srcA, srcB, srcC, op.Dest); + } + + public static void FsetR(EmitterContext context) + { + InstFsetR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); + } + + public static void FsetC(EmitterContext context) + { + InstFsetC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); + } + + public static void FsetI(EmitterContext context) + { + InstFsetI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + + EmitFset(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.BVal, op.WriteCC); + } + + public static void FsetpR(EmitterContext context) + { + InstFsetpR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitFsetp( + context, + op.FComp, + op.Bop, + srcA, + srcB, + op.SrcPred, + op.SrcPredInv, + op.DestPred, + op.DestPredInv, + op.AbsA, + op.AbsB, + op.NegA, + op.NegB, + op.WriteCC); + } + + public static void FsetpI(EmitterContext context) + { + InstFsetpI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + + EmitFsetp( + context, + op.FComp, + op.Bop, + srcA, + srcB, + op.SrcPred, + op.SrcPredInv, + op.DestPred, + op.DestPredInv, + op.AbsA, + op.AbsB, + op.NegA, + op.NegB, + op.WriteCC); + } + + public static void FsetpC(EmitterContext context) + { + InstFsetpC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitFsetp( + context, + op.FComp, + op.Bop, + srcA, + srcB, + op.SrcPred, + op.SrcPredInv, + op.DestPred, + op.DestPredInv, + op.AbsA, + op.AbsB, + op.NegA, + op.NegB, + op.WriteCC); + } + + public static void Hset2R(EmitterContext context) + { + InstHset2R op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); + + EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); + } + + public static void Hset2I(EmitterContext context) + { + InstHset2I op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); + + EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); + } + + public static void Hset2C(EmitterContext context) + { + InstHset2C op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, false); + + EmitHset2(context, op.Cmp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.Bval); + } + + public static void Hsetp2R(EmitterContext context) + { + InstHsetp2R op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BSwizzle, op.SrcB, op.NegB, op.AbsB); + + EmitHsetp2(context, op.FComp2, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); + } + + public static void Hsetp2I(EmitterContext context) + { + InstHsetp2I op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, op.BimmH0, op.BimmH1); + + EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); + } + + public static void Hsetp2C(EmitterContext context) + { + InstHsetp2C op = context.GetOp(); + + var srcA = GetHalfSrc(context, op.ASwizzle, op.SrcA, op.NegA, op.AbsA); + var srcB = GetHalfSrc(context, HalfSwizzle.F32, op.CbufSlot, op.CbufOffset, op.NegB, op.AbsB); + + EmitHsetp2(context, op.FComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.HAnd); + } + + private static void EmitFcmp(EmitterContext context, FComp cmpOp, Operand srcA, Operand srcB, Operand srcC, int rd) + { + Operand cmpRes = GetFPComparison(context, cmpOp, srcC, ConstF(0)); + + Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); + + context.Copy(GetDest(rd), res); + } + + private static void EmitFset( + EmitterContext context, + FComp cmpOp, + BoolOp logicOp, + Operand srcA, + Operand srcB, + int srcPred, + bool srcPredInv, + int rd, + bool absoluteA, + bool absoluteB, + bool negateA, + bool negateB, + bool boolFloat, + bool writeCC) + { + srcA = context.FPAbsNeg(srcA, absoluteA, negateA); + srcB = context.FPAbsNeg(srcB, absoluteB, negateB); + + Operand res = GetFPComparison(context, cmpOp, srcA, srcB); + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + res = GetPredLogicalOp(context, logicOp, res, pred); + + Operand dest = GetDest(rd); + + if (boolFloat) + { + res = context.ConditionalSelect(res, ConstF(1), Const(0)); + + context.Copy(dest, res); + + SetFPZnFlags(context, res, writeCC); + } + else + { + context.Copy(dest, res); + + SetZnFlags(context, res, writeCC, extended: false); + } + } + + private static void EmitFsetp( + EmitterContext context, + FComp cmpOp, + BoolOp logicOp, + Operand srcA, + Operand srcB, + int srcPred, + bool srcPredInv, + int destPred, + int destPredInv, + bool absoluteA, + bool absoluteB, + bool negateA, + bool negateB, + bool writeCC) + { + srcA = context.FPAbsNeg(srcA, absoluteA, negateA); + srcB = context.FPAbsNeg(srcB, absoluteB, negateB); + + Operand p0Res = GetFPComparison(context, cmpOp, srcA, srcB); + Operand p1Res = context.BitwiseNot(p0Res); + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); + p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); + + context.Copy(Register(destPred, RegisterType.Predicate), p0Res); + context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); + } + + private static void EmitHset2( + EmitterContext context, + FComp cmpOp, + BoolOp logicOp, + Operand[] srcA, + Operand[] srcB, + int srcPred, + bool srcPredInv, + int rd, + bool boolFloat) + { + Operand[] res = new Operand[2]; + + res[0] = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); + res[1] = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); + + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + res[0] = GetPredLogicalOp(context, logicOp, res[0], pred); + res[1] = GetPredLogicalOp(context, logicOp, res[1], pred); + + if (boolFloat) + { + res[0] = context.ConditionalSelect(res[0], ConstF(1), Const(0)); + res[1] = context.ConditionalSelect(res[1], ConstF(1), Const(0)); + + context.Copy(GetDest(rd), context.PackHalf2x16(res[0], res[1])); + } + else + { + Operand low = context.BitwiseAnd(res[0], Const(0xffff)); + Operand high = context.ShiftLeft (res[1], Const(16)); + + Operand packed = context.BitwiseOr(low, high); + + context.Copy(GetDest(rd), packed); + } + } + + private static void EmitHsetp2( + EmitterContext context, + FComp cmpOp, + BoolOp logicOp, + Operand[] srcA, + Operand[] srcB, + int srcPred, + bool srcPredInv, + int destPred, + int destPredInv, + bool hAnd) + { + Operand p0Res = GetFPComparison(context, cmpOp, srcA[0], srcB[0]); + Operand p1Res = GetFPComparison(context, cmpOp, srcA[1], srcB[1]); + + if (hAnd) + { + p0Res = context.BitwiseAnd(p0Res, p1Res); + p1Res = context.BitwiseNot(p0Res); + } + + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); + p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); + + context.Copy(Register(destPred, RegisterType.Predicate), p0Res); + context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); + } + + private static Operand GetFPComparison(EmitterContext context, FComp cond, Operand srcA, Operand srcB) + { + Operand res; + + if (cond == FComp.T) + { + res = Const(IrConsts.True); + } + else if (cond == FComp.F) + { + res = Const(IrConsts.False); + } + else if (cond == FComp.Nan || cond == FComp.Num) + { + res = context.BitwiseOr(context.IsNan(srcA), context.IsNan(srcB)); + + if (cond == FComp.Num) + { + res = context.BitwiseNot(res); + } + } + else + { + Instruction inst; + + switch (cond & ~FComp.Nan) + { + case FComp.Lt: inst = Instruction.CompareLess; break; + case FComp.Eq: inst = Instruction.CompareEqual; break; + case FComp.Le: inst = Instruction.CompareLessOrEqual; break; + case FComp.Gt: inst = Instruction.CompareGreater; break; + case FComp.Ne: inst = Instruction.CompareNotEqual; break; + case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; + + default: throw new ArgumentException($"Unexpected condition \"{cond}\"."); + } + + res = context.Add(inst | Instruction.FP32, Local(), srcA, srcB); + + if ((cond & FComp.Nan) != 0) + { + res = context.BitwiseOr(res, context.IsNan(srcA)); + res = context.BitwiseOr(res, context.IsNan(srcB)); + } + } + + return res; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs new file mode 100644 index 00000000..3e91fc8a --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFloatMinMax.cs @@ -0,0 +1,70 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void FmnmxR(EmitterContext context) + { + InstFmnmxR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); + } + + public static void FmnmxI(EmitterContext context) + { + InstFmnmxI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToFloat(op.Imm20)); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); + } + + public static void FmnmxC(EmitterContext context) + { + InstFmnmxC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitFmnmx(context, srcA, srcB, srcPred, op.Dest, op.AbsA, op.AbsB, op.NegA, op.NegB, op.WriteCC); + } + + private static void EmitFmnmx( + EmitterContext context, + Operand srcA, + Operand srcB, + Operand srcPred, + int rd, + bool absoluteA, + bool absoluteB, + bool negateA, + bool negateB, + bool writeCC) + { + srcA = context.FPAbsNeg(srcA, absoluteA, negateA); + srcB = context.FPAbsNeg(srcB, absoluteB, negateB); + + Operand resMin = context.FPMinimum(srcA, srcB); + Operand resMax = context.FPMaximum(srcA, srcB); + + Operand dest = GetDest(rd); + + context.Copy(dest, context.ConditionalSelect(srcPred, resMin, resMax)); + + SetFPZnFlags(context, dest, writeCC); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs similarity index 63% rename from Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs rename to Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs index 1f5bf35b..fce951ba 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlowControl.cs @@ -13,32 +13,38 @@ namespace Ryujinx.Graphics.Shader.Instructions { public static void Bra(EmitterContext context) { - EmitBranch(context, context.CurrBlock.Branch.Address); + InstBra op = context.GetOp(); + + EmitBranch(context, context.CurrBlock.Successors[^1].Address); } public static void Brk(EmitterContext context) { + InstBrk op = context.GetOp(); + EmitBrkOrSync(context); } public static void Brx(EmitterContext context) { - OpCodeBranchIndir op = (OpCodeBranchIndir)context.CurrOp; + InstBrx op = context.GetOp(); + InstOp currOp = context.CurrOp; + int startIndex = context.CurrBlock.HasNext() ? 1 : 0; - if (op.PossibleTargets.Count == 0) + if (context.CurrBlock.Successors.Count <= startIndex) { - context.Config.GpuAccessor.Log($"Failed to find targets for BRX instruction at 0x{op.Address:X}."); + context.Config.GpuAccessor.Log($"Failed to find targets for BRX instruction at 0x{currOp.Address:X}."); return; } - int offset = (int)op.Address + 8 + op.Offset; + int offset = (int)currOp.GetAbsoluteAddress(); - Operand address = context.IAdd(Register(op.Ra), Const(offset)); + Operand address = context.IAdd(Register(op.SrcA, RegisterType.Gpr), Const(offset)); // Sorting the target addresses in descending order improves the code, // since it will always check the most distant targets first, then the // near ones. This can be easily transformed into if/else statements. - IOrderedEnumerable sortedTargets = op.PossibleTargets.OrderByDescending(x => x.Address); + var sortedTargets = context.CurrBlock.Successors.Skip(startIndex).OrderByDescending(x => x.Address); Block lastTarget = sortedTargets.LastOrDefault(); @@ -59,28 +65,24 @@ namespace Ryujinx.Graphics.Shader.Instructions public static void Cal(EmitterContext context) { - OpCodeBranch op = (OpCodeBranch)context.CurrOp; + InstCal op = context.GetOp(); - context.Call(context.GetFunctionId(op.GetAbsoluteAddress()), false); - } - - public static void Depbar(EmitterContext context) - { + context.Call(context.GetFunctionId(context.CurrOp.GetAbsoluteAddress()), false); } public static void Exit(EmitterContext context) { + InstExit op = context.GetOp(); + if (context.IsNonMain) { context.Config.GpuAccessor.Log("Invalid exit on non-main function."); return; } - OpCodeExit op = (OpCodeExit)context.CurrOp; - // TODO: Figure out how this is supposed to work in the // presence of other condition codes. - if (op.Condition == Condition.Always) + if (op.Ccc == Ccc.T) { context.Return(); } @@ -88,20 +90,22 @@ namespace Ryujinx.Graphics.Shader.Instructions public static void Kil(EmitterContext context) { - context.Discard(); - } + InstKil op = context.GetOp(); - public static void Nop(EmitterContext context) - { + context.Discard(); } public static void Pbk(EmitterContext context) { + InstPbk op = context.GetOp(); + EmitPbkOrSsy(context); } public static void Ret(EmitterContext context) { + InstRet op = context.GetOp(); + if (context.IsNonMain) { context.Return(); @@ -114,63 +118,62 @@ namespace Ryujinx.Graphics.Shader.Instructions public static void Ssy(EmitterContext context) { + InstSsy op = context.GetOp(); + EmitPbkOrSsy(context); } public static void Sync(EmitterContext context) { + InstSync op = context.GetOp(); + EmitBrkOrSync(context); } private static void EmitPbkOrSsy(EmitterContext context) { - OpCodePush op = (OpCodePush)context.CurrOp; + var consumers = context.CurrBlock.PushOpCodes.First(x => x.Op.Address == context.CurrOp.Address).Consumers; - foreach (KeyValuePair kv in op.PopOps) + foreach (KeyValuePair kv in consumers) { - OpCodeBranchPop opSync = kv.Key; - + Block consumerBlock = kv.Key; Operand local = kv.Value; - int pushOpIndex = opSync.Targets[op]; + int id = consumerBlock.SyncTargets[context.CurrOp.Address].PushOpId; - context.Copy(local, Const(pushOpIndex)); + context.Copy(local, Const(id)); } } private static void EmitBrkOrSync(EmitterContext context) { - OpCodeBranchPop op = (OpCodeBranchPop)context.CurrOp; + var targets = context.CurrBlock.SyncTargets; - if (op.Targets.Count == 1) + if (targets.Count == 1) { // If we have only one target, then the SSY/PBK is basically // a branch, we can produce better codegen for this case. - OpCodePush pushOp = op.Targets.Keys.First(); - - EmitBranch(context, pushOp.GetAbsoluteAddress()); + EmitBranch(context, targets.Values.First().PushOpInfo.Op.GetAbsoluteAddress()); } else { // TODO: Support CC here aswell (condition). - foreach (KeyValuePair kv in op.Targets) + foreach (SyncTarget target in targets.Values) { - OpCodePush pushOp = kv.Key; + PushOpInfo pushOpInfo = target.PushOpInfo; - Operand label = context.GetLabel(pushOp.GetAbsoluteAddress()); + Operand label = context.GetLabel(pushOpInfo.Op.GetAbsoluteAddress()); + Operand local = pushOpInfo.Consumers[context.CurrBlock]; - Operand local = pushOp.PopOps[op]; - - int pushOpIndex = kv.Value; - - context.BranchIfTrue(label, context.ICompareEqual(local, Const(pushOpIndex))); + context.BranchIfTrue(label, context.ICompareEqual(local, Const(target.PushOpId))); } } } private static void EmitBranch(EmitterContext context, ulong address) { - OpCode op = context.CurrOp; + InstOp op = context.CurrOp; + InstConditional opCond = new InstConditional(op.RawOpCode); // If we're branching to the next instruction, then the branch // is useless and we can ignore it. @@ -181,17 +184,17 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand label = context.GetLabel(address); - Operand pred = Register(op.Predicate); + Operand pred = Register(opCond.Pred, RegisterType.Predicate); - if (op is OpCodeConditional opCond && opCond.Condition != Condition.Always) + if (opCond.Ccc != Ccc.T) { - Operand cond = GetCondition(context, opCond.Condition); + Operand cond = GetCondition(context, opCond.Ccc); - if (op.Predicate.IsPT) + if (opCond.Pred == RegisterConsts.PredicateTrueIndex) { pred = cond; } - else if (op.InvertPredicate) + else if (opCond.PredInv) { pred = context.BitwiseAnd(context.BitwiseNot(pred), cond); } @@ -202,11 +205,11 @@ namespace Ryujinx.Graphics.Shader.Instructions context.BranchIfTrue(label, pred); } - else if (op.Predicate.IsPT) + else if (opCond.Pred == RegisterConsts.PredicateTrueIndex) { context.Branch(label); } - else if (op.InvertPredicate) + else if (opCond.PredInv) { context.BranchIfFalse(label, pred); } @@ -216,16 +219,16 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - private static Operand GetCondition(EmitterContext context, Condition cond) + private static Operand GetCondition(EmitterContext context, Ccc cond) { // TODO: More condition codes, figure out how they work. switch (cond) { - case Condition.Equal: - case Condition.EqualUnordered: + case Ccc.Eq: + case Ccc.Equ: return GetZF(); - case Condition.NotEqual: - case Condition.NotEqualUnordered: + case Ccc.Ne: + case Ccc.Neu: return context.BitwiseNot(GetZF()); } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs index 5a351c73..9f5bbdf7 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs @@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; using System; +using System.Runtime.CompilerServices; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -29,184 +30,101 @@ namespace Ryujinx.Graphics.Shader.Instructions return Register(3, RegisterType.Flag); } - public static Operand GetDest(EmitterContext context) + public static Operand GetDest(int rd) { - return Register(((IOpCodeRd)context.CurrOp).Rd); + return Register(rd, RegisterType.Gpr); } - public static Operand GetDest2(EmitterContext context) + public static Operand GetDest2(int rd) { - Register rd = ((IOpCodeRd)context.CurrOp).Rd; - - return Register(rd.Index | 1, rd.Type); + return Register(rd | 1, RegisterType.Gpr); } - public static Operand GetSrcA(EmitterContext context, bool isFP64 = false) - { - IOpCodeRa op = (IOpCodeRa)context.CurrOp; - - if (isFP64) - { - return context.PackDouble2x32(Register(op.Ra.Index, op.Ra.Type), Register(op.Ra.Index | 1, op.Ra.Type)); - } - else - { - return Register(op.Ra); - } - } - - public static Operand GetSrcB(EmitterContext context, FPType floatType) - { - if (floatType == FPType.FP32) - { - return GetSrcB(context); - } - else if (floatType == FPType.FP16) - { - int h = context.CurrOp.RawOpCode.Extract(41, 1); - - return GetHalfUnpacked(context, GetSrcB(context), FPHalfSwizzle.FP16)[h]; - } - else if (floatType == FPType.FP64) - { - return GetSrcB(context, true); - } - - throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); - } - - public static Operand GetSrcB(EmitterContext context, bool isFP64 = false) + public static Operand GetSrcCbuf(EmitterContext context, int cbufSlot, int cbufOffset, bool isFP64 = false) { if (isFP64) { - switch (context.CurrOp) - { - case IOpCodeCbuf op: - return context.PackDouble2x32( - context.Config.CreateCbuf(op.Slot, op.Offset), - context.Config.CreateCbuf(op.Slot, op.Offset + 1)); - - case IOpCodeImmF op: - return context.FP32ConvertToFP64(ConstF(op.Immediate)); - - case IOpCodeReg op: - return context.PackDouble2x32(Register(op.Rb.Index, op.Rb.Type), Register(op.Rb.Index | 1, op.Rb.Type)); - - case IOpCodeRegCbuf op: - return context.PackDouble2x32(Register(op.Rc.Index, op.Rc.Type), Register(op.Rc.Index | 1, op.Rc.Type)); - } + return context.PackDouble2x32( + context.Config.CreateCbuf(cbufSlot, cbufOffset), + context.Config.CreateCbuf(cbufSlot, cbufOffset + 1)); } else { - switch (context.CurrOp) - { - case IOpCodeCbuf op: - return context.Config.CreateCbuf(op.Slot, op.Offset); - - case IOpCodeImm op: - return Const(op.Immediate); - - case IOpCodeImmF op: - return ConstF(op.Immediate); - - case IOpCodeReg op: - return Register(op.Rb); - - case IOpCodeRegCbuf op: - return Register(op.Rc); - } + return context.Config.CreateCbuf(cbufSlot, cbufOffset); } - - throw new InvalidOperationException($"Unexpected opcode type \"{context.CurrOp.GetType().Name}\"."); } - public static Operand GetSrcC(EmitterContext context, bool isFP64 = false) + public static Operand GetSrcImm(EmitterContext context, int imm, bool isFP64 = false) { if (isFP64) { - switch (context.CurrOp) - { - case IOpCodeRegCbuf op: - return context.PackDouble2x32( - context.Config.CreateCbuf(op.Slot, op.Offset), - context.Config.CreateCbuf(op.Slot, op.Offset + 1)); - - case IOpCodeRc op: - return context.PackDouble2x32(Register(op.Rc.Index, op.Rc.Type), Register(op.Rc.Index | 1, op.Rc.Type)); - } + return context.FP32ConvertToFP64(Const(imm)); } else { - switch (context.CurrOp) - { - case IOpCodeRegCbuf op: - return context.Config.CreateCbuf(op.Slot, op.Offset); - - case IOpCodeRc op: - return Register(op.Rc); - } + return Const(imm); } - - throw new InvalidOperationException($"Unexpected opcode type \"{context.CurrOp.GetType().Name}\"."); } - public static Operand[] GetHalfSrcA(EmitterContext context, bool isAdd = false) + public static Operand GetSrcReg(EmitterContext context, int reg, bool isFP64 = false) { - OpCode op = context.CurrOp; - - bool absoluteA = false, negateA = false; - - if (op is OpCodeAluImm32 && isAdd) + if (isFP64) { - negateA = op.RawOpCode.Extract(56); + return context.PackDouble2x32(Register(reg, RegisterType.Gpr), Register(reg | 1, RegisterType.Gpr)); } - else if (isAdd || op is IOpCodeCbuf || op is IOpCodeImm) + else { - negateA = op.RawOpCode.Extract(43); - absoluteA = op.RawOpCode.Extract(44); + return Register(reg, RegisterType.Gpr); } - else if (op is IOpCodeReg) - { - absoluteA = op.RawOpCode.Extract(44); - } - - FPHalfSwizzle swizzle = (FPHalfSwizzle)op.RawOpCode.Extract(47, 2); - - Operand[] operands = GetHalfUnpacked(context, GetSrcA(context), swizzle); - - return FPAbsNeg(context, operands, absoluteA, negateA); } - public static Operand[] GetHalfSrcB(EmitterContext context, bool isMul = false) + public static Operand[] GetHalfSrc( + EmitterContext context, + HalfSwizzle swizzle, + int ra, + bool negate, + bool absolute) { - OpCode op = context.CurrOp; + Operand[] operands = GetHalfUnpacked(context, GetSrcReg(context, ra), swizzle); - FPHalfSwizzle swizzle = FPHalfSwizzle.FP16; + return FPAbsNeg(context, operands, absolute, negate); + } - bool absoluteB = false, negateB = false; + public static Operand[] GetHalfSrc( + EmitterContext context, + HalfSwizzle swizzle, + int cbufSlot, + int cbufOffset, + bool negate, + bool absolute) + { + Operand[] operands = GetHalfUnpacked(context, GetSrcCbuf(context, cbufSlot, cbufOffset), swizzle); - if (op is IOpCodeReg) + return FPAbsNeg(context, operands, absolute, negate); + } + + public static Operand[] GetHalfSrc(EmitterContext context, int immH0, int immH1) + { + ushort low = (ushort)(immH0 << 6); + ushort high = (ushort)(immH1 << 6); + + return new Operand[] { - swizzle = (FPHalfSwizzle)op.RawOpCode.Extract(28, 2); + ConstF((float)Unsafe.As(ref low)), + ConstF((float)Unsafe.As(ref high)) + }; + } - absoluteB = op.RawOpCode.Extract(30); - negateB = op.RawOpCode.Extract(31); - } - else if (op is IOpCodeCbuf) + public static Operand[] GetHalfSrc(EmitterContext context, int imm32) + { + ushort low = (ushort)imm32; + ushort high = (ushort)(imm32 >> 16); + + return new Operand[] { - swizzle = FPHalfSwizzle.FP32; - - absoluteB = op.RawOpCode.Extract(54); - - if (!isMul) - { - negateB = op.RawOpCode.Extract(56); - } - } - - Operand[] operands = GetHalfUnpacked(context, GetSrcB(context), swizzle); - - return FPAbsNeg(context, operands, absoluteB, negateB); + ConstF((float)Unsafe.As(ref low)), + ConstF((float)Unsafe.As(ref high)) + }; } public static Operand[] FPAbsNeg(EmitterContext context, Operand[] operands, bool abs, bool neg) @@ -219,27 +137,27 @@ namespace Ryujinx.Graphics.Shader.Instructions return operands; } - public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, FPHalfSwizzle swizzle) + public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle) { switch (swizzle) { - case FPHalfSwizzle.FP16: + case HalfSwizzle.F16: return new Operand[] { context.UnpackHalf2x16Low (src), context.UnpackHalf2x16High(src) }; - case FPHalfSwizzle.FP32: return new Operand[] { src, src }; + case HalfSwizzle.F32: return new Operand[] { src, src }; - case FPHalfSwizzle.DupH0: + case HalfSwizzle.H0H0: return new Operand[] { context.UnpackHalf2x16Low(src), context.UnpackHalf2x16Low(src) }; - case FPHalfSwizzle.DupH1: + case HalfSwizzle.H1H1: return new Operand[] { context.UnpackHalf2x16High(src), @@ -250,33 +168,24 @@ namespace Ryujinx.Graphics.Shader.Instructions throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."); } - public static Operand GetHalfPacked(EmitterContext context, Operand[] results) + public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd) { - OpCode op = context.CurrOp; - - FPHalfSwizzle swizzle = FPHalfSwizzle.FP16; - - if (!(op is OpCodeAluImm32)) - { - swizzle = (FPHalfSwizzle)context.CurrOp.RawOpCode.Extract(49, 2); - } - switch (swizzle) { - case FPHalfSwizzle.FP16: return context.PackHalf2x16(results[0], results[1]); + case OFmt.F16: return context.PackHalf2x16(results[0], results[1]); - case FPHalfSwizzle.FP32: return results[0]; + case OFmt.F32: return results[0]; - case FPHalfSwizzle.DupH0: + case OFmt.MrgH0: { - Operand h1 = GetHalfDest(context, isHigh: true); + Operand h1 = GetHalfDest(context, rd, isHigh: true); return context.PackHalf2x16(results[0], h1); } - case FPHalfSwizzle.DupH1: + case OFmt.MrgH1: { - Operand h0 = GetHalfDest(context, isHigh: false); + Operand h0 = GetHalfDest(context, rd, isHigh: false); return context.PackHalf2x16(h0, results[1]); } @@ -285,25 +194,23 @@ namespace Ryujinx.Graphics.Shader.Instructions throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."); } - public static Operand GetHalfDest(EmitterContext context, bool isHigh) + public static Operand GetHalfDest(EmitterContext context, int rd, bool isHigh) { if (isHigh) { - return context.UnpackHalf2x16High(GetDest(context)); + return context.UnpackHalf2x16High(GetDest(rd)); } else { - return context.UnpackHalf2x16Low(GetDest(context)); + return context.UnpackHalf2x16Low(GetDest(rd)); } } - public static Operand GetPredicate39(EmitterContext context) + public static Operand GetPredicate(EmitterContext context, int pred, bool not) { - IOpCodePredicate39 op = (IOpCodePredicate39)context.CurrOp; + Operand local = Register(pred, RegisterType.Predicate); - Operand local = Register(op.Predicate39); - - if (op.InvertP) + if (not) { local = context.BitwiseNot(local); } @@ -311,6 +218,26 @@ namespace Ryujinx.Graphics.Shader.Instructions return local; } + public static int Imm16ToSInt(int imm16) + { + return (short)imm16; + } + + public static int Imm20ToFloat(int imm20) + { + return imm20 << 12; + } + + public static int Imm20ToSInt(int imm20) + { + return (imm20 << 12) >> 12; + } + + public static int Imm24ToSInt(int imm24) + { + return (imm24 << 8) >> 8; + } + public static Operand SignExtendTo32(EmitterContext context, Operand src, int srcBits) { return context.BitfieldExtractS32(src, Const(0), Const(srcBits)); @@ -318,7 +245,7 @@ namespace Ryujinx.Graphics.Shader.Instructions public static Operand ZeroExtendTo32(EmitterContext context, Operand src, int srcBits) { - int mask = (int)(0xffffffffu >> (32 - srcBits)); + int mask = (int)(uint.MaxValue >> (32 - srcBits)); return context.BitwiseAnd(src, Const(mask)); } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs new file mode 100644 index 00000000..ac8cca1b --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerArithmetic.cs @@ -0,0 +1,656 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void IaddR(EmitterContext context) + { + InstIaddR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); + } + + public static void IaddI(EmitterContext context) + { + InstIaddI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); + } + + public static void IaddC(EmitterContext context) + { + InstIaddC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); + } + + public static void Iadd32i(EmitterContext context) + { + InstIadd32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + + EmitIadd(context, srcA, srcB, op.Dest, op.AvgMode, op.X, op.WriteCC); + } + + public static void Iadd3R(EmitterContext context) + { + InstIadd3R op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIadd3(context, op.Lrs, srcA, srcB, srcC, op.Apart, op.Bpart, op.Cpart, op.Dest, op.NegA, op.NegB, op.NegC); + } + + public static void Iadd3I(EmitterContext context) + { + InstIadd3I op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); + } + + public static void Iadd3C(EmitterContext context) + { + InstIadd3C op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIadd3(context, Lrs.None, srcA, srcB, srcC, HalfSelect.B32, HalfSelect.B32, HalfSelect.B32, op.Dest, op.NegA, op.NegB, op.NegC); + } + + public static void ImadR(EmitterContext context) + { + InstImadR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); + } + + public static void ImadI(EmitterContext context) + { + InstImadI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); + } + + public static void ImadC(EmitterContext context) + { + InstImadC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); + } + + public static void ImadRc(EmitterContext context) + { + InstImadRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); + } + + public static void Imad32i(EmitterContext context) + { + InstImad32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + var srcC = GetSrcReg(context, op.Dest); + + EmitImad(context, srcA, srcB, srcC, op.Dest, op.AvgMode, op.ASigned, op.BSigned, op.Hilo); + } + + public static void IscaddR(EmitterContext context) + { + InstIscaddR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); + } + + public static void IscaddI(EmitterContext context) + { + InstIscaddI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); + } + + public static void IscaddC(EmitterContext context) + { + InstIscaddC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, op.AvgMode, op.WriteCC); + } + + public static void Iscadd32i(EmitterContext context) + { + InstIscadd32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + + EmitIscadd(context, srcA, srcB, op.Dest, op.Imm5, AvgMode.NoNeg, op.WriteCC); + } + + public static void LeaR(EmitterContext context) + { + InstLeaR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); + } + + public static void LeaI(EmitterContext context) + { + InstLeaI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); + } + + public static void LeaC(EmitterContext context) + { + InstLeaC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitLea(context, srcA, srcB, op.Dest, op.NegA, op.ImmU5); + } + + public static void LeaHiR(EmitterContext context) + { + InstLeaHiR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); + } + + public static void LeaHiC(EmitterContext context) + { + InstLeaHiC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitLeaHi(context, srcA, srcB, srcC, op.Dest, op.NegA, op.ImmU5); + } + + public static void XmadR(EmitterContext context) + { + InstXmadR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); + } + + public static void XmadI(EmitterContext context) + { + InstXmadI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm16); + var srcC = GetSrcReg(context, op.SrcC); + + EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, false, op.Psl, op.Mrg, op.X, op.WriteCC); + } + + public static void XmadC(EmitterContext context) + { + InstXmadC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, op.Psl, op.Mrg, op.X, op.WriteCC); + } + + public static void XmadRc(EmitterContext context) + { + InstXmadRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitXmad(context, op.XmadCop, srcA, srcB, srcC, op.Dest, op.ASigned, op.BSigned, op.HiloA, op.HiloB, false, false, op.X, op.WriteCC); + } + + private static void EmitIadd( + EmitterContext context, + Operand srcA, + Operand srcB, + int rd, + AvgMode avgMode, + bool extended, + bool writeCC) + { + srcA = context.INegate(srcA, avgMode == AvgMode.NegA); + srcB = context.INegate(srcB, avgMode == AvgMode.NegB); + + Operand res = context.IAdd(srcA, srcB); + + if (extended) + { + res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); + } + + SetIaddFlags(context, res, srcA, srcB, writeCC, extended); + + // TODO: SAT. + + context.Copy(GetDest(rd), res); + } + + private static void EmitIadd3( + EmitterContext context, + Lrs mode, + Operand srcA, + Operand srcB, + Operand srcC, + HalfSelect partA, + HalfSelect partB, + HalfSelect partC, + int rd, + bool negateA, + bool negateB, + bool negateC) + { + Operand Extend(Operand src, HalfSelect part) + { + if (part == HalfSelect.B32) + { + return src; + } + + if (part == HalfSelect.H0) + { + return context.BitwiseAnd(src, Const(0xffff)); + } + else if (part == HalfSelect.H1) + { + return context.ShiftRightU32(src, Const(16)); + } + else + { + context.Config.GpuAccessor.Log($"Iadd3 has invalid component selection {part}."); + } + + return src; + } + + srcA = context.INegate(Extend(srcA, partA), negateA); + srcB = context.INegate(Extend(srcB, partB), negateB); + srcC = context.INegate(Extend(srcC, partC), negateC); + + Operand res = context.IAdd(srcA, srcB); + + if (mode != Lrs.None) + { + if (mode == Lrs.LeftShift) + { + res = context.ShiftLeft(res, Const(16)); + } + else if (mode == Lrs.RightShift) + { + res = context.ShiftRightU32(res, Const(16)); + } + else + { + // TODO: Warning. + } + } + + res = context.IAdd(res, srcC); + + context.Copy(GetDest(rd), res); + + // TODO: CC, X, corner cases. + } + + public static void EmitImad( + EmitterContext context, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + AvgMode avgMode, + bool signedA, + bool signedB, + bool high) + { + srcB = context.INegate(srcB, avgMode == AvgMode.NegA); + srcC = context.INegate(srcC, avgMode == AvgMode.NegB); + + Operand res; + + if (high) + { + if (signedA && signedB) + { + res = context.MultiplyHighS32(srcA, srcB); + } + else + { + res = context.MultiplyHighU32(srcA, srcB); + + if (signedA) + { + res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31)))); + } + else if (signedB) + { + res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31)))); + } + } + } + else + { + res = context.IMultiply(srcA, srcB); + } + + res = context.IAdd(res, srcC); + + // TODO: CC, X, SAT, and more? + + context.Copy(GetDest(rd), res); + } + + private static void EmitIscadd( + EmitterContext context, + Operand srcA, + Operand srcB, + int rd, + int shift, + AvgMode avgMode, + bool writeCC) + { + srcA = context.ShiftLeft(srcA, Const(shift)); + + srcA = context.INegate(srcA, avgMode == AvgMode.NegA); + srcB = context.INegate(srcB, avgMode == AvgMode.NegB); + + Operand res = context.IAdd(srcA, srcB); + + SetIaddFlags(context, res, srcA, srcB, writeCC, false); + + context.Copy(GetDest(rd), res); + } + + public static void EmitLea(EmitterContext context, Operand srcA, Operand srcB, int rd, bool negateA, int shift) + { + srcA = context.ShiftLeft(srcA, Const(shift)); + srcA = context.INegate(srcA, negateA); + + Operand res = context.IAdd(srcA, srcB); + + context.Copy(GetDest(rd), res); + + // TODO: CC, X. + } + + private static void EmitLeaHi( + EmitterContext context, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + bool negateA, + int shift) + { + Operand aLow = context.ShiftLeft(srcA, Const(shift)); + Operand aHigh = shift == 0 ? Const(0) : context.ShiftRightU32(srcA, Const(32 - shift)); + aHigh = context.BitwiseOr(aHigh, context.ShiftLeft(srcC, Const(shift))); + + if (negateA) + { + // Perform 64-bit negation by doing bitwise not of the value, + // then adding 1 and carrying over from low to high. + aLow = context.BitwiseNot(aLow); + aHigh = context.BitwiseNot(aHigh); + + aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut); + aHigh = context.IAdd(aHigh, aLowCOut); + } + + Operand res = context.IAdd(aHigh, srcB); + + context.Copy(GetDest(rd), res); + + // TODO: CC, X. + } + + public static void EmitXmad( + EmitterContext context, + XmadCop2 mode, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + bool signedA, + bool signedB, + bool highA, + bool highB, + bool productShiftLeft, + bool merge, + bool extended, + bool writeCC) + { + XmadCop modeConv; + switch (mode) + { + case XmadCop2.Cfull: + modeConv = XmadCop.Cfull; + break; + case XmadCop2.Clo: + modeConv = XmadCop.Clo; + break; + case XmadCop2.Chi: + modeConv = XmadCop.Chi; + break; + case XmadCop2.Csfu: + modeConv = XmadCop.Csfu; + break; + default: + context.Config.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); + return; + } + + EmitXmad(context, modeConv, srcA, srcB, srcC, rd, signedA, signedB, highA, highB, productShiftLeft, merge, extended, writeCC); + } + + public static void EmitXmad( + EmitterContext context, + XmadCop mode, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + bool signedA, + bool signedB, + bool highA, + bool highB, + bool productShiftLeft, + bool merge, + bool extended, + bool writeCC) + { + var srcBUnmodified = srcB; + + Operand Extend16To32(Operand src, bool high, bool signed) + { + if (signed && high) + { + return context.ShiftRightS32(src, Const(16)); + } + else if (signed) + { + return context.BitfieldExtractS32(src, Const(0), Const(16)); + } + else if (high) + { + return context.ShiftRightU32(src, Const(16)); + } + else + { + return context.BitwiseAnd(src, Const(0xffff)); + } + } + + srcA = Extend16To32(srcA, highA, signedA); + srcB = Extend16To32(srcB, highB, signedB); + + Operand res = context.IMultiply(srcA, srcB); + + if (productShiftLeft) + { + res = context.ShiftLeft(res, Const(16)); + } + + switch (mode) + { + case XmadCop.Cfull: + break; + + case XmadCop.Clo: + srcC = Extend16To32(srcC, high: false, signed: false); + break; + case XmadCop.Chi: + srcC = Extend16To32(srcC, high: true, signed: false); + break; + + case XmadCop.Cbcc: + srcC = context.IAdd(srcC, context.ShiftLeft(srcBUnmodified, Const(16))); + break; + + case XmadCop.Csfu: + Operand signAdjustA = context.ShiftLeft(context.ShiftRightU32(srcA, Const(31)), Const(16)); + Operand signAdjustB = context.ShiftLeft(context.ShiftRightU32(srcB, Const(31)), Const(16)); + + srcC = context.ISubtract(srcC, context.IAdd(signAdjustA, signAdjustB)); + break; + + default: + context.Config.GpuAccessor.Log($"Invalid XMAD mode \"{mode}\"."); + return; + } + + Operand product = res; + + if (extended) + { + // Add with carry. + res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1))); + } + else + { + // Add (no carry in). + res = context.IAdd(res, srcC); + } + + SetIaddFlags(context, res, product, srcC, writeCC, extended); + + if (merge) + { + res = context.BitwiseAnd(res, Const(0xffff)); + res = context.BitwiseOr(res, context.ShiftLeft(srcBUnmodified, Const(16))); + } + + context.Copy(GetDest(rd), res); + } + + private static void SetIaddFlags(EmitterContext context, Operand res, Operand srcA, Operand srcB, bool setCC, bool extended) + { + if (!setCC) + { + return; + } + + if (extended) + { + // C = (d == a && CIn) || d < a + Operand tempC0 = context.ICompareEqual(res, srcA); + Operand tempC1 = context.ICompareLessUnsigned(res, srcA); + + tempC0 = context.BitwiseAnd(tempC0, GetCF()); + + context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1)); + } + else + { + // C = d < a + context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA)); + } + + // V = (d ^ a) & ~(a ^ b) < 0 + Operand tempV0 = context.BitwiseExclusiveOr(res, srcA); + Operand tempV1 = context.BitwiseExclusiveOr(srcA, srcB); + + tempV1 = context.BitwiseNot(tempV1); + + Operand tempV = context.BitwiseAnd(tempV0, tempV1); + + context.Copy(GetVF(), context.ICompareLess(tempV, Const(0))); + + SetZnFlags(context, res, setCC: true, extended: extended); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs new file mode 100644 index 00000000..ddd90f8e --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerComparison.cs @@ -0,0 +1,327 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; +using System; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Csetp(EmitterContext context) + { + InstCsetp op = context.GetOp(); + + // TODO: Implement that properly. + + Operand p0Res = Const(IrConsts.True); + Operand p1Res = context.BitwiseNot(p0Res); + Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + p0Res = GetPredLogicalOp(context, op.Bop, p0Res, srcPred); + p1Res = GetPredLogicalOp(context, op.Bop, p1Res, srcPred); + + context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); + context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); + } + + public static void IcmpR(EmitterContext context) + { + InstIcmpR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); + } + + public static void IcmpI(EmitterContext context) + { + InstIcmpI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); + } + + public static void IcmpC(EmitterContext context) + { + InstIcmpC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); + } + + public static void IcmpRc(EmitterContext context) + { + InstIcmpRc op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcC); + var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitIcmp(context, op.IComp, srcA, srcB, srcC, op.Dest, op.Signed); + } + + public static void IsetR(EmitterContext context) + { + InstIsetR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); + } + + public static void IsetI(EmitterContext context) + { + InstIsetI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); + } + + public static void IsetC(EmitterContext context) + { + InstIsetC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitIset(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.Dest, op.BVal, op.Signed, op.X, op.WriteCC); + } + + public static void IsetpR(EmitterContext context) + { + InstIsetpR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); + } + + public static void IsetpI(EmitterContext context) + { + InstIsetpI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); + } + + public static void IsetpC(EmitterContext context) + { + InstIsetpC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitIsetp(context, op.IComp, op.Bop, srcA, srcB, op.SrcPred, op.SrcPredInv, op.DestPred, op.DestPredInv, op.Signed, op.X); + } + + private static void EmitIcmp( + EmitterContext context, + IComp cmpOp, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + bool isSigned) + { + Operand cmpRes = GetIntComparison(context, cmpOp, srcC, Const(0), isSigned); + + Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); + + context.Copy(GetDest(rd), res); + } + + private static void EmitIset( + EmitterContext context, + IComp cmpOp, + BoolOp logicOp, + Operand srcA, + Operand srcB, + int srcPred, + bool srcPredInv, + int rd, + bool boolFloat, + bool isSigned, + bool extended, + bool writeCC) + { + Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, extended); + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + res = GetPredLogicalOp(context, logicOp, res, pred); + + Operand dest = GetDest(rd); + + if (boolFloat) + { + res = context.ConditionalSelect(res, ConstF(1), Const(0)); + + context.Copy(dest, res); + + SetFPZnFlags(context, res, writeCC); + } + else + { + context.Copy(dest, res); + + SetZnFlags(context, res, writeCC, extended); + } + } + + private static void EmitIsetp( + EmitterContext context, + IComp cmpOp, + BoolOp logicOp, + Operand srcA, + Operand srcB, + int srcPred, + bool srcPredInv, + int destPred, + int destPredInv, + bool isSigned, + bool extended) + { + Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, extended); + Operand p1Res = context.BitwiseNot(p0Res); + Operand pred = GetPredicate(context, srcPred, srcPredInv); + + p0Res = GetPredLogicalOp(context, logicOp, p0Res, pred); + p1Res = GetPredLogicalOp(context, logicOp, p1Res, pred); + + context.Copy(Register(destPred, RegisterType.Predicate), p0Res); + context.Copy(Register(destPredInv, RegisterType.Predicate), p1Res); + } + + private static Operand GetIntComparison( + EmitterContext context, + IComp cond, + Operand srcA, + Operand srcB, + bool isSigned, + bool extended) + { + return extended + ? GetIntComparisonExtended(context, cond, srcA, srcB, isSigned) + : GetIntComparison(context, cond, srcA, srcB, isSigned); + } + + private static Operand GetIntComparisonExtended(EmitterContext context, IComp cond, Operand srcA, Operand srcB, bool isSigned) + { + Operand res; + + if (cond == IComp.T) + { + res = Const(IrConsts.True); + } + else if (cond == IComp.F) + { + res = Const(IrConsts.False); + } + else + { + res = context.ISubtract(srcA, srcB); + res = context.IAdd(res, context.BitwiseNot(GetCF())); + + switch (cond) + { + case IComp.Eq: // r = xh == yh && xl == yl + res = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetZF()); + break; + case IComp.Lt: // r = xh < yh || (xh == yh && xl < yl) + Operand notC = context.BitwiseNot(GetCF()); + Operand prevLt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notC); + res = isSigned + ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLt) + : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLt); + break; + case IComp.Le: // r = xh < yh || (xh == yh && xl <= yl) + Operand zOrNotC = context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF())); + Operand prevLe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), zOrNotC); + res = isSigned + ? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLe) + : context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLe); + break; + case IComp.Gt: // r = xh > yh || (xh == yh && xl > yl) + Operand notZAndC = context.BitwiseAnd(context.BitwiseNot(GetZF()), GetCF()); + Operand prevGt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notZAndC); + res = isSigned + ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGt) + : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGt); + break; + case IComp.Ge: // r = xh > yh || (xh == yh && xl >= yl) + Operand prevGe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetCF()); + res = isSigned + ? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGe) + : context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGe); + break; + case IComp.Ne: // r = xh != yh || xl != yl + res = context.BitwiseOr(context.ICompareNotEqual(srcA, srcB), context.BitwiseNot(GetZF())); + break; + default: + throw new ArgumentException($"Unexpected condition \"{cond}\"."); + } + } + + return res; + } + + private static Operand GetIntComparison(EmitterContext context, IComp cond, Operand srcA, Operand srcB, bool isSigned) + { + Operand res; + + if (cond == IComp.T) + { + res = Const(IrConsts.True); + } + else if (cond == IComp.F) + { + res = Const(IrConsts.False); + } + else + { + var inst = cond switch + { + IComp.Lt => Instruction.CompareLessU32, + IComp.Eq => Instruction.CompareEqual, + IComp.Le => Instruction.CompareLessOrEqualU32, + IComp.Gt => Instruction.CompareGreaterU32, + IComp.Ne => Instruction.CompareNotEqual, + IComp.Ge => Instruction.CompareGreaterOrEqualU32, + _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".") + }; + + if (isSigned) + { + switch (cond) + { + case IComp.Lt: inst = Instruction.CompareLess; break; + case IComp.Le: inst = Instruction.CompareLessOrEqual; break; + case IComp.Gt: inst = Instruction.CompareGreater; break; + case IComp.Ge: inst = Instruction.CompareGreaterOrEqual; break; + } + } + + res = context.Add(inst, Local(), srcA, srcB); + } + + return res; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs new file mode 100644 index 00000000..1f3f66ae --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerLogical.cs @@ -0,0 +1,167 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + private const int PT = RegisterConsts.PredicateTrueIndex; + + public static void LopR(EmitterContext context) + { + InstLopR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitLop(context, op.Lop, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); + } + + public static void LopI(EmitterContext context) + { + InstLopI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); + } + + public static void LopC(EmitterContext context) + { + InstLopC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC); + } + + public static void Lop32i(EmitterContext context) + { + InstLop32i op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, op.Imm32); + + EmitLop(context, op.LogicOp, PredicateOp.F, srcA, srcB, op.Dest, PT, op.NegA, op.NegB, op.X, op.WriteCC); + } + + public static void Lop3R(EmitterContext context) + { + InstLop3R op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcC = GetSrcReg(context, op.SrcC); + + EmitLop3(context, op.Imm, op.PredicateOp, srcA, srcB, srcC, op.Dest, op.DestPred, op.X, op.WriteCC); + } + + public static void Lop3I(EmitterContext context) + { + InstLop3I op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcC = GetSrcReg(context, op.SrcC); + + EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC); + } + + public static void Lop3C(EmitterContext context) + { + InstLop3C op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcC = GetSrcReg(context, op.SrcC); + + EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC); + } + + private static void EmitLop( + EmitterContext context, + LogicOp logicOp, + PredicateOp predOp, + Operand srcA, + Operand srcB, + int rd, + int destPred, + bool invertA, + bool invertB, + bool extended, + bool writeCC) + { + srcA = context.BitwiseNot(srcA, invertA); + srcB = context.BitwiseNot(srcB, invertB); + + Operand res = logicOp switch + { + LogicOp.And => res = context.BitwiseAnd(srcA, srcB), + LogicOp.Or => res = context.BitwiseOr(srcA, srcB), + LogicOp.Xor => res = context.BitwiseExclusiveOr(srcA, srcB), + _ => srcB + }; + + EmitLopPredWrite(context, res, predOp, destPred); + + context.Copy(GetDest(rd), res); + + SetZnFlags(context, res, writeCC, extended); + } + + private static void EmitLop3( + EmitterContext context, + int truthTable, + PredicateOp predOp, + Operand srcA, + Operand srcB, + Operand srcC, + int rd, + int destPred, + bool extended, + bool writeCC) + { + Operand res = Lop3Expression.GetFromTruthTable(context, srcA, srcB, srcC, truthTable); + + EmitLopPredWrite(context, res, predOp, destPred); + + context.Copy(GetDest(rd), res); + + SetZnFlags(context, res, writeCC, extended); + } + + private static void EmitLopPredWrite(EmitterContext context, Operand result, PredicateOp predOp, int pred) + { + if (pred != RegisterConsts.PredicateTrueIndex) + { + Operand pRes; + + if (predOp == PredicateOp.F) + { + pRes = Const(IrConsts.False); + } + else if (predOp == PredicateOp.T) + { + pRes = Const(IrConsts.True); + } + else if (predOp == PredicateOp.Z) + { + pRes = context.ICompareEqual(result, Const(0)); + } + else /* if (predOp == Pop.Nz) */ + { + pRes = context.ICompareNotEqual(result, Const(0)); + } + + context.Copy(Register(pred, RegisterType.Predicate), pRes); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs new file mode 100644 index 00000000..73930ed1 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitIntegerMinMax.cs @@ -0,0 +1,71 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void ImnmxR(EmitterContext context) + { + InstImnmxR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); + } + + public static void ImnmxI(EmitterContext context) + { + InstImnmxI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); + } + + public static void ImnmxC(EmitterContext context) + { + InstImnmxC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + var srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitImnmx(context, srcA, srcB, srcPred, op.Dest, op.Signed, op.WriteCC); + } + + private static void EmitImnmx( + EmitterContext context, + Operand srcA, + Operand srcB, + Operand srcPred, + int rd, + bool isSignedInt, + bool writeCC) + { + Operand resMin = isSignedInt + ? context.IMinimumS32(srcA, srcB) + : context.IMinimumU32(srcA, srcB); + + Operand resMax = isSignedInt + ? context.IMaximumS32(srcA, srcB) + : context.IMaximumU32(srcA, srcB); + + Operand res = context.ConditionalSelect(srcPred, resMin, resMax); + + context.Copy(GetDest(rd), res); + + SetZnFlags(context, res, writeCC); + + // TODO: X flags. + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs index 6744a9e8..78f41e8e 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs @@ -15,369 +15,160 @@ namespace Ryujinx.Graphics.Shader.Instructions Shared } - public static void Al2p(EmitterContext context) - { - OpCodeAl2p op = (OpCodeAl2p)context.CurrOp; - - if (op.Rd.IsRZ) - { - return; - } - - context.Copy(Register(op.Rd), context.IAdd(Register(op.Ra), Const(op.Immediate))); - } - - public static void Ald(EmitterContext context) - { - OpCodeAttribute op = (OpCodeAttribute)context.CurrOp; - - Operand primVertex = context.Copy(GetSrcC(context)); - - for (int index = 0; index < op.Count; index++) - { - Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr); - - if (rd.IsRZ) - { - break; - } - - if (op.Phys) - { - Operand userAttrOffset = context.ISubtract(GetSrcA(context), Const(AttributeConsts.UserAttributeBase)); - Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); - - context.Copy(Register(rd), context.LoadAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, primVertex)); - - context.Config.SetUsedFeature(FeatureFlags.IaIndexing); - } - else if (op.Rc.IsRZ) - { - Operand src = Attribute(op.AttributeOffset + index * 4); - - context.FlagAttributeRead(src.Value); - - context.Copy(Register(rd), src); - } - else - { - Operand src = Const(op.AttributeOffset + index * 4); - - context.FlagAttributeRead(src.Value); - - context.Copy(Register(rd), context.LoadAttribute(src, Const(0), primVertex)); - } - } - } - - public static void Ast(EmitterContext context) - { - OpCodeAttribute op = (OpCodeAttribute)context.CurrOp; - - for (int index = 0; index < op.Count; index++) - { - if (op.Rd.Index + index > RegisterConsts.RegisterZeroIndex) - { - break; - } - - Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr); - - if (op.Phys) - { - Operand userAttrOffset = context.ISubtract(GetSrcA(context), Const(AttributeConsts.UserAttributeBase)); - Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); - - context.StoreAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, Register(rd)); - - context.Config.SetUsedFeature(FeatureFlags.OaIndexing); - } - else - { - Operand dest = Attribute(op.AttributeOffset + index * 4); - - context.FlagAttributeWritten(dest.Value); - - context.Copy(dest, Register(rd)); - } - } - } - public static void Atom(EmitterContext context) { - OpCodeAtom op = (OpCodeAtom)context.CurrOp; + InstAtom op = context.GetOp(); - ReductionType type = (ReductionType)op.RawOpCode.Extract(49, 2); + int sOffset = (op.Imm20 << 12) >> 12; - int sOffset = (op.RawOpCode.Extract(28, 20) << 12) >> 12; + (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(op.SrcA, RegisterType.Gpr), op.E, sOffset); - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, op.Ra, op.Extended, sOffset); + Operand value = GetSrcReg(context, op.SrcB); - Operand value = GetSrcB(context); + Operand res = EmitAtomicOp(context, Instruction.MrGlobal, op.Op, op.Size, addrLow, addrHigh, value); - Operand res = EmitAtomicOp( - context, - Instruction.MrGlobal, - op.AtomicOp, - type, - addrLow, - addrHigh, - value); - - context.Copy(GetDest(context), res); + context.Copy(GetDest(op.Dest), res); } public static void Atoms(EmitterContext context) { - OpCodeAtom op = (OpCodeAtom)context.CurrOp; + InstAtoms op = context.GetOp(); - ReductionType type = op.RawOpCode.Extract(28, 2) switch - { - 0 => ReductionType.U32, - 1 => ReductionType.S32, - 2 => ReductionType.U64, - _ => ReductionType.S64 - }; + Operand offset = context.ShiftRightU32(GetSrcReg(context, op.SrcA), Const(2)); - Operand offset = context.ShiftRightU32(GetSrcA(context), Const(2)); - - int sOffset = (op.RawOpCode.Extract(30, 22) << 10) >> 10; + int sOffset = (op.Imm22 << 10) >> 10; offset = context.IAdd(offset, Const(sOffset)); - Operand value = GetSrcB(context); + Operand value = GetSrcReg(context, op.SrcB); - Operand res = EmitAtomicOp( - context, - Instruction.MrShared, - op.AtomicOp, - type, - offset, - Const(0), - value); - - context.Copy(GetDest(context), res); - } - - public static void Bar(EmitterContext context) - { - OpCodeBarrier op = (OpCodeBarrier)context.CurrOp; - - // TODO: Support other modes. - if (op.Mode == BarrierMode.Sync) + AtomSize size = op.AtomsSize switch { - context.Barrier(); - } - else - { - context.Config.GpuAccessor.Log($"Invalid barrier mode: {op.Mode}."); - } - } + AtomsSize.S32 => AtomSize.S32, + AtomsSize.U64 => AtomSize.U64, + AtomsSize.S64 => AtomSize.S64, + _ => AtomSize.U32 + }; - public static void Ipa(EmitterContext context) - { - OpCodeIpa op = (OpCodeIpa)context.CurrOp; + Operand res = EmitAtomicOp(context, Instruction.MrShared, op.AtomOp, size, offset, Const(0), value); - context.FlagAttributeRead(op.AttributeOffset); - - Operand res; - - if (op.Idx) - { - Operand userAttrOffset = context.ISubtract(GetSrcA(context), Const(AttributeConsts.UserAttributeBase)); - Operand userAttrIndex = context.ShiftRightU32(userAttrOffset, Const(2)); - - res = context.LoadAttribute(Const(AttributeConsts.UserAttributeBase), userAttrIndex, Const(0)); - res = context.FPMultiply(res, Attribute(AttributeConsts.PositionW)); - - context.Config.SetUsedFeature(FeatureFlags.IaIndexing); - } - else - { - res = Attribute(op.AttributeOffset); - - if (op.AttributeOffset >= AttributeConsts.UserAttributeBase && - op.AttributeOffset < AttributeConsts.UserAttributeEnd) - { - int index = (op.AttributeOffset - AttributeConsts.UserAttributeBase) >> 4; - - if (context.Config.ImapTypes[index].GetFirstUsedType() == PixelImap.Perspective) - { - res = context.FPMultiply(res, Attribute(AttributeConsts.PositionW)); - } - } - } - - if (op.Mode == InterpolationMode.Default) - { - Operand srcB = GetSrcB(context); - - res = context.FPMultiply(res, srcB); - } - - res = context.FPSaturate(res, op.Saturate); - - context.Copy(GetDest(context), res); - } - - public static void Isberd(EmitterContext context) - { - // This instruction performs a load from ISBE memory, - // however it seems to be only used to get some vertex - // input data, so we instead propagate the offset so that - // it can be used on the attribute load. - context.Copy(GetDest(context), GetSrcA(context)); - } - - public static void Ld(EmitterContext context) - { - EmitLoad(context, MemoryRegion.Local); + context.Copy(GetDest(op.Dest), res); } public static void Ldc(EmitterContext context) { - OpCodeLdc op = (OpCodeLdc)context.CurrOp; + InstLdc op = context.GetOp(); - if (op.Size > IntegerSize.B64) + if (op.LsSize > LsSize2.B64) { - context.Config.GpuAccessor.Log($"Invalid LDC size: {op.Size}."); + context.Config.GpuAccessor.Log($"Invalid LDC size: {op.LsSize}."); + return; } - bool isSmallInt = op.Size < IntegerSize.B32; + bool isSmallInt = op.LsSize < LsSize2.B32; - int count = op.Size == IntegerSize.B64 ? 2 : 1; + int count = op.LsSize == LsSize2.B64 ? 2 : 1; - Operand slot = Const(op.Slot); - Operand srcA = GetSrcA(context); + Operand slot = Const(op.CbufSlot); + Operand srcA = GetSrcReg(context, op.SrcA); - if (op.IndexMode == CbIndexMode.Is || - op.IndexMode == CbIndexMode.Isl) + if (op.AddressMode == AddressMode.Is || op.AddressMode == AddressMode.Isl) { slot = context.IAdd(slot, context.BitfieldExtractU32(srcA, Const(16), Const(16))); srcA = context.BitwiseAnd(srcA, Const(0xffff)); } - Operand addr = context.IAdd(srcA, Const(op.Offset)); - + Operand addr = context.IAdd(srcA, Const(Imm16ToSInt(op.CbufOffset))); Operand wordOffset = context.ShiftRightU32(addr, Const(2)); - Operand bitOffset = GetBitOffset(context, addr); for (int index = 0; index < count; index++) { - Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr); + Register dest = new Register(op.Dest + index, RegisterType.Gpr); - if (rd.IsRZ) + if (dest.IsRZ) { break; } Operand offset = context.IAdd(wordOffset, Const(index)); - Operand value = context.LoadConstant(slot, offset); if (isSmallInt) { - value = ExtractSmallInt(context, op.Size, bitOffset, value); + value = ExtractSmallInt(context, (LsSize)op.LsSize, bitOffset, value); } - context.Copy(Register(rd), value); + context.Copy(Register(dest), value); } } public static void Ldg(EmitterContext context) { - EmitLoadGlobal(context); + InstLdg op = context.GetOp(); + + EmitLdg(context, op.LsSize, op.SrcA, op.Dest, Imm24ToSInt(op.Imm24), op.E); + } + + public static void Ldl(EmitterContext context) + { + InstLdl op = context.GetOp(); + + EmitLoad(context, MemoryRegion.Local, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); } public static void Lds(EmitterContext context) { - EmitLoad(context, MemoryRegion.Shared); - } + InstLds op = context.GetOp(); - public static void Membar(EmitterContext context) - { - OpCodeMemoryBarrier op = (OpCodeMemoryBarrier)context.CurrOp; - - if (op.Level == BarrierLevel.Cta) - { - context.GroupMemoryBarrier(); - } - else - { - context.MemoryBarrier(); - } - } - - public static void Out(EmitterContext context) - { - OpCode op = context.CurrOp; - - bool emit = op.RawOpCode.Extract(39); - bool cut = op.RawOpCode.Extract(40); - - if (!(emit || cut)) - { - context.Config.GpuAccessor.Log("Invalid OUT encoding."); - } - - if (emit) - { - context.EmitVertex(); - } - - if (cut) - { - context.EndPrimitive(); - } + EmitLoad(context, MemoryRegion.Shared, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); } public static void Red(EmitterContext context) { - OpCodeRed op = (OpCodeRed)context.CurrOp; + InstRed op = context.GetOp(); - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, op.Ra, op.Extended, op.Offset); + (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(op.SrcA, RegisterType.Gpr), op.E, op.Imm20); - EmitAtomicOp( - context, - Instruction.MrGlobal, - op.AtomicOp, - op.Type, - addrLow, - addrHigh, - GetDest(context)); - } - - public static void St(EmitterContext context) - { - EmitStore(context, MemoryRegion.Local); + EmitAtomicOp(context, Instruction.MrGlobal, (AtomOp)op.RedOp, op.RedSize, addrLow, addrHigh, GetDest(op.SrcB)); } public static void Stg(EmitterContext context) { - EmitStoreGlobal(context); + InstStg op = context.GetOp(); + + EmitStg(context, op.LsSize, op.SrcA, op.Dest, Imm24ToSInt(op.Imm24), op.E); + } + + public static void Stl(EmitterContext context) + { + InstStl op = context.GetOp(); + + EmitStore(context, MemoryRegion.Local, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); } public static void Sts(EmitterContext context) { - EmitStore(context, MemoryRegion.Shared); + InstSts op = context.GetOp(); + + EmitStore(context, MemoryRegion.Shared, op.LsSize, GetSrcReg(context, op.SrcA), op.Dest, Imm24ToSInt(op.Imm24)); } private static Operand EmitAtomicOp( EmitterContext context, - Instruction mr, - AtomicOp op, - ReductionType type, - Operand addrLow, - Operand addrHigh, - Operand value) + Instruction mr, + AtomOp op, + AtomSize type, + Operand addrLow, + Operand addrHigh, + Operand value) { Operand res = Const(0); switch (op) { - case AtomicOp.Add: - if (type == ReductionType.S32 || type == ReductionType.U32) + case AtomOp.Add: + if (type == AtomSize.S32 || type == AtomSize.U32) { res = context.AtomicAdd(mr, addrLow, addrHigh, value); } @@ -386,8 +177,8 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); } break; - case AtomicOp.BitwiseAnd: - if (type == ReductionType.S32 || type == ReductionType.U32) + case AtomOp.And: + if (type == AtomSize.S32 || type == AtomSize.U32) { res = context.AtomicAnd(mr, addrLow, addrHigh, value); } @@ -396,8 +187,8 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); } break; - case AtomicOp.BitwiseExclusiveOr: - if (type == ReductionType.S32 || type == ReductionType.U32) + case AtomOp.Xor: + if (type == AtomSize.S32 || type == AtomSize.U32) { res = context.AtomicXor(mr, addrLow, addrHigh, value); } @@ -406,8 +197,8 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); } break; - case AtomicOp.BitwiseOr: - if (type == ReductionType.S32 || type == ReductionType.U32) + case AtomOp.Or: + if (type == AtomSize.S32 || type == AtomSize.U32) { res = context.AtomicOr(mr, addrLow, addrHigh, value); } @@ -416,12 +207,12 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); } break; - case AtomicOp.Maximum: - if (type == ReductionType.S32) + case AtomOp.Max: + if (type == AtomSize.S32) { res = context.AtomicMaxS32(mr, addrLow, addrHigh, value); } - else if (type == ReductionType.U32) + else if (type == AtomSize.U32) { res = context.AtomicMaxU32(mr, addrLow, addrHigh, value); } @@ -430,12 +221,12 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log($"Invalid reduction type: {type}."); } break; - case AtomicOp.Minimum: - if (type == ReductionType.S32) + case AtomOp.Min: + if (type == AtomSize.S32) { res = context.AtomicMinS32(mr, addrLow, addrHigh, value); } - else if (type == ReductionType.U32) + else if (type == AtomSize.U32) { res = context.AtomicMinU32(mr, addrLow, addrHigh, value); } @@ -449,77 +240,82 @@ namespace Ryujinx.Graphics.Shader.Instructions return res; } - private static void EmitLoad(EmitterContext context, MemoryRegion region) + private static void EmitLoad( + EmitterContext context, + MemoryRegion region, + LsSize2 size, + Operand srcA, + int rd, + int offset) { - OpCodeMemory op = (OpCodeMemory)context.CurrOp; - - if (op.Size > IntegerSize.B128) + if (size > LsSize2.B128) { - context.Config.GpuAccessor.Log($"Invalid load size: {op.Size}."); + context.Config.GpuAccessor.Log($"Invalid load size: {size}."); + return; } - bool isSmallInt = op.Size < IntegerSize.B32; + bool isSmallInt = size < LsSize2.B32; int count = 1; - switch (op.Size) + switch (size) { - case IntegerSize.B64: count = 2; break; - case IntegerSize.B128: count = 4; break; + case LsSize2.B64: count = 2; break; + case LsSize2.B128: count = 4; break; } - Operand baseOffset = context.IAdd(GetSrcA(context), Const(op.Offset)); - - // Word offset = byte offset / 4 (one word = 4 bytes). - Operand wordOffset = context.ShiftRightU32(baseOffset, Const(2)); - + Operand baseOffset = context.IAdd(srcA, Const(offset)); + Operand wordOffset = context.ShiftRightU32(baseOffset, Const(2)); // Word offset = byte offset / 4 (one word = 4 bytes). Operand bitOffset = GetBitOffset(context, baseOffset); for (int index = 0; index < count; index++) { - Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr); + Register dest = new Register(rd + index, RegisterType.Gpr); - if (rd.IsRZ) + if (dest.IsRZ) { break; } - Operand offset = context.IAdd(wordOffset, Const(index)); - + Operand elemOffset = context.IAdd(wordOffset, Const(index)); Operand value = null; switch (region) { - case MemoryRegion.Local: value = context.LoadLocal (offset); break; - case MemoryRegion.Shared: value = context.LoadShared(offset); break; + case MemoryRegion.Local: value = context.LoadLocal(elemOffset); break; + case MemoryRegion.Shared: value = context.LoadShared(elemOffset); break; } if (isSmallInt) { - value = ExtractSmallInt(context, op.Size, bitOffset, value); + value = ExtractSmallInt(context, (LsSize)size, bitOffset, value); } - context.Copy(Register(rd), value); + context.Copy(Register(dest), value); } } - private static void EmitLoadGlobal(EmitterContext context) + private static void EmitLdg( + EmitterContext context, + LsSize size, + int ra, + int rd, + int offset, + bool extended) { - OpCodeMemory op = (OpCodeMemory)context.CurrOp; + bool isSmallInt = size < LsSize.B32; - bool isSmallInt = op.Size < IntegerSize.B32; + int count = GetVectorCount(size); - int count = GetVectorCount(op.Size); - - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, op.Ra, op.Extended, op.Offset); + (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset); Operand bitOffset = GetBitOffset(context, addrLow); for (int index = 0; index < count; index++) { - Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr); + Register dest = new Register(rd + index, RegisterType.Gpr); - if (rd.IsRZ) + if (dest.IsRZ) { break; } @@ -528,47 +324,47 @@ namespace Ryujinx.Graphics.Shader.Instructions if (isSmallInt) { - value = ExtractSmallInt(context, op.Size, bitOffset, value); + value = ExtractSmallInt(context, size, bitOffset, value); } - context.Copy(Register(rd), value); + context.Copy(Register(dest), value); } } - private static void EmitStore(EmitterContext context, MemoryRegion region) + private static void EmitStore( + EmitterContext context, + MemoryRegion region, + LsSize2 size, + Operand srcA, + int rd, + int offset) { - OpCodeMemory op = (OpCodeMemory)context.CurrOp; - - if (op.Size > IntegerSize.B128) + if (size > LsSize2.B128) { - context.Config.GpuAccessor.Log($"Invalid store size: {op.Size}."); + context.Config.GpuAccessor.Log($"Invalid store size: {size}."); + return; } - bool isSmallInt = op.Size < IntegerSize.B32; + bool isSmallInt = size < LsSize2.B32; int count = 1; - switch (op.Size) + switch (size) { - case IntegerSize.B64: count = 2; break; - case IntegerSize.B128: count = 4; break; + case LsSize2.B64: count = 2; break; + case LsSize2.B128: count = 4; break; } - Operand baseOffset = context.IAdd(GetSrcA(context), Const(op.Offset)); - + Operand baseOffset = context.IAdd(srcA, Const(offset)); Operand wordOffset = context.ShiftRightU32(baseOffset, Const(2)); - Operand bitOffset = GetBitOffset(context, baseOffset); for (int index = 0; index < count; index++) { - bool isRz = op.Rd.IsRZ; + bool isRz = rd + index >= RegisterConsts.RegisterZeroIndex; - Register rd = new Register(isRz ? op.Rd.Index : op.Rd.Index + index, RegisterType.Gpr); - - Operand value = Register(rd); - - Operand offset = context.IAdd(wordOffset, Const(index)); + Operand value = Register(isRz ? rd : rd + index, RegisterType.Gpr); + Operand elemOffset = context.IAdd(wordOffset, Const(index)); if (isSmallInt) { @@ -576,60 +372,68 @@ namespace Ryujinx.Graphics.Shader.Instructions switch (region) { - case MemoryRegion.Local: word = context.LoadLocal (offset); break; - case MemoryRegion.Shared: word = context.LoadShared(offset); break; + case MemoryRegion.Local: word = context.LoadLocal(elemOffset); break; + case MemoryRegion.Shared: word = context.LoadShared(elemOffset); break; } - value = InsertSmallInt(context, op.Size, bitOffset, word, value); + value = InsertSmallInt(context, (LsSize)size, bitOffset, word, value); } switch (region) { - case MemoryRegion.Local: context.StoreLocal (offset, value); break; - case MemoryRegion.Shared: context.StoreShared(offset, value); break; + case MemoryRegion.Local: context.StoreLocal(elemOffset, value); break; + case MemoryRegion.Shared: context.StoreShared(elemOffset, value); break; } } } - private static void EmitStoreGlobal(EmitterContext context) + private static void EmitStg( + EmitterContext context, + LsSize2 size, + int ra, + int rd, + int offset, + bool extended) { - OpCodeMemory op = (OpCodeMemory)context.CurrOp; + if (size > LsSize2.B128) + { + context.Config.GpuAccessor.Log($"Invalid store size: {size}."); + return; + } - bool isSmallInt = op.Size < IntegerSize.B32; + bool isSmallInt = size < LsSize2.B32; - int count = GetVectorCount(op.Size); + int count = GetVectorCount((LsSize)size); - (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, op.Ra, op.Extended, op.Offset); + (Operand addrLow, Operand addrHigh) = Get40BitsAddress(context, new Register(ra, RegisterType.Gpr), extended, offset); Operand bitOffset = GetBitOffset(context, addrLow); for (int index = 0; index < count; index++) { - bool isRz = op.Rd.IsRZ; + bool isRz = rd + index >= RegisterConsts.RegisterZeroIndex; - Register rd = new Register(isRz ? op.Rd.Index : op.Rd.Index + index, RegisterType.Gpr); - - Operand value = Register(rd); + Operand value = Register(isRz ? rd : rd + index, RegisterType.Gpr); if (isSmallInt) { Operand word = context.LoadGlobal(addrLow, addrHigh); - value = InsertSmallInt(context, op.Size, bitOffset, word, value); + value = InsertSmallInt(context, (LsSize)size, bitOffset, word, value); } context.StoreGlobal(context.IAdd(addrLow, Const(index * 4)), addrHigh, value); } } - private static int GetVectorCount(IntegerSize size) + private static int GetVectorCount(LsSize size) { switch (size) { - case IntegerSize.B64: + case LsSize.B64: return 2; - case IntegerSize.B128: - case IntegerSize.UB128: + case LsSize.B128: + case LsSize.UB128: return 4; } @@ -642,7 +446,7 @@ namespace Ryujinx.Graphics.Shader.Instructions bool extended, int offset) { - Operand addrLow = GetSrcA(context); + Operand addrLow = Register(ra); Operand addrHigh; if (extended && !ra.IsRZ) @@ -678,18 +482,18 @@ namespace Ryujinx.Graphics.Shader.Instructions private static Operand ExtractSmallInt( EmitterContext context, - IntegerSize size, - Operand bitOffset, - Operand value) + LsSize size, + Operand bitOffset, + Operand value) { value = context.ShiftRightU32(value, bitOffset); switch (size) { - case IntegerSize.U8: value = ZeroExtendTo32(context, value, 8); break; - case IntegerSize.U16: value = ZeroExtendTo32(context, value, 16); break; - case IntegerSize.S8: value = SignExtendTo32(context, value, 8); break; - case IntegerSize.S16: value = SignExtendTo32(context, value, 16); break; + case LsSize.U8: value = ZeroExtendTo32(context, value, 8); break; + case LsSize.U16: value = ZeroExtendTo32(context, value, 16); break; + case LsSize.S8: value = SignExtendTo32(context, value, 8); break; + case LsSize.S16: value = SignExtendTo32(context, value, 16); break; } return value; @@ -697,21 +501,21 @@ namespace Ryujinx.Graphics.Shader.Instructions private static Operand InsertSmallInt( EmitterContext context, - IntegerSize size, - Operand bitOffset, - Operand word, - Operand value) + LsSize size, + Operand bitOffset, + Operand word, + Operand value) { switch (size) { - case IntegerSize.U8: - case IntegerSize.S8: + case LsSize.U8: + case LsSize.S8: value = context.BitwiseAnd(value, Const(0xff)); value = context.BitfieldInsert(word, value, bitOffset, Const(8)); break; - case IntegerSize.U16: - case IntegerSize.S16: + case LsSize.U16: + case LsSize.S16: value = context.BitwiseAnd(value, Const(0xffff)); value = context.BitfieldInsert(word, value, bitOffset, Const(16)); break; diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 98a713fb..245b2253 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -9,67 +9,85 @@ namespace Ryujinx.Graphics.Shader.Instructions { static partial class InstEmit { - public static void Mov(EmitterContext context) + public static void MovR(EmitterContext context) { - context.Copy(GetDest(context), GetSrcB(context)); + InstMovR op = context.GetOp(); + + context.Copy(GetDest(op.Dest), GetSrcReg(context, op.SrcA)); } - public static void R2p(EmitterContext context) + public static void MovI(EmitterContext context) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; + InstMovI op = context.GetOp(); - bool isCC = op.RawOpCode.Extract(40); - int shift = op.RawOpCode.Extract(41, 2) * 8; + context.Copy(GetDest(op.Dest), GetSrcImm(context, op.Imm20)); + } - Operand value = GetSrcA(context); - Operand mask = GetSrcB(context); + public static void MovC(EmitterContext context) + { + InstMovC op = context.GetOp(); - Operand Test(Operand value, int bit) - { - return context.ICompareNotEqual(context.BitwiseAnd(value, Const(1 << bit)), Const(0)); - } + context.Copy(GetDest(op.Dest), GetSrcCbuf(context, op.CbufSlot, op.CbufOffset)); + } - if (isCC) - { - // TODO: Support Register to condition code flags copy. - context.Config.GpuAccessor.Log("R2P.CC not implemented."); - } - else - { - for (int bit = 0; bit < 7; bit++) - { - Operand pred = Register(bit, RegisterType.Predicate); + public static void Mov32i(EmitterContext context) + { + InstMov32i op = context.GetOp(); - Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), pred); + context.Copy(GetDest(op.Dest), GetSrcImm(context, op.Imm32)); + } - context.Copy(pred, res); - } - } + public static void R2pR(EmitterContext context) + { + InstR2pR op = context.GetOp(); + + Operand value = GetSrcReg(context, op.SrcA); + Operand mask = GetSrcReg(context, op.SrcB); + + EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); + } + + public static void R2pI(EmitterContext context) + { + InstR2pI op = context.GetOp(); + + Operand value = GetSrcReg(context, op.SrcA); + Operand mask = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); + } + + public static void R2pC(EmitterContext context) + { + InstR2pC op = context.GetOp(); + + Operand value = GetSrcReg(context, op.SrcA); + Operand mask = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitR2p(context, value, mask, op.ByteSel, op.Ccpr); } public static void S2r(EmitterContext context) { - // TODO: Better impl. - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - - SystemRegister sysReg = (SystemRegister)op.RawOpCode.Extract(20, 8); + InstS2r op = context.GetOp(); Operand src; - switch (sysReg) + switch (op.SReg) { - case SystemRegister.LaneId: src = Attribute(AttributeConsts.LaneId); break; - - // TODO: Use value from Y direction GPU register. - case SystemRegister.YDirection: src = ConstF(1); break; - - case SystemRegister.ThreadKill: src = context.Config.Stage == ShaderStage.Fragment - ? Attribute(AttributeConsts.ThreadKill) - : Const(0); + case SReg.LaneId: + src = Attribute(AttributeConsts.LaneId); break; - case SystemRegister.ThreadId: - { + case SReg.YDirection: + src = ConstF(1); // TODO: Use value from Y direction GPU register. + break; + + case SReg.ThreadKill: + src = context.Config.Stage == ShaderStage.Fragment ? Attribute(AttributeConsts.ThreadKill) : Const(0); + break; + + case SReg.TId: Operand tidX = Attribute(AttributeConsts.ThreadIdX); Operand tidY = Attribute(AttributeConsts.ThreadIdY); Operand tidZ = Attribute(AttributeConsts.ThreadIdZ); @@ -78,62 +96,115 @@ namespace Ryujinx.Graphics.Shader.Instructions tidZ = context.ShiftLeft(tidZ, Const(26)); src = context.BitwiseOr(tidX, context.BitwiseOr(tidY, tidZ)); - break; - } - case SystemRegister.ThreadIdX: src = Attribute(AttributeConsts.ThreadIdX); break; - case SystemRegister.ThreadIdY: src = Attribute(AttributeConsts.ThreadIdY); break; - case SystemRegister.ThreadIdZ: src = Attribute(AttributeConsts.ThreadIdZ); break; - case SystemRegister.CtaIdX: src = Attribute(AttributeConsts.CtaIdX); break; - case SystemRegister.CtaIdY: src = Attribute(AttributeConsts.CtaIdY); break; - case SystemRegister.CtaIdZ: src = Attribute(AttributeConsts.CtaIdZ); break; - case SystemRegister.EqMask: src = Attribute(AttributeConsts.EqMask); break; - case SystemRegister.LtMask: src = Attribute(AttributeConsts.LtMask); break; - case SystemRegister.LeMask: src = Attribute(AttributeConsts.LeMask); break; - case SystemRegister.GtMask: src = Attribute(AttributeConsts.GtMask); break; - case SystemRegister.GeMask: src = Attribute(AttributeConsts.GeMask); break; + case SReg.TIdX: + src = Attribute(AttributeConsts.ThreadIdX); + break; + case SReg.TIdY: + src = Attribute(AttributeConsts.ThreadIdY); + break; + case SReg.TIdZ: + src = Attribute(AttributeConsts.ThreadIdZ); + break; - default: src = Const(0); break; + case SReg.CtaIdX: + src = Attribute(AttributeConsts.CtaIdX); + break; + case SReg.CtaIdY: + src = Attribute(AttributeConsts.CtaIdY); + break; + case SReg.CtaIdZ: + src = Attribute(AttributeConsts.CtaIdZ); + break; + + case SReg.EqMask: + src = Attribute(AttributeConsts.EqMask); + break; + case SReg.LtMask: + src = Attribute(AttributeConsts.LtMask); + break; + case SReg.LeMask: + src = Attribute(AttributeConsts.LeMask); + break; + case SReg.GtMask: + src = Attribute(AttributeConsts.GtMask); + break; + case SReg.GeMask: + src = Attribute(AttributeConsts.GeMask); + break; + + default: + src = Const(0); + break; } - context.Copy(GetDest(context), src); + context.Copy(GetDest(op.Dest), src); } - public static void Sel(EmitterContext context) + public static void SelR(EmitterContext context) { - Operand pred = GetPredicate39(context); + InstSelR op = context.GetOp(); - Operand srcA = GetSrcA(context); - Operand srcB = GetSrcB(context); + Operand srcA = GetSrcReg(context, op.SrcA); + Operand srcB = GetSrcReg(context, op.SrcB); + Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - Operand res = context.ConditionalSelect(pred, srcA, srcB); - - context.Copy(GetDest(context), res); + EmitSel(context, srcA, srcB, srcPred, op.Dest); } - public static void Shfl(EmitterContext context) + public static void SelI(EmitterContext context) { - OpCodeShuffle op = (OpCodeShuffle)context.CurrOp; + InstSelI op = context.GetOp(); - Operand pred = Register(op.Predicate48); + Operand srcA = GetSrcReg(context, op.SrcA); + Operand srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); - Operand srcA = GetSrcA(context); + EmitSel(context, srcA, srcB, srcPred, op.Dest); + } - Operand srcB = op.IsBImmediate ? Const(op.ImmediateB) : Register(op.Rb); - Operand srcC = op.IsCImmediate ? Const(op.ImmediateC) : Register(op.Rc); + public static void SelC(EmitterContext context) + { + InstSelC op = context.GetOp(); - (Operand res, Operand valid) = op.ShuffleType switch + Operand srcA = GetSrcReg(context, op.SrcA); + Operand srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + EmitSel(context, srcA, srcB, srcPred, op.Dest); + } + + private static void EmitR2p(EmitterContext context, Operand value, Operand mask, ByteSel byteSel, bool ccpr) + { + Operand Test(Operand value, int bit) { - ShuffleType.Indexed => context.Shuffle(srcA, srcB, srcC), - ShuffleType.Up => context.ShuffleUp(srcA, srcB, srcC), - ShuffleType.Down => context.ShuffleDown(srcA, srcB, srcC), - ShuffleType.Butterfly => context.ShuffleXor(srcA, srcB, srcC), - _ => (null, null) - }; + return context.ICompareNotEqual(context.BitwiseAnd(value, Const(1 << bit)), Const(0)); + } - context.Copy(GetDest(context), res); - context.Copy(pred, valid); + if (ccpr) + { + // TODO: Support Register to condition code flags copy. + context.Config.GpuAccessor.Log("R2P.CC not implemented."); + } + else + { + int shift = (int)byteSel * 8; + + for (int bit = 0; bit < RegisterConsts.PredsCount; bit++) + { + Operand pred = Register(bit, RegisterType.Predicate); + Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), pred); + context.Copy(pred, res); + } + } + } + + private static void EmitSel(EmitterContext context, Operand srcA, Operand srcB, Operand srcPred, int rd) + { + Operand res = context.ConditionalSelect(srcPred, srcA, srcB); + + context.Copy(GetDest(rd), res); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs new file mode 100644 index 00000000..465024eb --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMultifunction.cs @@ -0,0 +1,85 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void RroR(EmitterContext context) + { + InstRroR op = context.GetOp(); + + EmitRro(context, GetSrcReg(context, op.SrcB), op.Dest, op.AbsB, op.NegB); + } + + public static void RroI(EmitterContext context) + { + InstRroI op = context.GetOp(); + + EmitRro(context, GetSrcImm(context, Imm20ToFloat(op.Imm20)), op.Dest, op.AbsB, op.NegB); + } + + public static void RroC(EmitterContext context) + { + InstRroC op = context.GetOp(); + + EmitRro(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.AbsB, op.NegB); + } + + public static void Mufu(EmitterContext context) + { + InstMufu op = context.GetOp(); + + Operand res = context.FPAbsNeg(GetSrcReg(context, op.SrcA), op.AbsA, op.NegA); + + switch (op.MufuOp) + { + case MufuOp.Cos: + res = context.FPCosine(res); + break; + + case MufuOp.Sin: + res = context.FPSine(res); + break; + + case MufuOp.Ex2: + res = context.FPExponentB2(res); + break; + + case MufuOp.Lg2: + res = context.FPLogarithmB2(res); + break; + + case MufuOp.Rcp: + res = context.FPReciprocal(res); + break; + + case MufuOp.Rsq: + res = context.FPReciprocalSquareRoot(res); + break; + + case MufuOp.Sqrt: + res = context.FPSquareRoot(res); + break; + + default: /* TODO */ break; + } + + context.Copy(GetDest(op.Dest), context.FPSaturate(res, op.Sat)); + } + + private static void EmitRro(EmitterContext context, Operand srcB, int rd, bool absB, bool negB) + { + // This is the range reduction operator, + // we translate it as a simple move, as it + // should be always followed by a matching + // MUFU instruction. + srcB = context.FPAbsNeg(srcB, absB, negB); + + context.Copy(GetDest(rd), srcB); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs new file mode 100644 index 00000000..01144007 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitNop.cs @@ -0,0 +1,15 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.Translation; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Nop(EmitterContext context) + { + InstNop op = context.GetOp(); + + // No operation. + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs new file mode 100644 index 00000000..d605661f --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs @@ -0,0 +1,54 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Pset(EmitterContext context) + { + InstPset op = context.GetOp(); + + Operand srcA = context.BitwiseNot(Register(op.Src2Pred, RegisterType.Predicate), op.Src2PredInv); + Operand srcB = context.BitwiseNot(Register(op.Src1Pred, RegisterType.Predicate), op.Src1PredInv); + Operand srcC = context.BitwiseNot(Register(op.SrcPred, RegisterType.Predicate), op.SrcPredInv); + + Operand res = GetPredLogicalOp(context, op.BoolOpAB, srcA, srcB); + res = GetPredLogicalOp(context, op.BoolOpC, res, srcC); + + Operand dest = GetDest(op.Dest); + + if (op.BVal) + { + context.Copy(dest, context.ConditionalSelect(res, ConstF(1), Const(0))); + } + else + { + context.Copy(dest, res); + } + } + + public static void Psetp(EmitterContext context) + { + InstPsetp op = context.GetOp(); + + Operand srcA = context.BitwiseNot(Register(op.Src2Pred, RegisterType.Predicate), op.Src2PredInv); + Operand srcB = context.BitwiseNot(Register(op.Src1Pred, RegisterType.Predicate), op.Src1PredInv); + + Operand p0Res = GetPredLogicalOp(context, op.BoolOpAB, srcA, srcB); + Operand p1Res = context.BitwiseNot(p0Res); + Operand srcPred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + + p0Res = GetPredLogicalOp(context, op.BoolOpC, p0Res, srcPred); + p1Res = GetPredLogicalOp(context, op.BoolOpC, p1Res, srcPred); + + context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); + context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs new file mode 100644 index 00000000..ca053ab6 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitShift.cs @@ -0,0 +1,132 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void ShlR(EmitterContext context) + { + InstShlR op = context.GetOp(); + + EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcReg(context, op.SrcB), op.Dest, op.M); + } + + public static void ShlI(EmitterContext context) + { + InstShlI op = context.GetOp(); + + EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.M); + } + + public static void ShlC(EmitterContext context) + { + InstShlC op = context.GetOp(); + + EmitShl(context, GetSrcReg(context, op.SrcA), GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.M); + } + + public static void ShrR(EmitterContext context) + { + InstShrR op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcReg(context, op.SrcB); + + EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); + } + + public static void ShrI(EmitterContext context) + { + InstShrI op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20)); + + EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); + } + + public static void ShrC(EmitterContext context) + { + InstShrC op = context.GetOp(); + + var srcA = GetSrcReg(context, op.SrcA); + var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitShr(context, srcA, srcB, op.Dest, op.M, op.Brev, op.Signed); + } + + private static void EmitShl(EmitterContext context, Operand srcA, Operand srcB, int rd, bool mask) + { + if (mask) + { + srcB = context.BitwiseAnd(srcB, Const(0x1f)); + } + + Operand res = context.ShiftLeft(srcA, srcB); + + if (!mask) + { + // Clamped shift value. + Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); + + res = context.ConditionalSelect(isLessThan32, res, Const(0)); + } + + // TODO: X, CC. + + context.Copy(GetDest(rd), res); + } + + private static void EmitShr( + EmitterContext context, + Operand srcA, + Operand srcB, + int rd, + bool mask, + bool bitReverse, + bool isSigned) + { + if (bitReverse) + { + srcA = context.BitfieldReverse(srcA); + } + + if (mask) + { + srcB = context.BitwiseAnd(srcB, Const(0x1f)); + } + + Operand res = isSigned + ? context.ShiftRightS32(srcA, srcB) + : context.ShiftRightU32(srcA, srcB); + + if (!mask) + { + // Clamped shift value. + Operand resShiftBy32; + + if (isSigned) + { + resShiftBy32 = context.ShiftRightS32(srcA, Const(31)); + } + else + { + resShiftBy32 = Const(0); + } + + Operand isLessThan32 = context.ICompareLessUnsigned(srcB, Const(32)); + + res = context.ConditionalSelect(isLessThan32, res, resShiftBy32); + } + + // TODO: X, CC. + + context.Copy(GetDest(rd), res); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs new file mode 100644 index 00000000..a47d6650 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitSurface.cs @@ -0,0 +1,776 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; +using System.Collections.Generic; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void SuatomB(EmitterContext context) + { + InstSuatomB op = context.GetOp(); + + EmitSuatom( + context, + op.Dim, + op.Op, + op.Size, + 0, + op.SrcA, + op.SrcB, + op.SrcC, + op.Dest, + op.Ba, + isBindless: true, + compareAndSwap: false); + } + + public static void Suatom(EmitterContext context) + { + InstSuatom op = context.GetOp(); + + EmitSuatom( + context, + op.Dim, + op.Op, + op.Size, + op.TidB, + op.SrcA, + op.SrcB, + 0, + op.Dest, + op.Ba, + isBindless: false, + compareAndSwap: false); + } + + public static void SuatomB2(EmitterContext context) + { + InstSuatomB2 op = context.GetOp(); + + EmitSuatom( + context, + op.Dim, + op.Op, + op.Size, + 0, + op.SrcA, + op.SrcB, + op.SrcC, + op.Dest, + op.Ba, + isBindless: true, + compareAndSwap: false); + } + + public static void SuatomCasB(EmitterContext context) + { + InstSuatomCasB op = context.GetOp(); + + EmitSuatom( + context, + op.Dim, + 0, + op.Size, + 0, + op.SrcA, + op.SrcB, + op.SrcC, + op.Dest, + op.Ba, + isBindless: true, + compareAndSwap: true); + } + + public static void SuatomCas(EmitterContext context) + { + InstSuatomCas op = context.GetOp(); + + EmitSuatom( + context, + op.Dim, + 0, + op.Size, + op.TidB, + op.SrcA, + op.SrcB, + 0, + op.Dest, + op.Ba, + isBindless: false, + compareAndSwap: true); + } + + public static void SuldDB(EmitterContext context) + { + InstSuldDB op = context.GetOp(); + + EmitSuld(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true); + } + + public static void SuldD(EmitterContext context) + { + InstSuldD op = context.GetOp(); + + EmitSuld(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false); + } + + public static void SuldB(EmitterContext context) + { + InstSuldB op = context.GetOp(); + + EmitSuld(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true); + } + + public static void Suld(EmitterContext context) + { + InstSuld op = context.GetOp(); + + EmitSuld(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false); + } + + public static void SuredB(EmitterContext context) + { + InstSuredB op = context.GetOp(); + + EmitSured(context, op.Dim, op.Op, op.Size, 0, op.SrcA, op.Dest, op.SrcC, op.Ba, isBindless: true); + } + + public static void Sured(EmitterContext context) + { + InstSured op = context.GetOp(); + + EmitSured(context, op.Dim, op.Op, op.Size, op.TidB, op.SrcA, op.Dest, 0, op.Ba, isBindless: false); + } + + public static void SustDB(EmitterContext context) + { + InstSustDB op = context.GetOp(); + + EmitSust(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true); + } + + public static void SustD(EmitterContext context) + { + InstSustD op = context.GetOp(); + + EmitSust(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false); + } + + public static void SustB(EmitterContext context) + { + InstSustB op = context.GetOp(); + + EmitSust(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true); + } + + public static void Sust(EmitterContext context) + { + InstSust op = context.GetOp(); + + EmitSust(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false); + } + + private static void EmitSuatom( + EmitterContext context, + SuDim dimensions, + SuatomOp atomicOp, + SuatomSize size, + int imm, + int srcA, + int srcB, + int srcC, + int dest, + bool byteAddress, + bool isBindless, + bool compareAndSwap) + { + SamplerType type = ConvertSamplerType(dimensions); + + if (type == SamplerType.None) + { + context.Config.GpuAccessor.Log("Invalid image atomic sampler type."); + return; + } + + Operand Ra() + { + if (srcA > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcA++, RegisterType.Gpr)); + } + + Operand Rb() + { + if (srcB > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcB++, RegisterType.Gpr)); + } + + Operand GetDest() + { + if (dest > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return Register(dest++, RegisterType.Gpr); + } + + List sourcesList = new List(); + + if (isBindless) + { + sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); + } + + int coordsCount = type.GetDimensions(); + + for (int index = 0; index < coordsCount; index++) + { + sourcesList.Add(Ra()); + } + + if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) + { + sourcesList.Add(Const(0)); + + type &= ~SamplerType.Mask; + type |= SamplerType.Texture2D; + } + + if (type.HasFlag(SamplerType.Array)) + { + sourcesList.Add(Ra()); + + type |= SamplerType.Array; + } + + if (byteAddress) + { + int xIndex = isBindless ? 1 : 0; + + sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); + } + + // TODO: FP and 64-bit formats. + TextureFormat format = !isBindless && (size == SuatomSize.Sd32 || size == SuatomSize.Sd64) + ? context.Config.GetTextureFormatAtomic(imm) + : GetTextureFormat(size); + + if (compareAndSwap) + { + sourcesList.Add(Rb()); + } + + sourcesList.Add(Rb()); + + Operand[] sources = sourcesList.ToArray(); + + TextureFlags flags = compareAndSwap ? TextureFlags.CAS : GetAtomicOpFlags(atomicOp); + + if (isBindless) + { + flags |= TextureFlags.Bindless; + } + + TextureOperation operation = context.CreateTextureOperation( + Instruction.ImageAtomic, + type, + format, + flags, + imm, + 0, + GetDest(), + sources); + + context.Add(operation); + } + + private static void EmitSuld( + EmitterContext context, + SuDim dimensions, + SuSize size, + int imm, + SuRgba componentMask, + int srcA, + int srcB, + int srcC, + bool useComponents, + bool byteAddress, + bool isBindless) + { + context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); + + SamplerType type = ConvertSamplerType(dimensions); + + if (type == SamplerType.None) + { + context.Config.GpuAccessor.Log("Invalid image store sampler type."); + return; + } + + Operand Ra() + { + if (srcA > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcA++, RegisterType.Gpr)); + } + + List sourcesList = new List(); + + if (isBindless) + { + sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); + } + + int coordsCount = type.GetDimensions(); + + for (int index = 0; index < coordsCount; index++) + { + sourcesList.Add(Ra()); + } + + if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) + { + sourcesList.Add(Const(0)); + + type &= ~SamplerType.Mask; + type |= SamplerType.Texture2D; + } + + if (type.HasFlag(SamplerType.Array)) + { + sourcesList.Add(Ra()); + } + + Operand[] sources = sourcesList.ToArray(); + + int handle = imm; + + TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; + + if (useComponents) + { + for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + { + if ((compMask & 1) == 0) + { + continue; + } + + if (srcB == RegisterConsts.RegisterZeroIndex) + { + break; + } + + Operand rd = Register(srcB++, RegisterType.Gpr); + + TextureOperation operation = context.CreateTextureOperation( + Instruction.ImageLoad, + type, + flags, + handle, + compIndex, + rd, + sources); + + if (!isBindless) + { + operation.Format = context.Config.GetTextureFormat(handle); + } + + context.Add(operation); + } + } + else + { + if (byteAddress) + { + int xIndex = isBindless ? 1 : 0; + + sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(size))); + } + + int components = GetComponents(size); + + for (int compIndex = 0; compIndex < components; compIndex++) + { + if (srcB == RegisterConsts.RegisterZeroIndex) + { + break; + } + + Operand rd = Register(srcB++, RegisterType.Gpr); + + TextureOperation operation = context.CreateTextureOperation( + Instruction.ImageLoad, + type, + GetTextureFormat(size), + flags, + handle, + compIndex, + rd, + sources); + + context.Add(operation); + + switch (size) + { + case SuSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break; + case SuSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break; + case SuSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break; + case SuSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break; + } + } + } + } + + private static void EmitSured( + EmitterContext context, + SuDim dimensions, + RedOp atomicOp, + SuatomSize size, + int imm, + int srcA, + int srcB, + int srcC, + bool byteAddress, + bool isBindless) + { + SamplerType type = ConvertSamplerType(dimensions); + + if (type == SamplerType.None) + { + context.Config.GpuAccessor.Log("Invalid image reduction sampler type."); + return; + } + + Operand Ra() + { + if (srcA > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcA++, RegisterType.Gpr)); + } + + Operand Rb() + { + if (srcB > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcB++, RegisterType.Gpr)); + } + + List sourcesList = new List(); + + if (isBindless) + { + sourcesList.Add(context.Copy(GetSrcReg(context, srcC))); + } + + int coordsCount = type.GetDimensions(); + + for (int index = 0; index < coordsCount; index++) + { + sourcesList.Add(Ra()); + } + + if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) + { + sourcesList.Add(Const(0)); + + type &= ~SamplerType.Mask; + type |= SamplerType.Texture2D; + } + + if (type.HasFlag(SamplerType.Array)) + { + sourcesList.Add(Ra()); + + type |= SamplerType.Array; + } + + if (byteAddress) + { + int xIndex = isBindless ? 1 : 0; + + sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); + } + + // TODO: FP and 64-bit formats. + TextureFormat format = !isBindless && (size == SuatomSize.Sd32 || size == SuatomSize.Sd64) + ? context.Config.GetTextureFormatAtomic(imm) + : GetTextureFormat(size); + + sourcesList.Add(Rb()); + + Operand[] sources = sourcesList.ToArray(); + + TextureFlags flags = GetAtomicOpFlags((SuatomOp)atomicOp); + + if (isBindless) + { + flags |= TextureFlags.Bindless; + } + + TextureOperation operation = context.CreateTextureOperation( + Instruction.ImageAtomic, + type, + format, + flags, + imm, + 0, + null, + sources); + + context.Add(operation); + } + + private static void EmitSust( + EmitterContext context, + SuDim dimensions, + SuSize size, + int imm, + SuRgba componentMask, + int srcA, + int srcB, + int srcC, + bool useComponents, + bool byteAddress, + bool isBindless) + { + SamplerType type = ConvertSamplerType(dimensions); + + if (type == SamplerType.None) + { + context.Config.GpuAccessor.Log("Invalid image store sampler type."); + return; + } + + Operand Ra() + { + if (srcA > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcA++, RegisterType.Gpr)); + } + + Operand Rb() + { + if (srcB > RegisterConsts.RegisterZeroIndex) + { + return Const(0); + } + + return context.Copy(Register(srcB++, RegisterType.Gpr)); + } + + List sourcesList = new List(); + + if (isBindless) + { + sourcesList.Add(context.Copy(Register(srcC, RegisterType.Gpr))); + } + + int coordsCount = type.GetDimensions(); + + for (int index = 0; index < coordsCount; index++) + { + sourcesList.Add(Ra()); + } + + if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) + { + sourcesList.Add(Const(0)); + + type &= ~SamplerType.Mask; + type |= SamplerType.Texture2D; + } + + if (type.HasFlag(SamplerType.Array)) + { + sourcesList.Add(Ra()); + } + + TextureFormat format = TextureFormat.Unknown; + + if (useComponents) + { + for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + { + if ((compMask & 1) != 0) + { + sourcesList.Add(Rb()); + } + } + + if (!isBindless) + { + format = context.Config.GetTextureFormat(imm); + } + } + else + { + if (byteAddress) + { + int xIndex = isBindless ? 1 : 0; + + sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(size))); + } + + int components = GetComponents(size); + + for (int compIndex = 0; compIndex < components; compIndex++) + { + sourcesList.Add(Rb()); + } + + format = GetTextureFormat(size); + } + + Operand[] sources = sourcesList.ToArray(); + + int handle = imm; + + TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; + + TextureOperation operation = context.CreateTextureOperation( + Instruction.ImageStore, + type, + format, + flags, + handle, + 0, + null, + sources); + + context.Add(operation); + } + + private static int GetComponentSizeInBytesLog2(SuatomSize size) + { + return size switch + { + SuatomSize.U32 => 2, + SuatomSize.S32 => 2, + SuatomSize.U64 => 3, + SuatomSize.F32FtzRn => 2, + SuatomSize.F16x2FtzRn => 2, + SuatomSize.S64 => 3, + SuatomSize.Sd32 => 2, + SuatomSize.Sd64 => 3, + _ => 2 + }; + } + + private static TextureFormat GetTextureFormat(SuatomSize size) + { + return size switch + { + SuatomSize.U32 => TextureFormat.R32Uint, + SuatomSize.S32 => TextureFormat.R32Sint, + SuatomSize.U64 => TextureFormat.R32G32Uint, + SuatomSize.F32FtzRn => TextureFormat.R32Float, + SuatomSize.F16x2FtzRn => TextureFormat.R16G16Float, + SuatomSize.S64 => TextureFormat.R32G32Uint, + SuatomSize.Sd32 => TextureFormat.R32Uint, + SuatomSize.Sd64 => TextureFormat.R32G32Uint, + _ => TextureFormat.R32Uint + }; + } + + private static TextureFlags GetAtomicOpFlags(SuatomOp op) + { + return op switch + { + SuatomOp.Add => TextureFlags.Add, + SuatomOp.Min => TextureFlags.Minimum, + SuatomOp.Max => TextureFlags.Maximum, + SuatomOp.Inc => TextureFlags.Increment, + SuatomOp.Dec => TextureFlags.Decrement, + SuatomOp.And => TextureFlags.BitwiseAnd, + SuatomOp.Or => TextureFlags.BitwiseOr, + SuatomOp.Xor => TextureFlags.BitwiseXor, + SuatomOp.Exch => TextureFlags.Swap, + _ => TextureFlags.Add + }; + } + + private static int GetComponents(SuSize size) + { + return size switch + { + SuSize.B64 => 2, + SuSize.B128 => 4, + SuSize.UB128 => 4, + _ => 1 + }; + } + + private static int GetComponentSizeInBytesLog2(SuSize size) + { + return size switch + { + SuSize.U8 => 0, + SuSize.S8 => 0, + SuSize.U16 => 1, + SuSize.S16 => 1, + SuSize.B32 => 2, + SuSize.B64 => 3, + SuSize.B128 => 4, + SuSize.UB128 => 4, + _ => 2 + }; + } + + private static TextureFormat GetTextureFormat(SuSize size) + { + return size switch + { + SuSize.U8 => TextureFormat.R8Uint, + SuSize.S8 => TextureFormat.R8Sint, + SuSize.U16 => TextureFormat.R16Uint, + SuSize.S16 => TextureFormat.R16Sint, + SuSize.B32 => TextureFormat.R32Uint, + SuSize.B64 => TextureFormat.R32G32Uint, + SuSize.B128 => TextureFormat.R32G32B32A32Uint, + SuSize.UB128 => TextureFormat.R32G32B32A32Uint, + _ => TextureFormat.R32Uint + }; + } + + private static SamplerType ConvertSamplerType(SuDim target) + { + return target switch + { + SuDim._1d => SamplerType.Texture1D, + SuDim._1dBuffer => SamplerType.TextureBuffer, + SuDim._1dArray => SamplerType.Texture1D | SamplerType.Array, + SuDim._2d => SamplerType.Texture2D, + SuDim._2dArray => SamplerType.Texture2D | SamplerType.Array, + SuDim._3d => SamplerType.Texture3D, + _ => SamplerType.None + }; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 88bafd76..ba1fdf17 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -4,173 +4,181 @@ using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Generic; -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; namespace Ryujinx.Graphics.Shader.Instructions { static partial class InstEmit { + private static readonly int[,] _maskLut = new int[,] + { + { 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b1001, 0b1010, 0b1100 }, + { 0b0111, 0b1011, 0b1101, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000 } + }; + private const bool Sample1DAs2D = true; - public static void Suld(EmitterContext context) + private enum TexsType { + Texs, + Tlds, + Tld4s + } + + public static void Tex(EmitterContext context) + { + InstTex op = context.GetOp(); + + EmitTex(context, TextureFlags.None, op.Dim, op.Lod, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, false, op.Dc, op.Aoffi); + } + + public static void TexB(EmitterContext context) + { + InstTexB op = context.GetOp(); + + EmitTex(context, TextureFlags.Bindless, op.Dim, op.Lodb, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, false, op.Dc, op.Aoffib); + } + + public static void Texs(EmitterContext context) + { + InstTexs op = context.GetOp(); + + EmitTexs(context, TexsType.Texs, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); + } + + public static void TexsF16(EmitterContext context) + { + InstTexs op = context.GetOp(); + + EmitTexs(context, TexsType.Texs, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); + } + + public static void Tld(EmitterContext context) + { + InstTld op = context.GetOp(); + context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - OpCodeImage op = (OpCodeImage)context.CurrOp; + var lod = op.Lod ? Lod.Ll : Lod.Lz; - SamplerType type = ConvertSamplerType(op.Dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image store sampler type."); - - return; - } - - // Rb is Rd on the SULD instruction. - int rdIndex = op.Rb.Index; - int raIndex = op.Ra.Index; - - Operand Ra() - { - if (raIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(raIndex++, RegisterType.Gpr)); - } - - List sourcesList = new List(); - - if (op.IsBindless) - { - sourcesList.Add(context.Copy(Register(op.Rc))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; - } - - Operand[] sources = sourcesList.ToArray(); - - int handle = !op.IsBindless ? op.HandleOffset : 0; - - TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None; - - if (op.UseComponents) - { - int componentMask = (int)op.Components; - - for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) == 0) - { - continue; - } - - if (rdIndex == RegisterConsts.RegisterZeroIndex) - { - break; - } - - Operand rd = Register(rdIndex++, RegisterType.Gpr); - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageLoad, - type, - flags, - handle, - compIndex, - rd, - sources); - - if (!op.IsBindless) - { - operation.Format = context.Config.GetTextureFormat(handle); - } - - context.Add(operation); - } - } - else - { - if (op.ByteAddress) - { - int xIndex = op.IsBindless ? 1 : 0; - - sources[xIndex] = context.ShiftRightS32(sources[xIndex], Const(GetComponentSizeInBytesLog2(op.Size))); - } - - int components = GetComponents(op.Size); - - for (int compIndex = 0; compIndex < components; compIndex++) - { - if (rdIndex == RegisterConsts.RegisterZeroIndex) - { - break; - } - - Operand rd = Register(rdIndex++, RegisterType.Gpr); - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageLoad, - type, - GetTextureFormat(op.Size), - flags, - handle, - compIndex, - rd, - sources); - - context.Add(operation); - - switch (op.Size) - { - case IntegerSize.U8: context.Copy(rd, ZeroExtendTo32(context, rd, 8)); break; - case IntegerSize.U16: context.Copy(rd, ZeroExtendTo32(context, rd, 16)); break; - case IntegerSize.S8: context.Copy(rd, SignExtendTo32(context, rd, 8)); break; - case IntegerSize.S16: context.Copy(rd, SignExtendTo32(context, rd, 16)); break; - } - } - } + EmitTex(context, TextureFlags.IntCoords, op.Dim, lod, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Ms, false, op.Toff); } - public static void Sust(EmitterContext context) + public static void TldB(EmitterContext context) { - OpCodeImage op = (OpCodeImage)context.CurrOp; + InstTldB op = context.GetOp(); - SamplerType type = ConvertSamplerType(op.Dimensions); + context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - if (type == SamplerType.None) + var flags = TextureFlags.IntCoords | TextureFlags.Bindless; + var lod = op.Lod ? Lod.Ll : Lod.Lz; + + EmitTex(context, flags, op.Dim, lod, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Ms, false, op.Toff); + } + + public static void Tlds(EmitterContext context) + { + InstTlds op = context.GetOp(); + + EmitTexs(context, TexsType.Tlds, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); + } + + public static void TldsF16(EmitterContext context) + { + InstTlds op = context.GetOp(); + + EmitTexs(context, TexsType.Tlds, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); + } + + public static void Tld4(EmitterContext context) + { + InstTld4 op = context.GetOp(); + + EmitTld4(context, op.Dim, op.TexComp, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, op.Dc, isBindless: false); + } + + public static void Tld4B(EmitterContext context) + { + InstTld4B op = context.GetOp(); + + EmitTld4(context, op.Dim, op.TexComp, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, op.Dc, isBindless: true); + } + + public static void Tld4s(EmitterContext context) + { + InstTld4s op = context.GetOp(); + + EmitTexs(context, TexsType.Tld4s, op.TidB, 4, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: false); + } + + public static void Tld4sF16(EmitterContext context) + { + InstTld4s op = context.GetOp(); + + EmitTexs(context, TexsType.Tld4s, op.TidB, 4, op.SrcA, op.SrcB, op.Dest, op.Dest2, isF16: true); + } + + public static void Tmml(EmitterContext context) + { + InstTmml op = context.GetOp(); + + EmitTmml(context, op.Dim, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, isBindless: false); + } + + public static void TmmlB(EmitterContext context) + { + InstTmmlB op = context.GetOp(); + + EmitTmml(context, op.Dim, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, isBindless: true); + } + + public static void Txd(EmitterContext context) + { + InstTxd op = context.GetOp(); + + EmitTxd(context, op.Dim, op.TidB, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, isBindless: false); + } + + public static void TxdB(EmitterContext context) + { + InstTxdB op = context.GetOp(); + + EmitTxd(context, op.Dim, 0, op.WMask, op.SrcA, op.SrcB, op.Dest, op.Toff, isBindless: true); + } + + public static void Txq(EmitterContext context) + { + InstTxq op = context.GetOp(); + + EmitTxq(context, op.TexQuery, op.TidB, op.WMask, op.SrcA, op.Dest, isBindless: false); + } + + public static void TxqB(EmitterContext context) + { + InstTxqB op = context.GetOp(); + + EmitTxq(context, op.TexQuery, 0, op.WMask, op.SrcA, op.Dest, isBindless: true); + } + + private static void EmitTex( + EmitterContext context, + TextureFlags flags, + TexDim dimensions, + Lod lodMode, + int imm, + int componentMask, + int raIndex, + int rbIndex, + int rdIndex, + bool isMultisample, + bool hasDepthCompare, + bool hasOffset) + { + if (rdIndex == RegisterConsts.RegisterZeroIndex) { - context.Config.GpuAccessor.Log("Invalid image store sampler type."); - return; } - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - Operand Ra() { if (raIndex > RegisterConsts.RegisterZeroIndex) @@ -191,11 +199,36 @@ namespace Ryujinx.Graphics.Shader.Instructions return context.Copy(Register(rbIndex++, RegisterType.Gpr)); } + SamplerType type = ConvertSamplerType(dimensions); + + bool isArray = type.HasFlag(SamplerType.Array); + bool isBindless = flags.HasFlag(TextureFlags.Bindless); + + Operand arrayIndex = isArray ? Ra() : null; + List sourcesList = new List(); - if (op.IsBindless) + if (isBindless) { - sourcesList.Add(context.Copy(Register(op.Rc))); + sourcesList.Add(Rb()); + } + + bool hasLod = lodMode > Lod.Lz; + + if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !( + hasLod || + hasDepthCompare || + hasOffset || + isArray || + isMultisample)) + { + // For bindless, we don't have any way to know the texture type, + // so we assume it's texture buffer when the sampler type is 1D, since that's more common. + bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QuerySamplerType(imm) == SamplerType.TextureBuffer; + if (isTypeBuffer) + { + type = SamplerType.TextureBuffer; + } } int coordsCount = type.GetDimensions(); @@ -205,229 +238,72 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Ra()); } - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; - } - - TextureFormat format = TextureFormat.Unknown; - - if (op.UseComponents) - { - int componentMask = (int)op.Components; - - for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) != 0) - { - sourcesList.Add(Rb()); - } - } - - if (!op.IsBindless) - { - format = context.Config.GetTextureFormat(op.HandleOffset); - } - } - else - { - if (op.ByteAddress) - { - int xIndex = op.IsBindless ? 1 : 0; - - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Size))); - } - - int components = GetComponents(op.Size); - - for (int compIndex = 0; compIndex < components; compIndex++) - { - sourcesList.Add(Rb()); - } - - format = GetTextureFormat(op.Size); - } - - Operand[] sources = sourcesList.ToArray(); - - int handle = !op.IsBindless ? op.HandleOffset : 0; - - TextureFlags flags = op.IsBindless ? TextureFlags.Bindless : TextureFlags.None; - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageStore, - type, - format, - flags, - handle, - 0, - null, - sources); - - context.Add(operation); - } - - public static void Sured(EmitterContext context) - { - OpCodeSured op = (OpCodeSured)context.CurrOp; - - SamplerType type = ConvertSamplerType(op.Dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image reduction sampler type."); - - return; - } - - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - - Operand Ra() - { - if (raIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(raIndex++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (rbIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); - } - - List sourcesList = new List(); - - if (op.IsBindless) - { - sourcesList.Add(context.Copy(Register(op.Rc))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } + bool is1DTo2D = false; if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) { - sourcesList.Add(Const(0)); + sourcesList.Add(ConstF(0)); - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; + type = SamplerType.Texture2D | (type & SamplerType.Array); + is1DTo2D = true; } - if (type.HasFlag(SamplerType.Array)) + if (isArray) { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; + sourcesList.Add(arrayIndex); } - TextureFormat format = TextureFormat.R32Sint; + Operand lodValue = hasLod ? Rb() : ConstF(0); - if (op.UseType) + Operand packedOffs = hasOffset ? Rb() : null; + + if (hasDepthCompare) { - if (op.ByteAddress) + sourcesList.Add(Rb()); + + type |= SamplerType.Shadow; + } + + if ((lodMode == Lod.Lz || + lodMode == Lod.Ll || + lodMode == Lod.Lla) && !isMultisample && type != SamplerType.TextureBuffer) + { + sourcesList.Add(lodValue); + + flags |= TextureFlags.LodLevel; + } + + if (hasOffset) + { + for (int index = 0; index < coordsCount; index++) { - int xIndex = op.IsBindless ? 1 : 0; - - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Type))); + sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4))); } - // TODO: FP and 64-bit formats. - format = (op.Type == ReductionType.SD32 || op.Type == ReductionType.SD64) ? - context.Config.GetTextureFormatAtomic(op.HandleOffset) : - GetTextureFormat(op.Type); - } - else if (!op.IsBindless) - { - format = context.Config.GetTextureFormatAtomic(op.HandleOffset); + if (is1DTo2D) + { + sourcesList.Add(Const(0)); + } + + flags |= TextureFlags.Offset; } - sourcesList.Add(Rb()); + if (lodMode == Lod.Lb || lodMode == Lod.Lba) + { + sourcesList.Add(lodValue); + + flags |= TextureFlags.LodBias; + } + + if (isMultisample) + { + sourcesList.Add(Rb()); + + type |= SamplerType.Multisample; + } Operand[] sources = sourcesList.ToArray(); - int handle = op.HandleOffset; - - TextureFlags flags = GetAtomicOpFlags(op.AtomicOp); - - if (op.IsBindless) - { - handle = 0; - flags |= TextureFlags.Bindless; - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageAtomic, - type, - format, - flags, - handle, - 0, - null, - sources); - - context.Add(operation); - } - - public static void Suatom(EmitterContext context) - { - OpCodeSuatom op = (OpCodeSuatom)context.CurrOp; - - SamplerType type = ConvertSamplerType(op.Dimensions); - - if (type == SamplerType.None) - { - context.Config.GpuAccessor.Log("Invalid image atomic sampler type."); - - return; - } - - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - - Operand Ra() - { - if (raIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(raIndex++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (rbIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); - } - - int rdIndex = op.Rd.Index; - Operand GetDest() { if (rdIndex > RegisterConsts.RegisterZeroIndex) @@ -438,144 +314,64 @@ namespace Ryujinx.Graphics.Shader.Instructions return Register(rdIndex++, RegisterType.Gpr); } - List sourcesList = new List(); + int handle = !isBindless ? imm : 0; - if (op.IsBindless) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { - sourcesList.Add(context.Copy(Register(op.Rc))); - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) - { - sourcesList.Add(Const(0)); - - type &= ~SamplerType.Mask; - type |= SamplerType.Texture2D; - } - - if (type.HasFlag(SamplerType.Array)) - { - sourcesList.Add(Ra()); - - type |= SamplerType.Array; - } - - TextureFormat format = TextureFormat.R32Sint; - - if (op.UseType) - { - if (op.ByteAddress) + if ((compMask & 1) != 0) { - int xIndex = op.IsBindless ? 1 : 0; + Operand dest = GetDest(); - sourcesList[xIndex] = context.ShiftRightS32(sourcesList[xIndex], Const(GetComponentSizeInBytesLog2(op.Type))); + TextureOperation operation = context.CreateTextureOperation( + Instruction.TextureSample, + type, + flags, + handle, + compIndex, + dest, + sources); + + context.Add(operation); } - - // TODO: FP and 64-bit formats. - format = (op.Type == ReductionType.SD32 || op.Type == ReductionType.SD64) ? - context.Config.GetTextureFormatAtomic(op.HandleOffset) : - GetTextureFormat(op.Type); } - else if (!op.IsBindless) - { - format = context.Config.GetTextureFormatAtomic(op.HandleOffset); - } - - if (op.CompareAndSwap) - { - sourcesList.Add(Rb()); - } - - sourcesList.Add(Rb()); - - Operand[] sources = sourcesList.ToArray(); - - int handle = op.HandleOffset; - - TextureFlags flags = op.CompareAndSwap ? TextureFlags.CAS : GetAtomicOpFlags(op.AtomicOp); - - if (op.IsBindless) - { - handle = 0; - flags |= TextureFlags.Bindless; - } - - TextureOperation operation = context.CreateTextureOperation( - Instruction.ImageAtomic, - type, - format, - flags, - handle, - 0, - GetDest(), - sources); - - context.Add(operation); } - public static void Tex(EmitterContext context) + private static void EmitTexs( + EmitterContext context, + TexsType texsType, + int imm, + int writeMask, + int srcA, + int srcB, + int dest, + int dest2, + bool isF16) { - EmitTextureSample(context, TextureFlags.None); - } - - public static void TexB(EmitterContext context) - { - EmitTextureSample(context, TextureFlags.Bindless); - } - - public static void Tld(EmitterContext context) - { - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - EmitTextureSample(context, TextureFlags.IntCoords); - } - - public static void TldB(EmitterContext context) - { - context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - - EmitTextureSample(context, TextureFlags.IntCoords | TextureFlags.Bindless); - } - - public static void Texs(EmitterContext context) - { - OpCodeTextureScalar op = (OpCodeTextureScalar)context.CurrOp; - - if (op.Rd0.IsRZ && op.Rd1.IsRZ) + if (dest == RegisterConsts.RegisterZeroIndex && dest2 == RegisterConsts.RegisterZeroIndex) { return; } List sourcesList = new List(); - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - Operand Ra() { - if (raIndex > RegisterConsts.RegisterZeroIndex) + if (srcA > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(raIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcA++, RegisterType.Gpr)); } Operand Rb() { - if (rbIndex > RegisterConsts.RegisterZeroIndex) + if (srcB > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcB++, RegisterType.Gpr)); } void AddTextureOffset(int coordsCount, int stride, int size) @@ -588,17 +384,18 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - SamplerType type; + SamplerType type; TextureFlags flags; - if (op is OpCodeTexs texsOp) + if (texsType == TexsType.Texs) { + var texsOp = context.GetOp(); + type = ConvertSamplerType(texsOp.Target); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("Invalid texture sampler type."); - return; } @@ -630,7 +427,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { switch (texsOp.Target) { - case TextureTarget.Texture1DLodZero: + case TexsTarget.Texture1DLodZero: sourcesList.Add(Ra()); if (Sample1DAs2D) @@ -644,36 +441,36 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(ConstF(0)); break; - case TextureTarget.Texture2D: + case TexsTarget.Texture2D: sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; - case TextureTarget.Texture2DLodZero: + case TexsTarget.Texture2DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; - case TextureTarget.Texture2DLodLevel: - case TextureTarget.Texture2DDepthCompare: - case TextureTarget.Texture3D: - case TextureTarget.TextureCube: + case TexsTarget.Texture2DLodLevel: + case TexsTarget.Texture2DDepthCompare: + case TexsTarget.Texture3D: + case TexsTarget.TextureCube: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; - case TextureTarget.Texture2DLodZeroDepthCompare: - case TextureTarget.Texture3DLodZero: + case TexsTarget.Texture2DLodZeroDepthCompare: + case TexsTarget.Texture3DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(ConstF(0)); break; - case TextureTarget.Texture2DLodLevelDepthCompare: - case TextureTarget.TextureCubeLodLevel: + case TexsTarget.Texture2DLodLevelDepthCompare: + case TexsTarget.TextureCubeLodLevel: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); @@ -682,14 +479,15 @@ namespace Ryujinx.Graphics.Shader.Instructions } } } - else if (op is OpCodeTlds tldsOp) + else if (texsType == TexsType.Tlds) { + var tldsOp = context.GetOp(); + type = ConvertSamplerType(tldsOp.Target); if (type == SamplerType.None) { context.Config.GpuAccessor.Log("Invalid texel fetch sampler type."); - return; } @@ -697,15 +495,16 @@ namespace Ryujinx.Graphics.Shader.Instructions flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords; - if (tldsOp.Target == TexelLoadTarget.Texture1DLodZero && context.Config.GpuAccessor.QuerySamplerType(tldsOp.HandleOffset) == SamplerType.TextureBuffer) + if (tldsOp.Target == TldsTarget.Texture1DLodZero && + context.Config.GpuAccessor.QuerySamplerType(tldsOp.TidB) == SamplerType.TextureBuffer) { - type = SamplerType.TextureBuffer; + type = SamplerType.TextureBuffer; flags &= ~TextureFlags.LodLevel; } switch (tldsOp.Target) { - case TexelLoadTarget.Texture1DLodZero: + case TldsTarget.Texture1DLodZero: sourcesList.Add(Ra()); if (type != SamplerType.TextureBuffer) @@ -722,7 +521,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } break; - case TexelLoadTarget.Texture1DLodLevel: + case TldsTarget.Texture1DLodLevel: sourcesList.Add(Ra()); if (Sample1DAs2D) @@ -736,34 +535,34 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Rb()); break; - case TexelLoadTarget.Texture2DLodZero: + case TldsTarget.Texture2DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(Const(0)); break; - case TexelLoadTarget.Texture2DLodZeroOffset: + case TldsTarget.Texture2DLodZeroOffset: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Const(0)); break; - case TexelLoadTarget.Texture2DLodZeroMultisample: - case TexelLoadTarget.Texture2DLodLevel: - case TexelLoadTarget.Texture2DLodLevelOffset: + case TldsTarget.Texture2DLodZeroMultisample: + case TldsTarget.Texture2DLodLevel: + case TldsTarget.Texture2DLodLevelOffset: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); break; - case TexelLoadTarget.Texture3DLodZero: + case TldsTarget.Texture3DLodZero: sourcesList.Add(Ra()); sourcesList.Add(Ra()); sourcesList.Add(Rb()); sourcesList.Add(Const(0)); break; - case TexelLoadTarget.Texture2DArrayLodZero: + case TldsTarget.Texture2DArrayLodZero: sourcesList.Add(Rb()); sourcesList.Add(Rb()); sourcesList.Add(Ra()); @@ -776,9 +575,11 @@ namespace Ryujinx.Graphics.Shader.Instructions AddTextureOffset(type.GetDimensions(), 4, 4); } } - else if (op is OpCodeTld4s tld4sOp) + else if (texsType == TexsType.Tld4s) { - if (!(tld4sOp.HasDepthCompare || tld4sOp.HasOffset)) + var tld4sOp = context.GetOp(); + + if (!(tld4sOp.Dc || tld4sOp.Aoffi)) { sourcesList.Add(Ra()); sourcesList.Add(Rb()); @@ -789,28 +590,28 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Ra()); } - type = SamplerType.Texture2D; + type = SamplerType.Texture2D; flags = TextureFlags.Gather; - if (tld4sOp.HasDepthCompare) + if (tld4sOp.Dc) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } - if (tld4sOp.HasOffset) + if (tld4sOp.Aoffi) { AddTextureOffset(type.GetDimensions(), 8, 6); flags |= TextureFlags.Offset; } - sourcesList.Add(Const(tld4sOp.GatherCompIndex)); + sourcesList.Add(Const((int)tld4sOp.TexComp)); } else { - throw new InvalidOperationException($"Invalid opcode type \"{op.GetType().Name}\"."); + throw new ArgumentException($"Invalid TEXS type \"{texsType}\"."); } Operand[] sources = sourcesList.ToArray(); @@ -823,11 +624,11 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand GetDest() { int high = destIncrement >> 1; - int low = destIncrement & 1; + int low = destIncrement & 1; destIncrement++; - if (op.IsFp16) + if (isF16) { return high != 0 ? (rd1[low] = Local()) @@ -835,7 +636,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - int rdIndex = high != 0 ? op.Rd1.Index : op.Rd0.Index; + int rdIndex = high != 0 ? dest2 : dest; if (rdIndex < RegisterConsts.RegisterZeroIndex) { @@ -846,74 +647,85 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - int handle = op.HandleOffset; + int handle = imm; + int componentMask = _maskLut[dest2 == RegisterConsts.RegisterZeroIndex ? 0 : 1, writeMask]; - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { - Operand dest = GetDest(); - TextureOperation operation = context.CreateTextureOperation( Instruction.TextureSample, type, flags, handle, compIndex, - dest, + GetDest(), sources); context.Add(operation); } } - if (op.IsFp16) + if (isF16) { - context.Copy(Register(op.Rd0), context.PackHalf2x16(rd0[0], rd0[1])); - context.Copy(Register(op.Rd1), context.PackHalf2x16(rd1[0], rd1[1])); + context.Copy(Register(dest, RegisterType.Gpr), context.PackHalf2x16(rd0[0], rd0[1])); + context.Copy(Register(dest2, RegisterType.Gpr), context.PackHalf2x16(rd1[0], rd1[1])); } } - public static void Tld4(EmitterContext context) + private static void EmitTld4( + EmitterContext context, + TexDim dimensions, + TexComp component, + int imm, + int componentMask, + int srcA, + int srcB, + int dest, + TexOffset offset, + bool hasDepthCompare, + bool isBindless) { - IOpCodeTld4 op = (IOpCodeTld4)context.CurrOp; - - if (op.Rd.IsRZ) + if (dest == RegisterConsts.RegisterZeroIndex) { return; } - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - Operand Ra() { - if (raIndex > RegisterConsts.RegisterZeroIndex) + if (srcA > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(raIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcA++, RegisterType.Gpr)); } Operand Rb() { - if (rbIndex > RegisterConsts.RegisterZeroIndex) + if (srcB > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcB++, RegisterType.Gpr)); } - Operand arrayIndex = op.IsArray ? Ra() : null; + bool isArray = + dimensions == TexDim.Array1d || + dimensions == TexDim.Array2d || + dimensions == TexDim.Array3d || + dimensions == TexDim.ArrayCube; + + Operand arrayIndex = isArray ? Ra() : null; List sourcesList = new List(); - SamplerType type = ConvertSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(dimensions); TextureFlags flags = TextureFlags.Gather; - if (op.Bindless) + if (isBindless) { sourcesList.Add(Rb()); @@ -927,37 +739,37 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Ra()); } - bool is1DTo2D = Sample1DAs2D && type == SamplerType.Texture1D; + bool is1DTo2D = Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D; if (is1DTo2D) { sourcesList.Add(ConstF(0)); - type = SamplerType.Texture2D; + type = SamplerType.Texture2D | (type & SamplerType.Array); } - if (op.IsArray) + if (isArray) { sourcesList.Add(arrayIndex); - - type |= SamplerType.Array; } Operand[] packedOffs = new Operand[2]; - packedOffs[0] = op.Offset != TextureGatherOffset.None ? Rb() : null; - packedOffs[1] = op.Offset == TextureGatherOffset.Offsets ? Rb() : null; + bool hasAnyOffset = offset == TexOffset.Aoffi || offset == TexOffset.Ptp; - if (op.HasDepthCompare) + packedOffs[0] = hasAnyOffset ? Rb() : null; + packedOffs[1] = offset == TexOffset.Ptp ? Rb() : null; + + if (hasDepthCompare) { sourcesList.Add(Rb()); type |= SamplerType.Shadow; } - if (op.Offset != TextureGatherOffset.None) + if (hasAnyOffset) { - int offsetTexelsCount = op.Offset == TextureGatherOffset.Offsets ? 4 : 1; + int offsetTexelsCount = offset == TexOffset.Ptp ? 4 : 1; for (int index = 0; index < coordsCount * offsetTexelsCount; index++) { @@ -974,42 +786,36 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - flags |= op.Offset == TextureGatherOffset.Offsets - ? TextureFlags.Offsets - : TextureFlags.Offset; + flags |= offset == TexOffset.Ptp ? TextureFlags.Offsets : TextureFlags.Offset; } - sourcesList.Add(Const(op.GatherCompIndex)); + sourcesList.Add(Const((int)component)); Operand[] sources = sourcesList.ToArray(); - int rdIndex = op.Rd.Index; - Operand GetDest() { - if (rdIndex > RegisterConsts.RegisterZeroIndex) + if (dest > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return Register(rdIndex++, RegisterType.Gpr); + return Register(dest++, RegisterType.Gpr); } - int handle = op.HandleOffset; + int handle = imm; - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { - Operand dest = GetDest(); - TextureOperation operation = context.CreateTextureOperation( Instruction.TextureSample, type, flags, handle, compIndex, - dest, + GetDest(), sources); context.Add(operation); @@ -1017,46 +823,39 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - public static void TmmlB(EmitterContext context) + private static void EmitTmml( + EmitterContext context, + TexDim dimensions, + int imm, + int componentMask, + int srcA, + int srcB, + int dest, + bool isBindless) { - EmitTextureMipMapLevel(context, true); - } - - public static void Tmml(EmitterContext context) - { - EmitTextureMipMapLevel(context, false); - } - - private static void EmitTextureMipMapLevel(EmitterContext context, bool isBindless) - { - OpCodeTexture op = (OpCodeTexture)context.CurrOp; - - if (op.Rd.IsRZ) + if (dest == RegisterConsts.RegisterZeroIndex) { return; } - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - Operand Ra() { - if (raIndex > RegisterConsts.RegisterZeroIndex) + if (srcA > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(raIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcA++, RegisterType.Gpr)); } Operand Rb() { - if (rbIndex > RegisterConsts.RegisterZeroIndex) + if (srcB > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcB++, RegisterType.Gpr)); } TextureFlags flags = TextureFlags.None; @@ -1070,58 +869,58 @@ namespace Ryujinx.Graphics.Shader.Instructions flags |= TextureFlags.Bindless; } - SamplerType type = ConvertSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(dimensions); int coordsCount = type.GetDimensions(); - Operand arrayIndex = op.IsArray ? Ra() : null; + bool isArray = + dimensions == TexDim.Array1d || + dimensions == TexDim.Array2d || + dimensions == TexDim.Array3d || + dimensions == TexDim.ArrayCube; + + Operand arrayIndex = isArray ? Ra() : null; for (int index = 0; index < coordsCount; index++) { sourcesList.Add(Ra()); } - if (Sample1DAs2D && type == SamplerType.Texture1D) + if (Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D) { sourcesList.Add(ConstF(0)); - type = SamplerType.Texture2D; + type = SamplerType.Texture2D | (type & SamplerType.Array); } - if (op.IsArray) + if (isArray) { sourcesList.Add(arrayIndex); - - type |= SamplerType.Array; } Operand[] sources = sourcesList.ToArray(); - int rdIndex = op.Rd.Index; - Operand GetDest() { - if (rdIndex > RegisterConsts.RegisterZeroIndex) + if (dest > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return Register(rdIndex++, RegisterType.Gpr); + return Register(dest++, RegisterType.Gpr); } - int handle = !isBindless ? op.HandleOffset : 0; + int handle = imm; - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { - Operand dest = GetDest(); - // Components z and w aren't standard, we return 0 in this case and add a comment. if (compIndex >= 2) { context.Add(new CommentNode("Unsupported component z or w found")); - context.Copy(dest, Const(0)); + context.Copy(GetDest(), Const(0)); } else { @@ -1142,56 +941,60 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand fixedPointValue = context.FPConvertToS32(tempDest); - context.Copy(dest, fixedPointValue); + context.Copy(GetDest(), fixedPointValue); } } } } - public static void Txd(EmitterContext context) + private static void EmitTxd( + EmitterContext context, + TexDim dimensions, + int imm, + int componentMask, + int srcA, + int srcB, + int dest, + bool hasOffset, + bool isBindless) { - OpCodeTxd op = (OpCodeTxd)context.CurrOp; - - if (op.Rd.IsRZ) + if (dest == RegisterConsts.RegisterZeroIndex) { return; } - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - Operand Ra() { - if (raIndex > RegisterConsts.RegisterZeroIndex) + if (srcA > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(raIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcA++, RegisterType.Gpr)); } Operand Rb() { - if (rbIndex > RegisterConsts.RegisterZeroIndex) + if (srcB > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcB++, RegisterType.Gpr)); } TextureFlags flags = TextureFlags.Derivatives; List sourcesList = new List(); - if (op.IsBindless) + if (isBindless) { sourcesList.Add(Ra()); flags |= TextureFlags.Bindless; } - SamplerType type = ConvertSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(dimensions); int coordsCount = type.GetDimensions(); @@ -1200,22 +1003,26 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Ra()); } - bool is1DTo2D = Sample1DAs2D && type == SamplerType.Texture1D; + bool is1DTo2D = Sample1DAs2D && (type & SamplerType.Mask) == SamplerType.Texture1D; if (is1DTo2D) { sourcesList.Add(ConstF(0)); - type = SamplerType.Texture2D; + type = SamplerType.Texture2D | (type & SamplerType.Array); } Operand packedParams = Ra(); - if (op.IsArray) + bool isArray = + dimensions == TexDim.Array1d || + dimensions == TexDim.Array2d || + dimensions == TexDim.Array3d || + dimensions == TexDim.ArrayCube; + + if (isArray) { sourcesList.Add(context.BitwiseAnd(packedParams, Const(0xffff))); - - type |= SamplerType.Array; } // Derivatives (X and Y). @@ -1229,7 +1036,7 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - if (op.HasOffset) + if (hasOffset) { for (int index = 0; index < coordsCount; index++) { @@ -1246,33 +1053,29 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand[] sources = sourcesList.ToArray(); - int rdIndex = op.Rd.Index; - Operand GetDest() { - if (rdIndex > RegisterConsts.RegisterZeroIndex) + if (dest > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return Register(rdIndex++, RegisterType.Gpr); + return Register(dest++, RegisterType.Gpr); } - int handle = !op.IsBindless ? op.HandleOffset : 0; + int handle = imm; - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { - Operand dest = GetDest(); - TextureOperation operation = context.CreateTextureOperation( Instruction.TextureSample, type, flags, handle, compIndex, - dest, + GetDest(), sources); context.Add(operation); @@ -1280,49 +1083,39 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - public static void Txq(EmitterContext context) + private static void EmitTxq( + EmitterContext context, + TexQuery query, + int imm, + int componentMask, + int srcA, + int dest, + bool isBindless) { - EmitTextureQuery(context, bindless: false); - } - - public static void TxqB(EmitterContext context) - { - EmitTextureQuery(context, bindless: true); - } - - private static void EmitTextureQuery(EmitterContext context, bool bindless) - { - OpCodeTex op = (OpCodeTex)context.CurrOp; - - if (op.Rd.IsRZ) + if (dest == RegisterConsts.RegisterZeroIndex) { return; } context.Config.SetUsedFeature(FeatureFlags.IntegerSampling); - TextureProperty property = (TextureProperty)op.RawOpCode.Extract(22, 6); - - // TODO: Validate and use property. + // TODO: Validate and use query. Instruction inst = Instruction.TextureSize; - - TextureFlags flags = bindless ? TextureFlags.Bindless : TextureFlags.None; - - int raIndex = op.Ra.Index; + TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None; Operand Ra() { - if (raIndex > RegisterConsts.RegisterZeroIndex) + if (srcA > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return context.Copy(Register(raIndex++, RegisterType.Gpr)); + return context.Copy(Register(srcA++, RegisterType.Gpr)); } List sourcesList = new List(); - if (bindless) + if (isBindless) { sourcesList.Add(Ra()); } @@ -1331,44 +1124,38 @@ namespace Ryujinx.Graphics.Shader.Instructions Operand[] sources = sourcesList.ToArray(); - int rdIndex = op.Rd.Index; - Operand GetDest() { - if (rdIndex > RegisterConsts.RegisterZeroIndex) + if (dest > RegisterConsts.RegisterZeroIndex) { return Const(0); } - return Register(rdIndex++, RegisterType.Gpr); + return Register(dest++, RegisterType.Gpr); } - int handle = !bindless ? op.HandleOffset : 0; - SamplerType type; - if (bindless) + if (isBindless) { - type = (op.ComponentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D; - } + type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D; + } else { - type = context.Config.GpuAccessor.QuerySamplerType(handle); + type = context.Config.GpuAccessor.QuerySamplerType(imm); } - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) + for (int compMask = componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) { if ((compMask & 1) != 0) { - Operand dest = GetDest(); - TextureOperation operation = context.CreateTextureOperation( inst, type, flags, - handle, + imm, compIndex, - dest, + GetDest(), sources); context.Add(operation); @@ -1376,393 +1163,126 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - private static void EmitTextureSample(EmitterContext context, TextureFlags flags) - { - OpCodeTexture op = (OpCodeTexture)context.CurrOp; - - bool isBindless = (flags & TextureFlags.Bindless) != 0; - - if (op.Rd.IsRZ) - { - return; - } - - int raIndex = op.Ra.Index; - int rbIndex = op.Rb.Index; - - Operand Ra() - { - if (raIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(raIndex++, RegisterType.Gpr)); - } - - Operand Rb() - { - if (rbIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return context.Copy(Register(rbIndex++, RegisterType.Gpr)); - } - - Operand arrayIndex = op.IsArray ? Ra() : null; - - List sourcesList = new List(); - - if (isBindless) - { - sourcesList.Add(Rb()); - } - - SamplerType type = ConvertSamplerType(op.Dimensions); - - bool hasLod = op.LodMode > TextureLodMode.LodZero; - - if (type == SamplerType.Texture1D && (flags & ~TextureFlags.Bindless) == TextureFlags.IntCoords && !(hasLod || - op.HasDepthCompare || - op.HasOffset || - op.IsArray || - op.IsMultisample)) - { - // For bindless, we don't have any way to know the texture type, - // so we assume it's texture buffer when the sampler type is 1D, since that's more common. - bool isTypeBuffer = isBindless || context.Config.GpuAccessor.QuerySamplerType(op.HandleOffset) == SamplerType.TextureBuffer; - - if (isTypeBuffer) - { - type = SamplerType.TextureBuffer; - } - } - - int coordsCount = type.GetDimensions(); - - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(Ra()); - } - - if (Sample1DAs2D && type == SamplerType.Texture1D) - { - sourcesList.Add(ConstF(0)); - - type = SamplerType.Texture2D; - } - - if (op.IsArray) - { - sourcesList.Add(arrayIndex); - - type |= SamplerType.Array; - } - - Operand lodValue = hasLod ? Rb() : ConstF(0); - - Operand packedOffs = op.HasOffset ? Rb() : null; - - if (op.HasDepthCompare) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Shadow; - } - - if ((op.LodMode == TextureLodMode.LodZero || - op.LodMode == TextureLodMode.LodLevel || - op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample && type != SamplerType.TextureBuffer) - { - sourcesList.Add(lodValue); - - flags |= TextureFlags.LodLevel; - } - - if (op.HasOffset) - { - for (int index = 0; index < coordsCount; index++) - { - sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 4), Const(4))); - } - - flags |= TextureFlags.Offset; - } - - if (op.LodMode == TextureLodMode.LodBias || - op.LodMode == TextureLodMode.LodBiasA) - { - sourcesList.Add(lodValue); - - flags |= TextureFlags.LodBias; - } - - if (op.IsMultisample) - { - sourcesList.Add(Rb()); - - type |= SamplerType.Multisample; - } - - Operand[] sources = sourcesList.ToArray(); - - int rdIndex = op.Rd.Index; - - Operand GetDest() - { - if (rdIndex > RegisterConsts.RegisterZeroIndex) - { - return Const(0); - } - - return Register(rdIndex++, RegisterType.Gpr); - } - - int handle = !isBindless ? op.HandleOffset : 0; - - for (int compMask = op.ComponentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++) - { - if ((compMask & 1) != 0) - { - Operand dest = GetDest(); - - TextureOperation operation = context.CreateTextureOperation( - Instruction.TextureSample, - type, - flags, - handle, - compIndex, - dest, - sources); - - context.Add(operation); - } - } - } - - private static int GetComponents(IntegerSize size) - { - return size switch - { - IntegerSize.B64 => 2, - IntegerSize.B128 => 4, - IntegerSize.UB128 => 4, - _ => 1 - }; - } - - private static int GetComponentSizeInBytesLog2(IntegerSize size) - { - return size switch - { - IntegerSize.U8 => 0, - IntegerSize.S8 => 0, - IntegerSize.U16 => 1, - IntegerSize.S16 => 1, - IntegerSize.B32 => 2, - IntegerSize.B64 => 3, - IntegerSize.B128 => 4, - IntegerSize.UB128 => 4, - _ => 2 - }; - } - - private static TextureFormat GetTextureFormat(IntegerSize size) - { - return size switch - { - IntegerSize.U8 => TextureFormat.R8Uint, - IntegerSize.S8 => TextureFormat.R8Sint, - IntegerSize.U16 => TextureFormat.R16Uint, - IntegerSize.S16 => TextureFormat.R16Sint, - IntegerSize.B32 => TextureFormat.R32Uint, - IntegerSize.B64 => TextureFormat.R32G32Uint, - IntegerSize.B128 => TextureFormat.R32G32B32A32Uint, - IntegerSize.UB128 => TextureFormat.R32G32B32A32Uint, - _ => TextureFormat.R32Uint - }; - } - - private static int GetComponentSizeInBytesLog2(ReductionType type) - { - return type switch - { - ReductionType.U32 => 2, - ReductionType.S32 => 2, - ReductionType.U64 => 3, - ReductionType.FP32FtzRn => 2, - ReductionType.FP16x2FtzRn => 2, - ReductionType.S64 => 3, - ReductionType.SD32 => 2, - ReductionType.SD64 => 3, - _ => 2 - }; - } - - private static TextureFormat GetTextureFormat(ReductionType type) - { - return type switch - { - ReductionType.U32 => TextureFormat.R32Uint, - ReductionType.S32 => TextureFormat.R32Sint, - ReductionType.U64 => TextureFormat.R32G32Uint, - ReductionType.FP32FtzRn => TextureFormat.R32Float, - ReductionType.FP16x2FtzRn => TextureFormat.R16G16Float, - ReductionType.S64 => TextureFormat.R32G32Uint, - ReductionType.SD32 => TextureFormat.R32Uint, - ReductionType.SD64 => TextureFormat.R32G32Uint, - _ => TextureFormat.R32Uint - }; - } - - private static TextureFlags GetAtomicOpFlags(AtomicOp op) - { - return op switch - { - AtomicOp.Add => TextureFlags.Add, - AtomicOp.Minimum => TextureFlags.Minimum, - AtomicOp.Maximum => TextureFlags.Maximum, - AtomicOp.Increment => TextureFlags.Increment, - AtomicOp.Decrement => TextureFlags.Decrement, - AtomicOp.BitwiseAnd => TextureFlags.BitwiseAnd, - AtomicOp.BitwiseOr => TextureFlags.BitwiseOr, - AtomicOp.BitwiseExclusiveOr => TextureFlags.BitwiseXor, - AtomicOp.Swap => TextureFlags.Swap, - _ => TextureFlags.Add - }; - } - - private static SamplerType ConvertSamplerType(ImageDimensions target) - { - return target switch - { - ImageDimensions.Image1D => SamplerType.Texture1D, - ImageDimensions.ImageBuffer => SamplerType.TextureBuffer, - ImageDimensions.Image1DArray => SamplerType.Texture1D | SamplerType.Array, - ImageDimensions.Image2D => SamplerType.Texture2D, - ImageDimensions.Image2DArray => SamplerType.Texture2D | SamplerType.Array, - ImageDimensions.Image3D => SamplerType.Texture3D, - _ => SamplerType.None - }; - } - - private static SamplerType ConvertSamplerType(TextureDimensions dimensions) + private static SamplerType ConvertSamplerType(TexDim dimensions) { return dimensions switch { - TextureDimensions.Texture1D => SamplerType.Texture1D, - TextureDimensions.Texture2D => SamplerType.Texture2D, - TextureDimensions.Texture3D => SamplerType.Texture3D, - TextureDimensions.TextureCube => SamplerType.TextureCube, + TexDim._1d => SamplerType.Texture1D, + TexDim.Array1d => SamplerType.Texture1D | SamplerType.Array, + TexDim._2d => SamplerType.Texture2D, + TexDim.Array2d => SamplerType.Texture2D | SamplerType.Array, + TexDim._3d => SamplerType.Texture3D, + TexDim.Array3d => SamplerType.Texture3D | SamplerType.Array, + TexDim.Cube => SamplerType.TextureCube, + TexDim.ArrayCube => SamplerType.TextureCube | SamplerType.Array, _ => throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".") }; } - private static SamplerType ConvertSamplerType(TextureTarget type) + private static SamplerType ConvertSamplerType(TexsTarget type) { switch (type) { - case TextureTarget.Texture1DLodZero: + case TexsTarget.Texture1DLodZero: return SamplerType.Texture1D; - case TextureTarget.Texture2D: - case TextureTarget.Texture2DLodZero: - case TextureTarget.Texture2DLodLevel: + case TexsTarget.Texture2D: + case TexsTarget.Texture2DLodZero: + case TexsTarget.Texture2DLodLevel: return SamplerType.Texture2D; - case TextureTarget.Texture2DDepthCompare: - case TextureTarget.Texture2DLodLevelDepthCompare: - case TextureTarget.Texture2DLodZeroDepthCompare: + case TexsTarget.Texture2DDepthCompare: + case TexsTarget.Texture2DLodLevelDepthCompare: + case TexsTarget.Texture2DLodZeroDepthCompare: return SamplerType.Texture2D | SamplerType.Shadow; - case TextureTarget.Texture2DArray: - case TextureTarget.Texture2DArrayLodZero: + case TexsTarget.Texture2DArray: + case TexsTarget.Texture2DArrayLodZero: return SamplerType.Texture2D | SamplerType.Array; - case TextureTarget.Texture2DArrayLodZeroDepthCompare: + case TexsTarget.Texture2DArrayLodZeroDepthCompare: return SamplerType.Texture2D | SamplerType.Array | SamplerType.Shadow; - case TextureTarget.Texture3D: - case TextureTarget.Texture3DLodZero: + case TexsTarget.Texture3D: + case TexsTarget.Texture3DLodZero: return SamplerType.Texture3D; - case TextureTarget.TextureCube: - case TextureTarget.TextureCubeLodLevel: + case TexsTarget.TextureCube: + case TexsTarget.TextureCubeLodLevel: return SamplerType.TextureCube; } return SamplerType.None; } - private static SamplerType ConvertSamplerType(TexelLoadTarget type) + private static SamplerType ConvertSamplerType(TldsTarget type) { switch (type) { - case TexelLoadTarget.Texture1DLodZero: - case TexelLoadTarget.Texture1DLodLevel: + case TldsTarget.Texture1DLodZero: + case TldsTarget.Texture1DLodLevel: return SamplerType.Texture1D; - case TexelLoadTarget.Texture2DLodZero: - case TexelLoadTarget.Texture2DLodZeroOffset: - case TexelLoadTarget.Texture2DLodLevel: - case TexelLoadTarget.Texture2DLodLevelOffset: + case TldsTarget.Texture2DLodZero: + case TldsTarget.Texture2DLodZeroOffset: + case TldsTarget.Texture2DLodLevel: + case TldsTarget.Texture2DLodLevelOffset: return SamplerType.Texture2D; - case TexelLoadTarget.Texture2DLodZeroMultisample: + case TldsTarget.Texture2DLodZeroMultisample: return SamplerType.Texture2D | SamplerType.Multisample; - case TexelLoadTarget.Texture3DLodZero: + case TldsTarget.Texture3DLodZero: return SamplerType.Texture3D; - case TexelLoadTarget.Texture2DArrayLodZero: + case TldsTarget.Texture2DArrayLodZero: return SamplerType.Texture2D | SamplerType.Array; } return SamplerType.None; } - private static TextureFlags ConvertTextureFlags(TextureTarget type) + private static TextureFlags ConvertTextureFlags(TexsTarget type) { switch (type) { - case TextureTarget.Texture1DLodZero: - case TextureTarget.Texture2DLodZero: - case TextureTarget.Texture2DLodLevel: - case TextureTarget.Texture2DLodLevelDepthCompare: - case TextureTarget.Texture2DLodZeroDepthCompare: - case TextureTarget.Texture2DArrayLodZero: - case TextureTarget.Texture2DArrayLodZeroDepthCompare: - case TextureTarget.Texture3DLodZero: - case TextureTarget.TextureCubeLodLevel: + case TexsTarget.Texture1DLodZero: + case TexsTarget.Texture2DLodZero: + case TexsTarget.Texture2DLodLevel: + case TexsTarget.Texture2DLodLevelDepthCompare: + case TexsTarget.Texture2DLodZeroDepthCompare: + case TexsTarget.Texture2DArrayLodZero: + case TexsTarget.Texture2DArrayLodZeroDepthCompare: + case TexsTarget.Texture3DLodZero: + case TexsTarget.TextureCubeLodLevel: return TextureFlags.LodLevel; - case TextureTarget.Texture2D: - case TextureTarget.Texture2DDepthCompare: - case TextureTarget.Texture2DArray: - case TextureTarget.Texture3D: - case TextureTarget.TextureCube: + case TexsTarget.Texture2D: + case TexsTarget.Texture2DDepthCompare: + case TexsTarget.Texture2DArray: + case TexsTarget.Texture3D: + case TexsTarget.TextureCube: return TextureFlags.None; } return TextureFlags.None; } - private static TextureFlags ConvertTextureFlags(TexelLoadTarget type) + private static TextureFlags ConvertTextureFlags(TldsTarget type) { switch (type) { - case TexelLoadTarget.Texture1DLodZero: - case TexelLoadTarget.Texture1DLodLevel: - case TexelLoadTarget.Texture2DLodZero: - case TexelLoadTarget.Texture2DLodLevel: - case TexelLoadTarget.Texture2DLodZeroMultisample: - case TexelLoadTarget.Texture3DLodZero: - case TexelLoadTarget.Texture2DArrayLodZero: + case TldsTarget.Texture1DLodZero: + case TldsTarget.Texture1DLodLevel: + case TldsTarget.Texture2DLodZero: + case TldsTarget.Texture2DLodLevel: + case TldsTarget.Texture2DLodZeroMultisample: + case TldsTarget.Texture3DLodZero: + case TldsTarget.Texture2DArrayLodZero: return TextureFlags.LodLevel; - case TexelLoadTarget.Texture2DLodZeroOffset: - case TexelLoadTarget.Texture2DLodLevelOffset: + case TldsTarget.Texture2DLodZeroOffset: + case TldsTarget.Texture2DLodLevelOffset: return TextureFlags.LodLevel | TextureFlags.Offset; } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs new file mode 100644 index 00000000..43c0035a --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoArithmetic.cs @@ -0,0 +1,18 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Vmad(EmitterContext context) + { + InstVmad op = context.GetOp(); + + // TODO: Implement properly. + context.Copy(GetDest(op.Dest), GetSrcReg(context, op.SrcC)); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideo.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs similarity index 51% rename from Ryujinx.Graphics.Shader/Instructions/InstEmitVideo.cs rename to Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs index 7b3d9ca5..890b31d6 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVideo.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitVideoMinMax.cs @@ -9,47 +9,46 @@ namespace Ryujinx.Graphics.Shader.Instructions { static partial class InstEmit { - public static void Vmad(EmitterContext context) - { - // TODO: Implement properly. - context.Copy(GetDest(context), GetSrcC(context)); - } - public static void Vmnmx(EmitterContext context) { - OpCodeVideo op = (OpCodeVideo)context.CurrOp; + InstVmnmx op = context.GetOp(); - bool max = op.RawOpCode.Extract(56); - - Operand srcA = Extend(context, GetSrcA(context), op.RaSelection, op.RaType); - Operand srcC = GetSrcC(context); + Operand srcA = Extend(context, GetSrcReg(context, op.SrcA), op.ASelect); + Operand srcC = GetSrcReg(context, op.SrcC); Operand srcB; - if (op.HasRb) + if (op.BVideo) { - srcB = Extend(context, Register(op.Rb), op.RbSelection, op.RbType); + srcB = Extend(context, GetSrcReg(context, op.SrcB), op.BSelect); } else { - srcB = Const(op.Immediate); + int imm = op.Imm16; + + if ((op.BSelect & VectorSelect.S8B0) != 0) + { + imm = (imm << 16) >> 16; + } + + srcB = Const(imm); } Operand res; bool resSigned; - if ((op.RaType & VideoType.Signed) != (op.RbType & VideoType.Signed)) + if ((op.ASelect & VectorSelect.S8B0) != (op.BSelect & VectorSelect.S8B0)) { // Signedness is different, but for max, result will always fit a U32, // since one of the inputs can't be negative, and the result is the one // with highest value. For min, it will always fit on a S32, since // one of the input can't be greater than INT_MAX and we want the lowest value. - resSigned = !max; + resSigned = !op.Mn; - res = max ? context.IMaximumU32(srcA, srcB) : context.IMinimumS32(srcA, srcB); + res = op.Mn ? context.IMaximumU32(srcA, srcB) : context.IMinimumS32(srcA, srcB); - if ((op.RaType & VideoType.Signed) != 0) + if ((op.ASelect & VectorSelect.S8B0) != 0) { Operand isBGtIntMax = context.ICompareLess(srcB, Const(0)); @@ -65,9 +64,9 @@ namespace Ryujinx.Graphics.Shader.Instructions else { // Ra and Rb have the same signedness, so doesn't matter which one we test. - resSigned = (op.RaType & VideoType.Signed) != 0; + resSigned = (op.ASelect & VectorSelect.S8B0) != 0; - if (max) + if (op.Mn) { res = resSigned ? context.IMaximumS32(srcA, srcB) @@ -81,54 +80,62 @@ namespace Ryujinx.Graphics.Shader.Instructions } } - if (op.Saturate) + if (op.Sat) { - if (op.DstSigned && !resSigned) + if (op.DFormat && !resSigned) { res = context.IMinimumU32(res, Const(int.MaxValue)); } - else if (!op.DstSigned && resSigned) + else if (!op.DFormat && resSigned) { res = context.IMaximumS32(res, Const(0)); } } - switch (op.PostOp) + switch (op.VideoOp) { - case VideoPostOp.Acc: + case VideoOp.Acc: res = context.IAdd(res, srcC); break; - case VideoPostOp.Max: - res = op.DstSigned ? context.IMaximumS32(res, srcC) : context.IMaximumU32(res, srcC); + case VideoOp.Max: + res = op.DFormat ? context.IMaximumS32(res, srcC) : context.IMaximumU32(res, srcC); break; - case VideoPostOp.Min: - res = op.DstSigned ? context.IMinimumS32(res, srcC) : context.IMinimumU32(res, srcC); + case VideoOp.Min: + res = op.DFormat ? context.IMinimumS32(res, srcC) : context.IMinimumU32(res, srcC); break; - case VideoPostOp.Mrg16h: + case VideoOp.Mrg16h: res = context.BitfieldInsert(srcC, res, Const(16), Const(16)); break; - case VideoPostOp.Mrg16l: + case VideoOp.Mrg16l: res = context.BitfieldInsert(srcC, res, Const(0), Const(16)); break; - case VideoPostOp.Mrg8b0: + case VideoOp.Mrg8b0: res = context.BitfieldInsert(srcC, res, Const(0), Const(8)); break; - case VideoPostOp.Mrg8b2: + case VideoOp.Mrg8b2: res = context.BitfieldInsert(srcC, res, Const(16), Const(8)); break; } - context.Copy(GetDest(context), res); + context.Copy(GetDest(op.Dest), res); } - private static Operand Extend(EmitterContext context, Operand src, int sel, VideoType type) + private static Operand Extend(EmitterContext context, Operand src, VectorSelect type) { return type switch { - VideoType.U8 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(sel * 8)), 8), - VideoType.U16 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(sel * 16)), 16), - VideoType.S8 => SignExtendTo32(context, context.ShiftRightU32(src, Const(sel * 8)), 8), - VideoType.S16 => SignExtendTo32(context, context.ShiftRightU32(src, Const(sel * 16)), 16), + VectorSelect.U8B0 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(0)), 8), + VectorSelect.U8B1 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(8)), 8), + VectorSelect.U8B2 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(16)), 8), + VectorSelect.U8B3 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8), + VectorSelect.U16H0 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16), + VectorSelect.U16H1 => ZeroExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16), + VectorSelect.S8B0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 8), + VectorSelect.S8B1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(8)), 8), + VectorSelect.S8B2 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 8), + VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8), + VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16), + VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16), _ => src }; } diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs deleted file mode 100644 index 5c16770a..00000000 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitVote.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Ryujinx.Graphics.Shader.Decoders; -using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using Ryujinx.Graphics.Shader.Translation; - -using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; -using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; - -namespace Ryujinx.Graphics.Shader.Instructions -{ - static partial class InstEmit - { - public static void Vote(EmitterContext context) - { - OpCodeVote op = (OpCodeVote)context.CurrOp; - - Operand pred = GetPredicate39(context); - - Operand res = null; - - switch (op.VoteOp) - { - case VoteOp.All: - res = context.VoteAll(pred); - break; - case VoteOp.Any: - res = context.VoteAny(pred); - break; - case VoteOp.AllEqual: - res = context.VoteAllEqual(pred); - break; - } - - if (res != null) - { - context.Copy(Register(op.Predicate45), res); - } - else - { - context.Config.GpuAccessor.Log($"Invalid vote operation: {op.VoteOp}."); - } - - if (!op.Rd.IsRZ) - { - context.Copy(Register(op.Rd), context.Ballot(pred)); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs new file mode 100644 index 00000000..3c833613 --- /dev/null +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitWarp.cs @@ -0,0 +1,84 @@ +using Ryujinx.Graphics.Shader.Decoders; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.Translation; + +using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; +using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; + +namespace Ryujinx.Graphics.Shader.Instructions +{ + static partial class InstEmit + { + public static void Fswzadd(EmitterContext context) + { + InstFswzadd op = context.GetOp(); + + Operand srcA = GetSrcReg(context, op.SrcA); + Operand srcB = GetSrcReg(context, op.SrcB); + Operand dest = GetDest(op.Dest); + + context.Copy(dest, context.FPSwizzleAdd(srcA, srcB, op.PnWord)); + + InstEmitAluHelper.SetFPZnFlags(context, dest, op.WriteCC); + } + + public static void Shfl(EmitterContext context) + { + InstShfl op = context.GetOp(); + + Operand pred = Register(op.DestPred, RegisterType.Predicate); + + Operand srcA = GetSrcReg(context, op.SrcA); + + Operand srcB = op.BFixShfl ? Const(op.SrcBImm) : GetSrcReg(context, op.SrcB); + Operand srcC = op.CFixShfl ? Const(op.SrcCImm) : GetSrcReg(context, op.SrcC); + + (Operand res, Operand valid) = op.ShflMode switch + { + ShflMode.Idx => context.Shuffle(srcA, srcB, srcC), + ShflMode.Up => context.ShuffleUp(srcA, srcB, srcC), + ShflMode.Down => context.ShuffleDown(srcA, srcB, srcC), + ShflMode.Bfly => context.ShuffleXor(srcA, srcB, srcC), + _ => (null, null) + }; + + context.Copy(GetDest(op.Dest), res); + context.Copy(pred, valid); + } + + public static void Vote(EmitterContext context) + { + InstVote op = context.GetOp(); + + Operand pred = GetPredicate(context, op.SrcPred, op.SrcPredInv); + Operand res = null; + + switch (op.VoteMode) + { + case VoteMode.All: + res = context.VoteAll(pred); + break; + case VoteMode.Any: + res = context.VoteAny(pred); + break; + case VoteMode.Eq: + res = context.VoteAllEqual(pred); + break; + } + + if (res != null) + { + context.Copy(Register(op.VpDest, RegisterType.Predicate), res); + } + else + { + context.Config.GpuAccessor.Log($"Invalid vote operation: {op.VoteMode}."); + } + + if (op.Dest != RegisterConsts.RegisterZeroIndex) + { + context.Copy(GetDest(op.Dest), context.Ballot(pred)); + } + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs b/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs index 67e24957..76a52007 100644 --- a/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs +++ b/Ryujinx.Graphics.Shader/Instructions/Lop3Expression.cs @@ -7,12 +7,7 @@ namespace Ryujinx.Graphics.Shader.Instructions { static class Lop3Expression { - public static Operand GetFromTruthTable( - EmitterContext context, - Operand srcA, - Operand srcB, - Operand srcC, - int imm) + public static Operand GetFromTruthTable(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int imm) { Operand expr = null; @@ -45,7 +40,7 @@ namespace Ryujinx.Graphics.Shader.Instructions int map; // Encode into gray code. - map = ((imm >> 0) & 1) << 0; + map = ((imm >> 0) & 1) << 0; map |= ((imm >> 1) & 1) << 4; map |= ((imm >> 2) & 1) << 1; map |= ((imm >> 3) & 1) << 5; diff --git a/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs b/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs index fb0535c8..65328fd7 100644 --- a/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs +++ b/Ryujinx.Graphics.Shader/Translation/ControlFlowGraph.cs @@ -129,6 +129,31 @@ namespace Ryujinx.Graphics.Shader.Translation } } + // Remove unreachable blocks. + bool hasUnreachable; + + do + { + hasUnreachable = false; + + for (int blkIndex = 1; blkIndex < blocks.Count; blkIndex++) + { + BasicBlock block = blocks[blkIndex]; + + if (block.Predecessors.Count == 0) + { + block.Next = null; + block.Branch = null; + blocks.RemoveAt(blkIndex--); + hasUnreachable = true; + } + else + { + block.Index = blkIndex; + } + } + } while (hasUnreachable); + return new ControlFlowGraph(blocks.ToArray()); } diff --git a/Ryujinx.Graphics.Shader/Translation/Dominance.cs b/Ryujinx.Graphics.Shader/Translation/Dominance.cs index da4a38da..09c2eb0f 100644 --- a/Ryujinx.Graphics.Shader/Translation/Dominance.cs +++ b/Ryujinx.Graphics.Shader/Translation/Dominance.cs @@ -1,5 +1,4 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation; -using System.Collections.Generic; namespace Ryujinx.Graphics.Shader.Translation { diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs index c96b75a5..bdfd9626 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs @@ -1,6 +1,8 @@ using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -9,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.Translation class EmitterContext { public Block CurrBlock { get; set; } - public OpCode CurrOp { get; set; } + public InstOp CurrOp { get; set; } public ShaderConfig Config { get; } @@ -30,6 +32,13 @@ namespace Ryujinx.Graphics.Shader.Translation _labels = new Dictionary(); } + public T GetOp() where T : unmanaged + { + Debug.Assert(Unsafe.SizeOf() == sizeof(ulong)); + ulong op = CurrOp.RawOpCode; + return Unsafe.As(ref op); + } + public Operand Add(Instruction inst, Operand dest = null, params Operand[] sources) { Operation operation = new Operation(inst, dest, sources); diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs index ff5932e1..0ad172da 100644 --- a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs +++ b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs @@ -1,5 +1,6 @@ using Ryujinx.Graphics.Shader.Decoders; using System; +using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Shader.Translation { @@ -113,11 +114,13 @@ namespace Ryujinx.Graphics.Shader.Translation public ShaderHeader(IGpuAccessor gpuAccessor, ulong address) { - int commonWord0 = gpuAccessor.MemoryRead(address + 0); - int commonWord1 = gpuAccessor.MemoryRead(address + 4); - int commonWord2 = gpuAccessor.MemoryRead(address + 8); - int commonWord3 = gpuAccessor.MemoryRead(address + 12); - int commonWord4 = gpuAccessor.MemoryRead(address + 16); + ReadOnlySpan header = MemoryMarshal.Cast(gpuAccessor.GetCode(address, 0x50)); + + int commonWord0 = header[0]; + int commonWord1 = header[1]; + int commonWord2 = header[2]; + int commonWord3 = header[3]; + int commonWord4 = header[4]; SphType = commonWord0.Extract(0, 5); Version = commonWord0.Extract(5, 5); @@ -164,9 +167,9 @@ namespace Ryujinx.Graphics.Shader.Translation ImapTypes = new ImapPixelType[32]; - for (ulong i = 0; i < 32; i++) + for (int i = 0; i < 32; i++) { - byte imap = gpuAccessor.MemoryRead(address + 0x18 + i); + byte imap = (byte)(header[6 + (i >> 2)] >> ((i & 3) * 8)); ImapTypes[i] = new ImapPixelType( (PixelImap)((imap >> 0) & 3), @@ -175,8 +178,8 @@ namespace Ryujinx.Graphics.Shader.Translation (PixelImap)((imap >> 6) & 3)); } - int type2OmapTarget = gpuAccessor.MemoryRead(address + 0x48); - int type2Omap = gpuAccessor.MemoryRead(address + 0x4c); + int type2OmapTarget = header[18]; + int type2Omap = header[19]; OmapTargets = new OmapTarget[8]; diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index 1abf19d7..0a0ee4a7 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -150,9 +150,12 @@ namespace Ryujinx.Graphics.Shader.Translation { for (int index = 0; index < block.OpCodes.Count; index++) { - if (block.OpCodes[index] is OpCodeTextureBase texture) + InstOp op = block.OpCodes[index]; + + if (op.Props.HasFlag(InstProps.Tex)) { - config.TextureHandlesForCache.Add(texture.HandleOffset); + int tidB = (int)((op.RawOpCode >> 36) & 0x1fff); + config.TextureHandlesForCache.Add(tidB); } } } @@ -241,15 +244,15 @@ namespace Ryujinx.Graphics.Shader.Translation { for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++) { - OpCode op = block.OpCodes[opIndex]; + InstOp op = block.OpCodes[opIndex]; - if ((context.Config.Options.Flags & TranslationFlags.DebugMode) != 0) + if (context.Config.Options.Flags.HasFlag(TranslationFlags.DebugMode)) { string instName; if (op.Emitter != null) { - instName = op.Emitter.Method.Name; + instName = op.Name.ToString(); } else { @@ -263,31 +266,36 @@ namespace Ryujinx.Graphics.Shader.Translation context.Add(new CommentNode(dbgComment)); } - if (op.NeverExecute) + InstConditional opConditional = new InstConditional(op.RawOpCode); + + bool noPred = op.Props.HasFlag(InstProps.NoPred); + if (!noPred && opConditional.Pred == RegisterConsts.PredicateTrueIndex && opConditional.PredInv) { continue; } Operand predSkipLbl = null; - bool skipPredicateCheck = op is OpCodeBranch opBranch && !opBranch.PushTarget; - - if (op is OpCodeBranchPop opBranchPop) + if (op.Name == InstName.Sync || op.Name == InstName.Brk) { // If the instruction is a SYNC or BRK instruction with only one // possible target address, then the instruction is basically // just a simple branch, we can generate code similar to branch // instructions, with the condition check on the branch itself. - skipPredicateCheck = opBranchPop.Targets.Count < 2; + noPred = block.SyncTargets.Count <= 1; + } + else if (op.Name == InstName.Bra) + { + noPred = true; } - if (!(op.Predicate.IsPT || skipPredicateCheck)) + if (!(opConditional.Pred == RegisterConsts.PredicateTrueIndex || noPred)) { Operand label; - if (opIndex == block.OpCodes.Count - 1 && block.Next != null) + if (opIndex == block.OpCodes.Count - 1 && block.HasNext()) { - label = context.GetLabel(block.Next.Address); + label = context.GetLabel(block.Successors[0].Address); } else { @@ -296,9 +304,9 @@ namespace Ryujinx.Graphics.Shader.Translation predSkipLbl = label; } - Operand pred = Register(op.Predicate); + Operand pred = Register(opConditional.Pred, RegisterType.Predicate); - if (op.InvertPredicate) + if (opConditional.PredInv) { context.BranchIfTrue(label, pred); } diff --git a/Ryujinx.ShaderTools/Program.cs b/Ryujinx.ShaderTools/Program.cs index fba0b3ad..43b9494e 100644 --- a/Ryujinx.ShaderTools/Program.cs +++ b/Ryujinx.ShaderTools/Program.cs @@ -18,9 +18,9 @@ namespace Ryujinx.ShaderTools _data = data; } - public T MemoryRead(ulong address) where T : unmanaged + public ReadOnlySpan GetCode(ulong address, int minimumSize) { - return MemoryMarshal.Cast(new ReadOnlySpan(_data).Slice((int)address))[0]; + return MemoryMarshal.Cast(new ReadOnlySpan(_data).Slice((int)address)); } }