mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-09-10 13:43:17 +02:00
Add support for fragment shader interlock (#2768)
* Support coherent images * Add support for fragment shader interlock * Change to tree based match approach * Refactor + check for branch targets and external registers * Make detection more robust * Use Intel fragment shader ordering if interlock is not available, use nothing if both are not available * Remove unused field
This commit is contained in:
parent
a7a40a77f2
commit
99445dd0a6
@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.GAL
|
||||
public bool HasVectorIndexingBug { get; }
|
||||
|
||||
public bool SupportsAstcCompression { get; }
|
||||
public bool SupportsFragmentShaderInterlock { get; }
|
||||
public bool SupportsFragmentShaderOrderingIntel { get; }
|
||||
public bool SupportsImageLoadFormatted { get; }
|
||||
public bool SupportsMismatchingViewFormat { get; }
|
||||
public bool SupportsNonConstantTextureOffset { get; }
|
||||
@ -22,6 +24,8 @@ namespace Ryujinx.Graphics.GAL
|
||||
bool hasFrontFacingBug,
|
||||
bool hasVectorIndexingBug,
|
||||
bool supportsAstcCompression,
|
||||
bool supportsFragmentShaderInterlock,
|
||||
bool supportsFragmentShaderOrderingIntel,
|
||||
bool supportsImageLoadFormatted,
|
||||
bool supportsMismatchingViewFormat,
|
||||
bool supportsNonConstantTextureOffset,
|
||||
@ -36,6 +40,8 @@ namespace Ryujinx.Graphics.GAL
|
||||
HasFrontFacingBug = hasFrontFacingBug;
|
||||
HasVectorIndexingBug = hasVectorIndexingBug;
|
||||
SupportsAstcCompression = supportsAstcCompression;
|
||||
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
||||
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
||||
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
/// <summary>
|
||||
/// Version of the codegen (to be changed when codegen or guest format change).
|
||||
/// </summary>
|
||||
private const ulong ShaderCodeGenVersion = 2741;
|
||||
private const ulong ShaderCodeGenVersion = 2768;
|
||||
|
||||
// Progress reporting helpers
|
||||
private volatile int _shaderCount;
|
||||
|
@ -36,6 +36,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||
/// <returns>Host storage buffer alignment in bytes</returns>
|
||||
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
||||
|
||||
/// <summary>
|
||||
/// Queries host support for fragment shader ordering critical sections on the shader code.
|
||||
/// </summary>
|
||||
/// <returns>True if fragment shader interlock is supported, false otherwise</returns>
|
||||
public bool QueryHostSupportsFragmentShaderInterlock() => _context.Capabilities.SupportsFragmentShaderInterlock;
|
||||
|
||||
/// <summary>
|
||||
/// Queries host support for fragment shader ordering scoped critical sections on the shader code.
|
||||
/// </summary>
|
||||
/// <returns>True if fragment shader ordering is supported, false otherwise</returns>
|
||||
public bool QueryHostSupportsFragmentShaderOrderingIntel() => _context.Capabilities.SupportsFragmentShaderOrderingIntel;
|
||||
|
||||
/// <summary>
|
||||
/// Queries host support for readable images without a explicit format declaration on the shader.
|
||||
/// </summary>
|
||||
|
@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
static class HwCapabilities
|
||||
{
|
||||
private static readonly Lazy<bool> _supportsAstcCompression = new Lazy<bool>(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
||||
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
||||
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
||||
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||
private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck);
|
||||
@ -14,7 +17,6 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
private static readonly Lazy<bool> _supportsShaderBallot = new Lazy<bool>(() => HasExtension("GL_ARB_shader_ballot"));
|
||||
private static readonly Lazy<bool> _supportsTextureShadowLod = new Lazy<bool>(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
||||
private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle"));
|
||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||
|
||||
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
||||
@ -41,7 +43,10 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
||||
|
||||
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
||||
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
||||
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
||||
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||
public static bool SupportsQuads => _supportsQuads.Value;
|
||||
@ -49,7 +54,6 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
||||
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||
|
||||
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
||||
|
@ -104,6 +104,8 @@ namespace Ryujinx.Graphics.OpenGL
|
||||
HwCapabilities.Vendor == HwCapabilities.GpuVendor.IntelWindows,
|
||||
HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
|
||||
HwCapabilities.SupportsAstcCompression,
|
||||
HwCapabilities.SupportsFragmentShaderInterlock,
|
||||
HwCapabilities.SupportsFragmentShaderOrdering,
|
||||
HwCapabilities.SupportsImageLoadFormatted,
|
||||
HwCapabilities.SupportsMismatchingViewFormat,
|
||||
HwCapabilities.SupportsNonConstantTextureOffset,
|
||||
|
@ -32,6 +32,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_compute_shader : enable");
|
||||
}
|
||||
else if (context.Config.Stage == ShaderStage.Fragment)
|
||||
{
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
||||
{
|
||||
context.AppendLine("#extension GL_ARB_fragment_shader_interlock : enable");
|
||||
}
|
||||
else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel())
|
||||
{
|
||||
context.AppendLine("#extension GL_INTEL_fragment_shader_ordering : enable");
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Config.GpPassthrough)
|
||||
{
|
||||
@ -431,6 +442,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType());
|
||||
|
||||
if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
|
||||
{
|
||||
imageTypeName = "coherent " + imageTypeName;
|
||||
}
|
||||
|
||||
string layout = descriptor.Format.ToGlslFormat();
|
||||
|
||||
if (!string.IsNullOrEmpty(layout))
|
||||
|
@ -117,7 +117,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
if (node is AstOperation operation)
|
||||
{
|
||||
context.AppendLine(InstGen.GetExpression(context, operation) + ";");
|
||||
string expr = InstGen.GetExpression(context, operation);
|
||||
|
||||
if (expr != null)
|
||||
{
|
||||
context.AppendLine(expr + ";");
|
||||
}
|
||||
}
|
||||
else if (node is AstAssignment assignment)
|
||||
{
|
||||
|
@ -4,6 +4,7 @@ using System;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot;
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall;
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenFSI;
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
|
||||
@ -144,6 +145,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
case Instruction.Call:
|
||||
return Call(context, operation);
|
||||
|
||||
case Instruction.FSIBegin:
|
||||
return FSIBegin(context);
|
||||
|
||||
case Instruction.FSIEnd:
|
||||
return FSIEnd(context);
|
||||
|
||||
case Instruction.ImageLoad:
|
||||
case Instruction.ImageStore:
|
||||
case Instruction.ImageAtomic:
|
||||
|
@ -0,0 +1,29 @@
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
static class InstGenFSI
|
||||
{
|
||||
public static string FSIBegin(CodeGenContext context)
|
||||
{
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
||||
{
|
||||
return "beginInvocationInterlockARB()";
|
||||
}
|
||||
else if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderOrderingIntel())
|
||||
{
|
||||
return "beginFragmentShaderOrderingINTEL()";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string FSIEnd(CodeGenContext context)
|
||||
{
|
||||
if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock())
|
||||
{
|
||||
return "endInvocationInterlockARB()";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -65,6 +65,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
Add(Instruction.EmitVertex, InstType.CallNullary, "EmitVertex");
|
||||
Add(Instruction.EndPrimitive, InstType.CallNullary, "EndPrimitive");
|
||||
Add(Instruction.ExponentB2, InstType.CallUnary, "exp2");
|
||||
Add(Instruction.FSIBegin, InstType.Special);
|
||||
Add(Instruction.FSIEnd, InstType.Special);
|
||||
Add(Instruction.FindFirstSetS32, InstType.CallUnary, "findMSB");
|
||||
Add(Instruction.FindFirstSetU32, InstType.CallUnary, "findMSB");
|
||||
Add(Instruction.Floor, InstType.CallUnary, "floor");
|
||||
|
48
Ryujinx.Graphics.Shader/Decoders/DecodedFunction.cs
Normal file
48
Ryujinx.Graphics.Shader/Decoders/DecodedFunction.cs
Normal file
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
class DecodedFunction
|
||||
{
|
||||
private readonly HashSet<DecodedFunction> _callers;
|
||||
|
||||
public bool IsCompilerGenerated => Type != FunctionType.User;
|
||||
public FunctionType Type { get; set; }
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong Address { get; }
|
||||
public Block[] Blocks { get; private set; }
|
||||
|
||||
public DecodedFunction(ulong address)
|
||||
{
|
||||
Address = address;
|
||||
_callers = new HashSet<DecodedFunction>();
|
||||
Type = FunctionType.User;
|
||||
Id = -1;
|
||||
}
|
||||
|
||||
public void SetBlocks(Block[] blocks)
|
||||
{
|
||||
if (Blocks != null)
|
||||
{
|
||||
throw new InvalidOperationException("Blocks have already been set.");
|
||||
}
|
||||
|
||||
Blocks = blocks;
|
||||
}
|
||||
|
||||
public void AddCaller(DecodedFunction caller)
|
||||
{
|
||||
_callers.Add(caller);
|
||||
}
|
||||
|
||||
public void RemoveCaller(DecodedFunction caller)
|
||||
{
|
||||
if (_callers.Remove(caller) && _callers.Count == 0)
|
||||
{
|
||||
Type = FunctionType.Unused;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
57
Ryujinx.Graphics.Shader/Decoders/DecodedProgram.cs
Normal file
57
Ryujinx.Graphics.Shader/Decoders/DecodedProgram.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
struct DecodedProgram : IEnumerable<DecodedFunction>
|
||||
{
|
||||
public DecodedFunction MainFunction { get; }
|
||||
private readonly IReadOnlyDictionary<ulong, DecodedFunction> _functions;
|
||||
private readonly List<DecodedFunction> _functionsWithId;
|
||||
public int FunctionsWithIdCount => _functionsWithId.Count;
|
||||
|
||||
public DecodedProgram(DecodedFunction mainFunction, IReadOnlyDictionary<ulong, DecodedFunction> functions)
|
||||
{
|
||||
MainFunction = mainFunction;
|
||||
_functions = functions;
|
||||
_functionsWithId = new List<DecodedFunction>();
|
||||
}
|
||||
|
||||
public DecodedFunction GetFunctionByAddress(ulong address)
|
||||
{
|
||||
if (_functions.TryGetValue(address, out DecodedFunction function))
|
||||
{
|
||||
return function;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public DecodedFunction GetFunctionById(int id)
|
||||
{
|
||||
if ((uint)id >= (uint)_functionsWithId.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(id));
|
||||
}
|
||||
|
||||
return _functionsWithId[id];
|
||||
}
|
||||
|
||||
public void AddFunctionAndSetId(DecodedFunction function)
|
||||
{
|
||||
function.Id = _functionsWithId.Count;
|
||||
_functionsWithId.Add(function);
|
||||
}
|
||||
|
||||
public IEnumerator<DecodedFunction> GetEnumerator()
|
||||
{
|
||||
return _functions.Values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
@ -10,24 +10,25 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
static class Decoder
|
||||
{
|
||||
public static Block[][] Decode(ShaderConfig config, ulong startAddress)
|
||||
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
||||
{
|
||||
List<Block[]> funcs = new List<Block[]>();
|
||||
Queue<DecodedFunction> functionsQueue = new Queue<DecodedFunction>();
|
||||
Dictionary<ulong, DecodedFunction> functionsVisited = new Dictionary<ulong, DecodedFunction>();
|
||||
|
||||
Queue<ulong> funcQueue = new Queue<ulong>();
|
||||
HashSet<ulong> funcVisited = new HashSet<ulong>();
|
||||
|
||||
void EnqueueFunction(ulong funcAddress)
|
||||
DecodedFunction EnqueueFunction(ulong address)
|
||||
{
|
||||
if (funcVisited.Add(funcAddress))
|
||||
if (!functionsVisited.TryGetValue(address, out DecodedFunction function))
|
||||
{
|
||||
funcQueue.Enqueue(funcAddress);
|
||||
functionsVisited.Add(address, function = new DecodedFunction(address));
|
||||
functionsQueue.Enqueue(function);
|
||||
}
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
funcQueue.Enqueue(0);
|
||||
DecodedFunction mainFunction = EnqueueFunction(0);
|
||||
|
||||
while (funcQueue.TryDequeue(out ulong funcAddress))
|
||||
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
Queue<Block> workQueue = new Queue<Block>();
|
||||
@ -46,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
return block;
|
||||
}
|
||||
|
||||
GetBlock(funcAddress);
|
||||
GetBlock(currentFunction.Address);
|
||||
|
||||
bool hasNewTarget;
|
||||
|
||||
@ -108,7 +109,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
if (lastOp.Name == InstName.Cal)
|
||||
{
|
||||
EnqueueFunction(lastOp.GetAbsoluteAddress());
|
||||
EnqueueFunction(lastOp.GetAbsoluteAddress()).AddCaller(currentFunction);
|
||||
}
|
||||
else if (lastOp.Name == InstName.Bra)
|
||||
{
|
||||
@ -157,10 +158,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
}
|
||||
while (hasNewTarget);
|
||||
|
||||
funcs.Add(blocks.ToArray());
|
||||
currentFunction.SetBlocks(blocks.ToArray());
|
||||
}
|
||||
|
||||
return funcs.ToArray();
|
||||
return new DecodedProgram(mainFunction, functionsVisited);
|
||||
}
|
||||
|
||||
private static bool BinarySearch(List<Block> blocks, ulong address, out int index)
|
||||
|
10
Ryujinx.Graphics.Shader/Decoders/FunctionType.cs
Normal file
10
Ryujinx.Graphics.Shader/Decoders/FunctionType.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
enum FunctionType : byte
|
||||
{
|
||||
User,
|
||||
Unused,
|
||||
BuiltInFSIBegin,
|
||||
BuiltInFSIEnd
|
||||
}
|
||||
}
|
@ -404,13 +404,22 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Attr = 3,
|
||||
}
|
||||
|
||||
enum CacheOp
|
||||
enum CacheOpLd
|
||||
{
|
||||
Ca = 0,
|
||||
Cg = 1,
|
||||
Ci = 2,
|
||||
Cv = 3,
|
||||
}
|
||||
|
||||
enum CacheOpSt
|
||||
{
|
||||
Wb = 0,
|
||||
Cg = 1,
|
||||
Ci = 2,
|
||||
Wt = 3,
|
||||
}
|
||||
|
||||
enum LsSize
|
||||
{
|
||||
U8 = 0,
|
||||
@ -1163,19 +1172,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3);
|
||||
}
|
||||
|
||||
struct InstContUnsup
|
||||
struct InstCont
|
||||
{
|
||||
private ulong _opcode;
|
||||
public InstContUnsup(ulong opcode) => _opcode = opcode;
|
||||
public InstCont(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
|
||||
struct InstCset
|
||||
{
|
||||
private ulong _opcode;
|
||||
public InstCsetUnsup(ulong opcode) => _opcode = opcode;
|
||||
public InstCset(ulong opcode) => _opcode = opcode;
|
||||
public int Dest => (int)((_opcode >> 0) & 0xFF);
|
||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||
@ -3507,7 +3516,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 56) & 0x3);
|
||||
public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
|
||||
public bool E => (_opcode & 0x10000000000000) != 0;
|
||||
public int Imm32 => (int)(_opcode >> 20);
|
||||
@ -3536,7 +3545,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 46) & 0x3);
|
||||
public bool E => (_opcode & 0x200000000000) != 0;
|
||||
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||
}
|
||||
@ -4502,7 +4511,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 56) & 0x3);
|
||||
public LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
|
||||
public bool E => (_opcode & 0x10000000000000) != 0;
|
||||
public int Imm32 => (int)(_opcode >> 20);
|
||||
@ -4517,7 +4526,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 46) & 0x3);
|
||||
public bool E => (_opcode & 0x200000000000) != 0;
|
||||
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||
}
|
||||
@ -4531,7 +4540,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 44) & 0x3);
|
||||
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||
}
|
||||
|
||||
@ -4653,7 +4662,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
|
||||
public bool Ba => (_opcode & 0x800000) != 0;
|
||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||
}
|
||||
@ -4670,7 +4679,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
|
||||
public bool Ba => (_opcode & 0x800000) != 0;
|
||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||
}
|
||||
@ -4687,7 +4696,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
|
||||
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||
}
|
||||
|
||||
@ -4703,7 +4712,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpLd CacheOp => (CacheOpLd)((_opcode >> 24) & 0x3);
|
||||
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||
}
|
||||
|
||||
@ -4750,7 +4759,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
|
||||
public bool Ba => (_opcode & 0x800000) != 0;
|
||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||
}
|
||||
@ -4766,7 +4775,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
|
||||
public bool Ba => (_opcode & 0x800000) != 0;
|
||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||
}
|
||||
@ -4782,7 +4791,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
|
||||
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||
}
|
||||
|
||||
@ -4797,7 +4806,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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 CacheOpSt CacheOp => (CacheOpSt)((_opcode >> 24) & 0x3);
|
||||
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,22 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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
|
||||
Rb2 = 1 << 4,
|
||||
Ib = 1 << 5,
|
||||
Rc = 1 << 6,
|
||||
|
||||
Pd = 1 << 7,
|
||||
LPd = 2 << 7,
|
||||
SPd = 3 << 7,
|
||||
TPd = 4 << 7,
|
||||
VPd = 5 << 7,
|
||||
PdMask = 7 << 7,
|
||||
|
||||
Pdn = 1 << 10,
|
||||
Ps = 1 << 11,
|
||||
Tex = 1 << 12,
|
||||
TexB = 1 << 13,
|
||||
Bra = 1 << 14,
|
||||
NoPred = 1 << 15
|
||||
}
|
||||
}
|
@ -32,13 +32,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
#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("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | 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("1111000010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B2r, InstEmit.B2r, InstProps.Rd | InstProps.Ra | InstProps.VPd);
|
||||
Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra | InstProps.Ps);
|
||||
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);
|
||||
@ -56,8 +56,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd | InstProps.Ps);
|
||||
Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
@ -67,18 +67,18 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011100x01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("0100110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
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("010110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011001x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("010010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
Add("010110111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("0011011x1000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("010010111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
@ -105,19 +105,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011100x01100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("0100110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
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("01011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("01001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
Add("010110111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("0011011x1011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("010010111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fsetp, InstEmit.FsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
@ -133,12 +133,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101110100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0111110x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("0111110x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2C, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
Add("0101110100100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2R, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("0111111x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2I, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("0111111x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hsetp2, InstEmit.Hsetp2C, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
@ -168,9 +168,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011100x00100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("0100110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
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);
|
||||
@ -181,12 +181,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("010110110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011011x0101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("010010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
Add("010110110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpR, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("0011011x0110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpI, InstProps.Ra | InstProps.Ib | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
Add("010010110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
@ -196,17 +196,17 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.LPd);
|
||||
Add("0011011x11010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.LPd);
|
||||
Add("0100101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaC, InstProps.Rd | InstProps.Ra | InstProps.LPd);
|
||||
Add("0101101111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
|
||||
Add("000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiC, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.LPd);
|
||||
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("0101110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.LPd);
|
||||
Add("0011100x01000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.LPd);
|
||||
Add("0100110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopC, InstProps.Rd | InstProps.Ra | InstProps.LPd);
|
||||
Add("0101101111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3R, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
|
||||
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);
|
||||
@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("1110111111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pixld, InstEmit.Pixld, InstProps.Rd | InstProps.Ra | InstProps.VPd);
|
||||
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);
|
||||
@ -236,14 +236,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101000010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pset, InstEmit.Pset, InstProps.Rd | InstProps.Ps);
|
||||
Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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("1110101111111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Red, InstEmit.Red, InstProps.Ra | InstProps.Rb2);
|
||||
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);
|
||||
@ -251,16 +251,16 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Ps);
|
||||
Add("0011100x10100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||
Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||
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("1110111100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shfl, InstEmit.Shfl, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.LPd);
|
||||
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);
|
||||
@ -276,12 +276,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("1110101011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCasB, InstEmit.SuatomCasB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc | InstProps.SPd);
|
||||
Add("1110101x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuatomCas, InstEmit.SuatomCas, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.SPd);
|
||||
Add("111010110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldDB, InstEmit.SuldDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("1110101100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldD, InstEmit.SuldD, InstProps.Rd | InstProps.Ra | InstProps.SPd | InstProps.Tex);
|
||||
Add("11101011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuldB, InstEmit.SuldB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.SPd | InstProps.TexB);
|
||||
Add("11101011000x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Suld, InstEmit.Suld, InstProps.Rd | InstProps.Ra | InstProps.SPd | 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);
|
||||
@ -289,23 +289,23 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("11000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tex, InstEmit.Tex, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
|
||||
Add("1101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TexB, InstEmit.TexB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | 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("11011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld, InstEmit.Tld, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
|
||||
Add("11011101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TldB, InstEmit.TldB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | 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("110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4, InstEmit.Tld4, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
|
||||
Add("1101111011xxxxxxxxxxxxx0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Tld4B, InstEmit.Tld4B, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | 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("110111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txd, InstEmit.Txd, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | InstProps.Tex);
|
||||
Add("1101111001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxdB, InstEmit.TxdB, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.TPd | 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);
|
||||
@ -313,10 +313,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
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("0101000011011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vote, InstEmit.Vote, InstProps.Rd | InstProps.VPd | InstProps.Ps);
|
||||
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("0101000011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vsetp, InstEmit.Vsetp, InstProps.Ra | InstProps.Rb | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||
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);
|
||||
|
@ -61,6 +61,16 @@ namespace Ryujinx.Graphics.Shader
|
||||
return 16;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsFragmentShaderInterlock()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsFragmentShaderOrderingIntel()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QueryHostSupportsImageLoadFormatted()
|
||||
{
|
||||
return true;
|
||||
|
@ -56,14 +56,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Cont(EmitterContext context)
|
||||
{
|
||||
InstContUnsup op = context.GetOp<InstContUnsup>();
|
||||
InstCont op = context.GetOp<InstCont>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction ContUnsup is not implemented.");
|
||||
}
|
||||
|
||||
public static void Cset(EmitterContext context)
|
||||
{
|
||||
InstCsetUnsup op = context.GetOp<InstCsetUnsup>();
|
||||
InstCset op = context.GetOp<InstCset>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction CsetUnsup is not implemented.");
|
||||
}
|
||||
|
@ -67,7 +67,24 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
InstCal op = context.GetOp<InstCal>();
|
||||
|
||||
context.Call(context.GetFunctionId(context.CurrOp.GetAbsoluteAddress()), false);
|
||||
DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress());
|
||||
|
||||
if (function.IsCompilerGenerated)
|
||||
{
|
||||
switch (function.Type)
|
||||
{
|
||||
case FunctionType.BuiltInFSIBegin:
|
||||
context.FSIBegin();
|
||||
break;
|
||||
case FunctionType.BuiltInFSIEnd:
|
||||
context.FSIEnd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Call(function.Id, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Exit(EmitterContext context)
|
||||
|
@ -109,28 +109,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
InstSuldDB op = context.GetOp<InstSuldDB>();
|
||||
|
||||
EmitSuld(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
|
||||
EmitSuld(context, op.CacheOp, 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<InstSuldD>();
|
||||
|
||||
EmitSuld(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
|
||||
EmitSuld(context, op.CacheOp, 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<InstSuldB>();
|
||||
|
||||
EmitSuld(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: true);
|
||||
EmitSuld(context, op.CacheOp, 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<InstSuld>();
|
||||
|
||||
EmitSuld(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
|
||||
EmitSuld(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
|
||||
}
|
||||
|
||||
public static void SuredB(EmitterContext context)
|
||||
@ -151,28 +151,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
InstSustDB op = context.GetOp<InstSustDB>();
|
||||
|
||||
EmitSust(context, op.Dim, op.Size, 0, 0, op.SrcA, op.Dest, op.SrcC, useComponents: false, op.Ba, isBindless: true);
|
||||
EmitSust(context, op.CacheOp, 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<InstSustD>();
|
||||
|
||||
EmitSust(context, op.Dim, op.Size, op.TidB, 0, op.SrcA, op.Dest, 0, useComponents: false, op.Ba, isBindless: false);
|
||||
EmitSust(context, op.CacheOp, 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<InstSustB>();
|
||||
|
||||
EmitSust(context, op.Dim, 0, 0, op.Rgba, op.SrcA, op.Dest, op.SrcC, useComponents: true, false, isBindless: true);
|
||||
EmitSust(context, op.CacheOp, 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<InstSust>();
|
||||
|
||||
EmitSust(context, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
|
||||
EmitSust(context, op.CacheOp, op.Dim, 0, op.TidB, op.Rgba, op.SrcA, op.Dest, 0, useComponents: true, false, isBindless: false);
|
||||
}
|
||||
|
||||
private static void EmitSuatom(
|
||||
@ -299,6 +299,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
private static void EmitSuld(
|
||||
EmitterContext context,
|
||||
CacheOpLd cacheOp,
|
||||
SuDim dimensions,
|
||||
SuSize size,
|
||||
int imm,
|
||||
@ -363,6 +364,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||
|
||||
if (cacheOp == CacheOpLd.Cg)
|
||||
{
|
||||
flags |= TextureFlags.Coherent;
|
||||
}
|
||||
|
||||
if (useComponents)
|
||||
{
|
||||
for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
|
||||
@ -546,6 +552,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
private static void EmitSust(
|
||||
EmitterContext context,
|
||||
CacheOpSt cacheOp,
|
||||
SuDim dimensions,
|
||||
SuSize size,
|
||||
int imm,
|
||||
@ -654,6 +661,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||
|
||||
if (cacheOp == CacheOpSt.Cg)
|
||||
{
|
||||
flags |= TextureFlags.Coherent;
|
||||
}
|
||||
|
||||
TextureOperation operation = context.CreateTextureOperation(
|
||||
Instruction.ImageStore,
|
||||
type,
|
||||
|
@ -62,6 +62,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||
EmitVertex,
|
||||
EndPrimitive,
|
||||
ExponentB2,
|
||||
FSIBegin,
|
||||
FSIEnd,
|
||||
FindFirstSetS32,
|
||||
FindFirstSetU32,
|
||||
Floor,
|
||||
|
@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||
LodLevel = 1 << 5,
|
||||
Offset = 1 << 6,
|
||||
Offsets = 1 << 7,
|
||||
Coherent = 1 << 8,
|
||||
|
||||
AtomicMask = 15 << 16,
|
||||
|
||||
|
@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
OperandType.Argument => VariableType.S32,
|
||||
OperandType.Attribute => VariableType.F32,
|
||||
OperandType.AttributePerPatch => VariableType.F32,
|
||||
OperandType.Constant => VariableType.S32,
|
||||
|
@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
// Integer sampled textures must be noted for resolution scaling.
|
||||
ResScaleUnsupported = 1 << 0,
|
||||
NeedsScaleValue = 1 << 1,
|
||||
ImageStore = 1 << 2
|
||||
ImageStore = 1 << 2,
|
||||
ImageCoherent = 1 << 3
|
||||
}
|
||||
}
|
||||
|
@ -10,24 +10,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
class EmitterContext
|
||||
{
|
||||
public Block CurrBlock { get; set; }
|
||||
public InstOp CurrOp { get; set; }
|
||||
|
||||
public DecodedProgram Program { get; }
|
||||
public ShaderConfig Config { get; }
|
||||
|
||||
public bool IsNonMain { get; }
|
||||
|
||||
public Block CurrBlock { get; set; }
|
||||
public InstOp CurrOp { get; set; }
|
||||
|
||||
public int OperationsCount => _operations.Count;
|
||||
|
||||
private readonly IReadOnlyDictionary<ulong, int> _funcs;
|
||||
private readonly List<Operation> _operations;
|
||||
private readonly Dictionary<ulong, Operand> _labels;
|
||||
|
||||
public EmitterContext(ShaderConfig config, bool isNonMain, IReadOnlyDictionary<ulong, int> funcs)
|
||||
public EmitterContext(DecodedProgram program, ShaderConfig config, bool isNonMain)
|
||||
{
|
||||
Program = program;
|
||||
Config = config;
|
||||
IsNonMain = isNonMain;
|
||||
_funcs = funcs;
|
||||
_operations = new List<Operation>();
|
||||
_labels = new Dictionary<ulong, Operand>();
|
||||
}
|
||||
@ -154,11 +154,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return label;
|
||||
}
|
||||
|
||||
public int GetFunctionId(ulong address)
|
||||
{
|
||||
return _funcs[address];
|
||||
}
|
||||
|
||||
public void PrepareForReturn()
|
||||
{
|
||||
if (!IsNonMain && Config.Stage == ShaderStage.Fragment)
|
||||
@ -195,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
Operand isBgra = Attribute(AttributeConsts.FragmentOutputIsBgraBase + rtIndex * 4);
|
||||
|
||||
Operand lblIsBgra = Label();
|
||||
Operand lblEnd = Label();
|
||||
Operand lblEnd = Label();
|
||||
|
||||
this.BranchIfTrue(lblIsBgra, isBgra);
|
||||
|
||||
|
@ -361,6 +361,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return context.Add(Instruction.SwizzleAdd, Local(), a, b, Const(mask));
|
||||
}
|
||||
|
||||
public static void FSIBegin(this EmitterContext context)
|
||||
{
|
||||
context.Add(Instruction.FSIBegin);
|
||||
}
|
||||
|
||||
public static void FSIEnd(this EmitterContext context)
|
||||
{
|
||||
context.Add(Instruction.FSIEnd);
|
||||
}
|
||||
|
||||
public static Operand GroupMemoryBarrier(this EmitterContext context)
|
||||
{
|
||||
return context.Add(Instruction.GroupMemoryBarrier);
|
||||
|
866
Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
Normal file
866
Ryujinx.Graphics.Shader/Translation/FunctionMatch.cs
Normal file
@ -0,0 +1,866 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
static class FunctionMatch
|
||||
{
|
||||
private static IPatternTreeNode[] _fsiGetAddressTree = PatternTrees.GetFsiGetAddress();
|
||||
private static IPatternTreeNode[] _fsiGetAddressV2Tree = PatternTrees.GetFsiGetAddressV2();
|
||||
private static IPatternTreeNode[] _fsiIsLastWarpThreadPatternTree = PatternTrees.GetFsiIsLastWarpThread();
|
||||
private static IPatternTreeNode[] _fsiBeginPatternTree = PatternTrees.GetFsiBeginPattern();
|
||||
private static IPatternTreeNode[] _fsiEndPatternTree = PatternTrees.GetFsiEndPattern();
|
||||
|
||||
public static void RunPass(DecodedProgram program)
|
||||
{
|
||||
byte[] externalRegs = new byte[4];
|
||||
bool hasGetAddress = false;
|
||||
|
||||
foreach (DecodedFunction function in program)
|
||||
{
|
||||
if (function == program.MainFunction)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int externalReg4 = 0;
|
||||
|
||||
TreeNode[] functionTree = BuildTree(function.Blocks);
|
||||
|
||||
if (Matches(_fsiGetAddressTree, functionTree))
|
||||
{
|
||||
externalRegs[1] = functionTree[0].GetRd();
|
||||
externalRegs[2] = functionTree[2].GetRd();
|
||||
externalRegs[3] = functionTree[1].GetRd();
|
||||
externalReg4 = functionTree[3].GetRd();
|
||||
}
|
||||
else if (Matches(_fsiGetAddressV2Tree, functionTree))
|
||||
{
|
||||
externalRegs[1] = functionTree[2].GetRd();
|
||||
externalRegs[2] = functionTree[1].GetRd();
|
||||
externalRegs[3] = functionTree[0].GetRd();
|
||||
externalReg4 = functionTree[3].GetRd();
|
||||
}
|
||||
|
||||
// Ensure the register allocation is valid.
|
||||
// If so, then we have a match.
|
||||
if (externalRegs[1] != externalRegs[2] &&
|
||||
externalRegs[2] != externalRegs[3] &&
|
||||
externalRegs[1] != externalRegs[3] &&
|
||||
externalRegs[1] + 1 != externalRegs[2] &&
|
||||
externalRegs[1] + 1 != externalRegs[3] &&
|
||||
externalRegs[1] + 1 == externalReg4 &&
|
||||
externalRegs[2] != RegisterConsts.RegisterZeroIndex &&
|
||||
externalRegs[3] != RegisterConsts.RegisterZeroIndex &&
|
||||
externalReg4 != RegisterConsts.RegisterZeroIndex)
|
||||
{
|
||||
hasGetAddress = true;
|
||||
function.Type = FunctionType.Unused;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (DecodedFunction function in program)
|
||||
{
|
||||
if (function.IsCompilerGenerated || function == program.MainFunction)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasGetAddress)
|
||||
{
|
||||
TreeNode[] functionTree = BuildTree(function.Blocks);
|
||||
|
||||
if (MatchesFsi(_fsiBeginPatternTree, program, function, functionTree, externalRegs))
|
||||
{
|
||||
function.Type = FunctionType.BuiltInFSIBegin;
|
||||
continue;
|
||||
}
|
||||
else if (MatchesFsi(_fsiEndPatternTree, program, function, functionTree, externalRegs))
|
||||
{
|
||||
function.Type = FunctionType.BuiltInFSIEnd;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct TreeNodeUse
|
||||
{
|
||||
public TreeNode Node { get; }
|
||||
public int Index { get; }
|
||||
public bool Inverted { get; }
|
||||
|
||||
private TreeNodeUse(int index, bool inverted, TreeNode node)
|
||||
{
|
||||
Index = index;
|
||||
Inverted = inverted;
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public TreeNodeUse(int index, TreeNode node) : this(index, false, node)
|
||||
{
|
||||
}
|
||||
|
||||
public TreeNodeUse Flip()
|
||||
{
|
||||
return new TreeNodeUse(Index, !Inverted, Node);
|
||||
}
|
||||
}
|
||||
|
||||
private enum TreeNodeType : byte
|
||||
{
|
||||
Op,
|
||||
Label
|
||||
}
|
||||
|
||||
private class TreeNode
|
||||
{
|
||||
public readonly InstOp Op;
|
||||
public readonly List<TreeNodeUse> Uses;
|
||||
public TreeNodeType Type { get; }
|
||||
public byte Order { get; }
|
||||
|
||||
public TreeNode(byte order)
|
||||
{
|
||||
Type = TreeNodeType.Label;
|
||||
Order = order;
|
||||
}
|
||||
|
||||
public TreeNode(InstOp op, byte order)
|
||||
{
|
||||
Op = op;
|
||||
Uses = new List<TreeNodeUse>();
|
||||
Type = TreeNodeType.Op;
|
||||
Order = order;
|
||||
}
|
||||
|
||||
public byte GetPd()
|
||||
{
|
||||
return (byte)((Op.RawOpCode >> 3) & 7);
|
||||
}
|
||||
|
||||
public byte GetRd()
|
||||
{
|
||||
return (byte)Op.RawOpCode;
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeNode[] BuildTree(Block[] blocks)
|
||||
{
|
||||
List<TreeNode> nodes = new List<TreeNode>();
|
||||
|
||||
Dictionary<ulong, TreeNode> labels = new Dictionary<ulong, TreeNode>();
|
||||
|
||||
TreeNodeUse[] predDefs = new TreeNodeUse[RegisterConsts.PredsCount];
|
||||
TreeNodeUse[] gprDefs = new TreeNodeUse[RegisterConsts.GprsCount];
|
||||
|
||||
void DefPred(byte predIndex, int index, TreeNode node)
|
||||
{
|
||||
if (predIndex != RegisterConsts.PredicateTrueIndex)
|
||||
{
|
||||
predDefs[predIndex] = new TreeNodeUse(index, node);
|
||||
}
|
||||
}
|
||||
|
||||
void DefGpr(byte regIndex, int index, TreeNode node)
|
||||
{
|
||||
if (regIndex != RegisterConsts.RegisterZeroIndex)
|
||||
{
|
||||
gprDefs[regIndex] = new TreeNodeUse(index, node);
|
||||
}
|
||||
}
|
||||
|
||||
TreeNodeUse UsePred(byte predIndex, bool predInv)
|
||||
{
|
||||
if (predIndex != RegisterConsts.PredicateTrueIndex)
|
||||
{
|
||||
TreeNodeUse use = predDefs[predIndex];
|
||||
|
||||
if (use.Node != null)
|
||||
{
|
||||
nodes.Remove(use.Node);
|
||||
}
|
||||
else
|
||||
{
|
||||
use = new TreeNodeUse(-(predIndex + 2), null);
|
||||
}
|
||||
|
||||
return predInv ? use.Flip() : use;
|
||||
}
|
||||
|
||||
return new TreeNodeUse(-1, null);
|
||||
}
|
||||
|
||||
TreeNodeUse UseGpr(byte regIndex)
|
||||
{
|
||||
if (regIndex != RegisterConsts.RegisterZeroIndex)
|
||||
{
|
||||
TreeNodeUse use = gprDefs[regIndex];
|
||||
|
||||
if (use.Node != null)
|
||||
{
|
||||
nodes.Remove(use.Node);
|
||||
}
|
||||
else
|
||||
{
|
||||
use = new TreeNodeUse(-(regIndex + 2), null);
|
||||
}
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
return new TreeNodeUse(-1, null);
|
||||
}
|
||||
|
||||
byte order = 0;
|
||||
|
||||
for (int index = 0; index < blocks.Length; index++)
|
||||
{
|
||||
Block block = blocks[index];
|
||||
|
||||
if (block.Predecessors.Count > 1)
|
||||
{
|
||||
TreeNode label = new TreeNode(order++);
|
||||
nodes.Add(label);
|
||||
labels.Add(block.Address, label);
|
||||
}
|
||||
|
||||
for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
|
||||
{
|
||||
InstOp op = block.OpCodes[opIndex];
|
||||
|
||||
TreeNode node = new TreeNode(op, IsOrderDependant(op.Name) ? order : (byte)0);
|
||||
|
||||
// Add uses.
|
||||
|
||||
if (!op.Props.HasFlag(InstProps.NoPred))
|
||||
{
|
||||
byte predIndex = (byte)((op.RawOpCode >> 16) & 7);
|
||||
bool predInv = (op.RawOpCode & 0x80000) != 0;
|
||||
node.Uses.Add(UsePred(predIndex, predInv));
|
||||
}
|
||||
|
||||
if (op.Props.HasFlag(InstProps.Ps))
|
||||
{
|
||||
byte predIndex = (byte)((op.RawOpCode >> 39) & 7);
|
||||
bool predInv = (op.RawOpCode & 0x40000000000) != 0;
|
||||
node.Uses.Add(UsePred(predIndex, predInv));
|
||||
}
|
||||
|
||||
if (op.Props.HasFlag(InstProps.Ra))
|
||||
{
|
||||
byte ra = (byte)(op.RawOpCode >> 8);
|
||||
node.Uses.Add(UseGpr(ra));
|
||||
}
|
||||
|
||||
if ((op.Props & (InstProps.Rb | InstProps.Rb2)) != 0)
|
||||
{
|
||||
byte rb = op.Props.HasFlag(InstProps.Rb2) ? (byte)op.RawOpCode : (byte)(op.RawOpCode >> 20);
|
||||
node.Uses.Add(UseGpr(rb));
|
||||
}
|
||||
|
||||
if (op.Props.HasFlag(InstProps.Rc))
|
||||
{
|
||||
byte rc = (byte)(op.RawOpCode >> 39);
|
||||
node.Uses.Add(UseGpr(rc));
|
||||
}
|
||||
|
||||
if (op.Name == InstName.Bra && labels.TryGetValue(op.GetAbsoluteAddress(), out TreeNode label))
|
||||
{
|
||||
node.Uses.Add(new TreeNodeUse(0, label));
|
||||
}
|
||||
|
||||
// Make definitions.
|
||||
|
||||
int defIndex = 0;
|
||||
|
||||
InstProps pdType = op.Props & InstProps.PdMask;
|
||||
|
||||
if (pdType != 0)
|
||||
{
|
||||
int bit = pdType switch
|
||||
{
|
||||
InstProps.Pd => 3,
|
||||
InstProps.LPd => 48,
|
||||
InstProps.SPd => 30,
|
||||
InstProps.TPd => 51,
|
||||
InstProps.VPd => 45,
|
||||
_ => throw new InvalidOperationException($"Table has unknown predicate destination {pdType}.")
|
||||
};
|
||||
|
||||
byte predIndex = (byte)((op.RawOpCode >> bit) & 7);
|
||||
DefPred(predIndex, defIndex++, node);
|
||||
}
|
||||
|
||||
if (op.Props.HasFlag(InstProps.Rd))
|
||||
{
|
||||
byte rd = (byte)op.RawOpCode;
|
||||
DefGpr(rd, defIndex++, node);
|
||||
}
|
||||
|
||||
nodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
return nodes.ToArray();
|
||||
}
|
||||
|
||||
private static bool IsOrderDependant(InstName name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case InstName.Atom:
|
||||
case InstName.AtomCas:
|
||||
case InstName.Atoms:
|
||||
case InstName.AtomsCas:
|
||||
case InstName.Ld:
|
||||
case InstName.Ldg:
|
||||
case InstName.Ldl:
|
||||
case InstName.Lds:
|
||||
case InstName.Suatom:
|
||||
case InstName.SuatomB:
|
||||
case InstName.SuatomB2:
|
||||
case InstName.SuatomCas:
|
||||
case InstName.SuatomCasB:
|
||||
case InstName.Suld:
|
||||
case InstName.SuldB:
|
||||
case InstName.SuldD:
|
||||
case InstName.SuldDB:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private interface IPatternTreeNode
|
||||
{
|
||||
List<PatternTreeNodeUse> Uses { get; }
|
||||
InstName Name { get; }
|
||||
TreeNodeType Type { get; }
|
||||
byte Order { get; }
|
||||
bool IsImm { get; }
|
||||
bool Matches(in InstOp opInfo);
|
||||
}
|
||||
|
||||
private struct PatternTreeNodeUse
|
||||
{
|
||||
public IPatternTreeNode Node { get; }
|
||||
public int Index { get; }
|
||||
public bool Inverted { get; }
|
||||
public PatternTreeNodeUse Inv => new PatternTreeNodeUse(Index, !Inverted, Node);
|
||||
|
||||
private PatternTreeNodeUse(int index, bool inverted, IPatternTreeNode node)
|
||||
{
|
||||
Index = index;
|
||||
Inverted = inverted;
|
||||
Node = node;
|
||||
}
|
||||
|
||||
public PatternTreeNodeUse(int index, IPatternTreeNode node) : this(index, false, node)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class PatternTreeNode<T> : IPatternTreeNode
|
||||
{
|
||||
public List<PatternTreeNodeUse> Uses { get; }
|
||||
private readonly Func<T, bool> _match;
|
||||
|
||||
public InstName Name { get; }
|
||||
public TreeNodeType Type { get; }
|
||||
public byte Order { get; }
|
||||
public bool IsImm { get; }
|
||||
public PatternTreeNodeUse Out => new PatternTreeNodeUse(0, this);
|
||||
|
||||
public PatternTreeNode(InstName name, Func<T, bool> match, TreeNodeType type = TreeNodeType.Op, byte order = 0, bool isImm = false)
|
||||
{
|
||||
Name = name;
|
||||
_match = match;
|
||||
Type = type;
|
||||
Order = order;
|
||||
IsImm = isImm;
|
||||
Uses = new List<PatternTreeNodeUse>();
|
||||
}
|
||||
|
||||
public PatternTreeNode<T> Use(PatternTreeNodeUse use)
|
||||
{
|
||||
Uses.Add(use);
|
||||
return this;
|
||||
}
|
||||
|
||||
public PatternTreeNodeUse OutAt(int index)
|
||||
{
|
||||
return new PatternTreeNodeUse(index, this);
|
||||
}
|
||||
|
||||
public bool Matches(in InstOp opInfo)
|
||||
{
|
||||
if (opInfo.Name != Name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong rawOp = opInfo.RawOpCode;
|
||||
T op = Unsafe.As<ulong, T>(ref rawOp);
|
||||
|
||||
if (!_match(op))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool MatchesFsi(
|
||||
IPatternTreeNode[] pattern,
|
||||
DecodedProgram program,
|
||||
DecodedFunction function,
|
||||
TreeNode[] functionTree,
|
||||
byte[] externalRegs)
|
||||
{
|
||||
if (function.Blocks.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
InstOp callOp = function.Blocks[0].GetLastOp();
|
||||
|
||||
if (callOp.Name != InstName.Cal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DecodedFunction callTarget = program.GetFunctionByAddress(callOp.GetAbsoluteAddress());
|
||||
TreeNode[] callTargetTree = null;
|
||||
|
||||
if (callTarget == null || !Matches(_fsiIsLastWarpThreadPatternTree, callTargetTree = BuildTree(callTarget.Blocks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
externalRegs[0] = callTargetTree[0].GetPd();
|
||||
|
||||
if (Matches(pattern, functionTree, externalRegs))
|
||||
{
|
||||
callTarget.RemoveCaller(function);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool Matches(IPatternTreeNode[] pTree, TreeNode[] cTree, byte[] externalRegs = null)
|
||||
{
|
||||
if (pTree.Length != cTree.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = 0; index < pTree.Length; index++)
|
||||
{
|
||||
if (!Matches(pTree[index], cTree[index], externalRegs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool Matches(IPatternTreeNode pTreeNode, TreeNode cTreeNode, byte[] externalRegs)
|
||||
{
|
||||
if (!pTreeNode.Matches(in cTreeNode.Op) ||
|
||||
pTreeNode.Type != cTreeNode.Type ||
|
||||
pTreeNode.Order != cTreeNode.Order ||
|
||||
pTreeNode.IsImm != cTreeNode.Op.Props.HasFlag(InstProps.Ib))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pTreeNode.Type == TreeNodeType.Op)
|
||||
{
|
||||
if (pTreeNode.Uses.Count != cTreeNode.Uses.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int index = 0; index < pTreeNode.Uses.Count; index++)
|
||||
{
|
||||
var pUse = pTreeNode.Uses[index];
|
||||
var cUse = cTreeNode.Uses[index];
|
||||
|
||||
if (pUse.Index <= -2)
|
||||
{
|
||||
if (externalRegs[-pUse.Index - 2] != (-cUse.Index - 2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (pUse.Index != cUse.Index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pUse.Inverted != cUse.Inverted || (pUse.Node == null) != (cUse.Node == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pUse.Node != null && !Matches(pUse.Node, cUse.Node, externalRegs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class PatternTrees
|
||||
{
|
||||
public static IPatternTreeNode[] GetFsiGetAddress()
|
||||
{
|
||||
var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
|
||||
var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
|
||||
|
||||
return new IPatternTreeNode[]
|
||||
{
|
||||
Iscadd(cc: true, 2, 0, 404)
|
||||
.Use(PT)
|
||||
.Use(Iscadd(cc: false, 8)
|
||||
.Use(PT)
|
||||
.Use(Lop32i(LogicOp.And, 0xff)
|
||||
.Use(PT)
|
||||
.Use(affinityValue).Out)
|
||||
.Use(Lop32i(LogicOp.And, 0xff)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue).Out).Out),
|
||||
ShrU32W(16)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue),
|
||||
Iadd32i(0x200)
|
||||
.Use(PT)
|
||||
.Use(Lop32i(LogicOp.And, 0xfe00)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue).Out),
|
||||
Iadd(x: true, 0, 405).Use(PT).Use(RZ),
|
||||
Ret().Use(PT)
|
||||
};
|
||||
}
|
||||
|
||||
public static IPatternTreeNode[] GetFsiGetAddressV2()
|
||||
{
|
||||
var affinityValue = S2r(SReg.Affinity).Use(PT).Out;
|
||||
var orderingTicketValue = S2r(SReg.OrderingTicket).Use(PT).Out;
|
||||
|
||||
return new IPatternTreeNode[]
|
||||
{
|
||||
ShrU32W(16)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue),
|
||||
Iadd32i(0x200)
|
||||
.Use(PT)
|
||||
.Use(Lop32i(LogicOp.And, 0xfe00)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue).Out),
|
||||
Iscadd(cc: true, 2, 0, 404)
|
||||
.Use(PT)
|
||||
.Use(Bfi(0x808)
|
||||
.Use(PT)
|
||||
.Use(affinityValue)
|
||||
.Use(Lop32i(LogicOp.And, 0xff)
|
||||
.Use(PT)
|
||||
.Use(orderingTicketValue).Out).Out),
|
||||
Iadd(x: true, 0, 405).Use(PT).Use(RZ),
|
||||
Ret().Use(PT)
|
||||
};
|
||||
}
|
||||
|
||||
public static IPatternTreeNode[] GetFsiIsLastWarpThread()
|
||||
{
|
||||
var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
|
||||
var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
|
||||
|
||||
return new IPatternTreeNode[]
|
||||
{
|
||||
IsetpU32(IComp.Eq)
|
||||
.Use(PT)
|
||||
.Use(PT)
|
||||
.Use(FloU32()
|
||||
.Use(PT)
|
||||
.Use(Vote(VoteMode.Any)
|
||||
.Use(PT)
|
||||
.Use(IsetpU32(IComp.Ne)
|
||||
.Use(PT)
|
||||
.Use(PT)
|
||||
.Use(Lop(negB: true, LogicOp.PassB)
|
||||
.Use(PT)
|
||||
.Use(RZ)
|
||||
.Use(threadKillValue).OutAt(1))
|
||||
.Use(RZ).Out).OutAt(1)).Out)
|
||||
.Use(laneIdValue),
|
||||
Ret().Use(PT)
|
||||
};
|
||||
}
|
||||
|
||||
public static IPatternTreeNode[] GetFsiBeginPattern()
|
||||
{
|
||||
var addressLowValue = CallArg(1);
|
||||
|
||||
static PatternTreeNodeUse HighU16Equals(PatternTreeNodeUse x)
|
||||
{
|
||||
var expectedValue = CallArg(3);
|
||||
|
||||
return IsetpU32(IComp.Eq)
|
||||
.Use(PT)
|
||||
.Use(PT)
|
||||
.Use(ShrU32W(16).Use(PT).Use(x).Out)
|
||||
.Use(expectedValue).Out;
|
||||
}
|
||||
|
||||
PatternTreeNode<byte> label;
|
||||
|
||||
return new IPatternTreeNode[]
|
||||
{
|
||||
Cal(),
|
||||
Ret().Use(CallArg(0).Inv),
|
||||
Ret()
|
||||
.Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32)
|
||||
.Use(PT)
|
||||
.Use(addressLowValue).Out)),
|
||||
label = Label(),
|
||||
Bra()
|
||||
.Use(HighU16Equals(LdgE(CacheOpLd.Cg, LsSize.B32, 1)
|
||||
.Use(PT)
|
||||
.Use(addressLowValue).Out).Inv)
|
||||
.Use(label.Out),
|
||||
Ret().Use(PT)
|
||||
};
|
||||
}
|
||||
|
||||
public static IPatternTreeNode[] GetFsiEndPattern()
|
||||
{
|
||||
var voteResult = Vote(VoteMode.All).Use(PT).Use(PT).OutAt(1);
|
||||
var popcResult = Popc().Use(PT).Use(voteResult).Out;
|
||||
var threadKillValue = S2r(SReg.ThreadKill).Use(PT).Out;
|
||||
var laneIdValue = S2r(SReg.LaneId).Use(PT).Out;
|
||||
|
||||
var addressLowValue = CallArg(1);
|
||||
var incrementValue = CallArg(2);
|
||||
|
||||
return new IPatternTreeNode[]
|
||||
{
|
||||
Cal(),
|
||||
Ret().Use(CallArg(0).Inv),
|
||||
Membar(Decoders.Membar.Vc).Use(PT),
|
||||
Ret().Use(IsetpU32(IComp.Ne)
|
||||
.Use(PT)
|
||||
.Use(PT)
|
||||
.Use(threadKillValue)
|
||||
.Use(RZ).Out),
|
||||
RedE(RedOp.Add, AtomSize.U32)
|
||||
.Use(IsetpU32(IComp.Eq)
|
||||
.Use(PT)
|
||||
.Use(PT)
|
||||
.Use(FloU32()
|
||||
.Use(PT)
|
||||
.Use(voteResult).Out)
|
||||
.Use(laneIdValue).Out)
|
||||
.Use(addressLowValue)
|
||||
.Use(Xmad(XmadCop.Cbcc, psl: true, hiloA: true, hiloB: true)
|
||||
.Use(PT)
|
||||
.Use(incrementValue)
|
||||
.Use(Xmad(XmadCop.Cfull, mrg: true, hiloB: true)
|
||||
.Use(PT)
|
||||
.Use(incrementValue)
|
||||
.Use(popcResult)
|
||||
.Use(RZ).Out)
|
||||
.Use(Xmad(XmadCop.Cfull)
|
||||
.Use(PT)
|
||||
.Use(incrementValue)
|
||||
.Use(popcResult)
|
||||
.Use(RZ).Out).Out),
|
||||
Ret().Use(PT)
|
||||
};
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstBfiI> Bfi(int imm)
|
||||
{
|
||||
return new(InstName.Bfi, (op) => !op.WriteCC && op.Imm20 == imm, isImm: true);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstBra> Bra()
|
||||
{
|
||||
return new(InstName.Bra, (op) => op.Ccc == Ccc.T && !op.Ca);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstCal> Cal()
|
||||
{
|
||||
return new(InstName.Cal, (op) => !op.Ca && op.Inc);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstFloR> FloU32()
|
||||
{
|
||||
return new(InstName.Flo, (op) => !op.Signed && !op.Sh && !op.NegB && !op.WriteCC);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstIaddC> Iadd(bool x, int cbufSlot, int cbufOffset)
|
||||
{
|
||||
return new(InstName.Iadd, (op) =>
|
||||
!op.Sat &&
|
||||
!op.WriteCC &&
|
||||
op.X == x &&
|
||||
op.AvgMode == AvgMode.NoNeg &&
|
||||
op.CbufSlot == cbufSlot &&
|
||||
op.CbufOffset == cbufOffset);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstIadd32i> Iadd32i(int imm)
|
||||
{
|
||||
return new(InstName.Iadd32i, (op) => !op.Sat && !op.WriteCC && !op.X && op.AvgMode == AvgMode.NoNeg && op.Imm32 == imm);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstIscaddR> Iscadd(bool cc, int imm)
|
||||
{
|
||||
return new(InstName.Iscadd, (op) => op.WriteCC == cc && op.AvgMode == AvgMode.NoNeg && op.Imm5 == imm);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstIscaddC> Iscadd(bool cc, int imm, int cbufSlot, int cbufOffset)
|
||||
{
|
||||
return new(InstName.Iscadd, (op) =>
|
||||
op.WriteCC == cc &&
|
||||
op.AvgMode == AvgMode.NoNeg &&
|
||||
op.Imm5 == imm &&
|
||||
op.CbufSlot == cbufSlot &&
|
||||
op.CbufOffset == cbufOffset);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstIsetpR> IsetpU32(IComp comp)
|
||||
{
|
||||
return new(InstName.Isetp, (op) => !op.Signed && op.IComp == comp && op.Bop == BoolOp.And);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<byte> Label()
|
||||
{
|
||||
return new(InstName.Invalid, (op) => true, type: TreeNodeType.Label);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstLopR> Lop(bool negB, LogicOp logicOp)
|
||||
{
|
||||
return new(InstName.Lop, (op) => !op.NegA && op.NegB == negB && !op.WriteCC && !op.X && op.Lop == logicOp && op.PredicateOp == PredicateOp.F);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstLop32i> Lop32i(LogicOp logicOp, int imm)
|
||||
{
|
||||
return new(InstName.Lop32i, (op) => !op.NegA && !op.NegB && !op.X && !op.WriteCC && op.LogicOp == logicOp && op.Imm32 == imm);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstMembar> Membar(Membar membar)
|
||||
{
|
||||
return new(InstName.Membar, (op) => op.Membar == membar);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstPopcR> Popc()
|
||||
{
|
||||
return new(InstName.Popc, (op) => !op.NegB);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstRet> Ret()
|
||||
{
|
||||
return new(InstName.Ret, (op) => op.Ccc == Ccc.T);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstS2r> S2r(SReg reg)
|
||||
{
|
||||
return new(InstName.S2r, (op) => op.SReg == reg);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstShrI> ShrU32W(int imm)
|
||||
{
|
||||
return new(InstName.Shr, (op) => !op.Signed && !op.Brev && op.M && op.XMode == 0 && op.Imm20 == imm, isImm: true);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstLdg> LdgE(CacheOpLd cacheOp, LsSize size, byte order = 0)
|
||||
{
|
||||
return new(InstName.Ldg, (op) => op.E && op.CacheOp == cacheOp && op.LsSize == size, order: order);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstRed> RedE(RedOp redOp, AtomSize size, byte order = 0)
|
||||
{
|
||||
return new(InstName.Red, (op) => op.E && op.RedOp == redOp && op.RedSize == size, order: order);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstVote> Vote(VoteMode mode)
|
||||
{
|
||||
return new(InstName.Vote, (op) => op.VoteMode == mode);
|
||||
}
|
||||
|
||||
private static PatternTreeNode<InstXmadR> Xmad(XmadCop cop, bool psl = false, bool mrg = false, bool hiloA = false, bool hiloB = false)
|
||||
{
|
||||
return new(InstName.Xmad, (op) => op.XmadCop == cop && op.Psl == psl && op.Mrg == mrg && op.HiloA == hiloA && op.HiloB == hiloB);
|
||||
}
|
||||
|
||||
private static PatternTreeNodeUse PT => PTOrRZ();
|
||||
private static PatternTreeNodeUse RZ => PTOrRZ();
|
||||
private static PatternTreeNodeUse Undef => new PatternTreeNodeUse(0, null);
|
||||
|
||||
private static PatternTreeNodeUse CallArg(int index)
|
||||
{
|
||||
return new PatternTreeNodeUse(-(index + 2), null);
|
||||
}
|
||||
|
||||
private static PatternTreeNodeUse PTOrRZ()
|
||||
{
|
||||
return new PatternTreeNodeUse(-1, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintTreeNode(TreeNode node, string indentation)
|
||||
{
|
||||
Console.WriteLine($" {node.Op.Name}");
|
||||
|
||||
for (int i = 0; i < node.Uses.Count; i++)
|
||||
{
|
||||
TreeNodeUse use = node.Uses[i];
|
||||
bool last = i == node.Uses.Count - 1;
|
||||
char separator = last ? '`' : '|';
|
||||
|
||||
if (use.Node != null)
|
||||
{
|
||||
Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
|
||||
PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintTreeNode(IPatternTreeNode node, string indentation)
|
||||
{
|
||||
Console.WriteLine($" {node.Name}");
|
||||
|
||||
for (int i = 0; i < node.Uses.Count; i++)
|
||||
{
|
||||
PatternTreeNodeUse use = node.Uses[i];
|
||||
bool last = i == node.Uses.Count - 1;
|
||||
char separator = last ? '`' : '|';
|
||||
|
||||
if (use.Node != null)
|
||||
{
|
||||
Console.Write($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index})");
|
||||
PrintTreeNode(use.Node, indentation + (last ? " " : " | "));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{indentation} {separator}- ({(use.Inverted ? "INV " : "")}{use.Index}) NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -315,15 +315,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||
bool accurateType = inst != Instruction.Lod;
|
||||
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
||||
|
||||
if (isImage)
|
||||
{
|
||||
SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false);
|
||||
SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false, coherent);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool intCoords = flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
|
||||
SetUsedTextureOrImage(_usedTextures, cbufSlot, handle, type, TextureFormat.Unknown, intCoords, false, accurateType);
|
||||
SetUsedTextureOrImage(_usedTextures, cbufSlot, handle, type, TextureFormat.Unknown, intCoords, false, accurateType, coherent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,7 +336,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
TextureFormat format,
|
||||
bool intCoords,
|
||||
bool write,
|
||||
bool accurateType)
|
||||
bool accurateType,
|
||||
bool coherent)
|
||||
{
|
||||
var dimensions = type.GetDimensions();
|
||||
var isIndexed = type.HasFlag(SamplerType.Indexed);
|
||||
@ -361,6 +363,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
usageFlags |= TextureUsageFlags.ImageStore;
|
||||
}
|
||||
|
||||
if (coherent)
|
||||
{
|
||||
usageFlags |= TextureUsageFlags.ImageCoherent;
|
||||
}
|
||||
|
||||
int arraySize = isIndexed ? SamplerArraySize : 1;
|
||||
|
||||
for (int layer = 0; layer < arraySize; layer++)
|
||||
|
@ -4,7 +4,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation.Optimizations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@ -33,9 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
counts ??= new TranslationCounts();
|
||||
|
||||
Block[][] cfg = DecodeShader(address, gpuAccessor, options, counts, out ShaderConfig config);
|
||||
|
||||
return new TranslatorContext(address, cfg, config);
|
||||
return DecodeShader(address, gpuAccessor, options, counts);
|
||||
}
|
||||
|
||||
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
|
||||
@ -112,35 +110,29 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
return program;
|
||||
}
|
||||
|
||||
private static Block[][] DecodeShader(
|
||||
ulong address,
|
||||
IGpuAccessor gpuAccessor,
|
||||
TranslationOptions options,
|
||||
TranslationCounts counts,
|
||||
out ShaderConfig config)
|
||||
private static TranslatorContext DecodeShader(ulong address, IGpuAccessor gpuAccessor, TranslationOptions options, TranslationCounts counts)
|
||||
{
|
||||
Block[][] cfg;
|
||||
ShaderConfig config;
|
||||
DecodedProgram program;
|
||||
ulong maxEndAddress = 0;
|
||||
|
||||
if ((options.Flags & TranslationFlags.Compute) != 0)
|
||||
{
|
||||
config = new ShaderConfig(gpuAccessor, options, counts);
|
||||
|
||||
cfg = Decoder.Decode(config, address);
|
||||
program = Decoder.Decode(config, address);
|
||||
}
|
||||
else
|
||||
{
|
||||
config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, options, counts);
|
||||
|
||||
cfg = Decoder.Decode(config, address + HeaderSize);
|
||||
program = Decoder.Decode(config, address + HeaderSize);
|
||||
}
|
||||
|
||||
for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
|
||||
foreach (DecodedFunction function in program)
|
||||
{
|
||||
for (int blkIndex = 0; blkIndex < cfg[funcIndex].Length; blkIndex++)
|
||||
foreach (Block block in function.Blocks)
|
||||
{
|
||||
Block block = cfg[funcIndex][blkIndex];
|
||||
|
||||
if (maxEndAddress < block.EndAddress)
|
||||
{
|
||||
maxEndAddress = block.EndAddress;
|
||||
@ -164,36 +156,36 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
config.SizeAdd((int)maxEndAddress + (options.Flags.HasFlag(TranslationFlags.Compute) ? 0 : HeaderSize));
|
||||
|
||||
return cfg;
|
||||
return new TranslatorContext(address, program, config);
|
||||
}
|
||||
|
||||
internal static FunctionCode[] EmitShader(Block[][] cfg, ShaderConfig config, bool initializeOutputs, out int initializationOperations)
|
||||
internal static FunctionCode[] EmitShader(DecodedProgram program, ShaderConfig config, bool initializeOutputs, out int initializationOperations)
|
||||
{
|
||||
initializationOperations = 0;
|
||||
|
||||
Dictionary<ulong, int> funcIds = new Dictionary<ulong, int>();
|
||||
FunctionMatch.RunPass(program);
|
||||
|
||||
for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
|
||||
foreach (DecodedFunction function in program.OrderBy(x => x.Address).Where(x => !x.IsCompilerGenerated))
|
||||
{
|
||||
funcIds.Add(cfg[funcIndex][0].Address, funcIndex);
|
||||
program.AddFunctionAndSetId(function);
|
||||
}
|
||||
|
||||
List<FunctionCode> funcs = new List<FunctionCode>();
|
||||
FunctionCode[] functions = new FunctionCode[program.FunctionsWithIdCount];
|
||||
|
||||
for (int funcIndex = 0; funcIndex < cfg.Length; funcIndex++)
|
||||
for (int index = 0; index < functions.Length; index++)
|
||||
{
|
||||
EmitterContext context = new EmitterContext(config, funcIndex != 0, funcIds);
|
||||
EmitterContext context = new EmitterContext(program, config, index != 0);
|
||||
|
||||
if (initializeOutputs && funcIndex == 0)
|
||||
if (initializeOutputs && index == 0)
|
||||
{
|
||||
EmitOutputsInitialization(context, config);
|
||||
initializationOperations = context.OperationsCount;
|
||||
}
|
||||
|
||||
for (int blkIndex = 0; blkIndex < cfg[funcIndex].Length; blkIndex++)
|
||||
{
|
||||
Block block = cfg[funcIndex][blkIndex];
|
||||
DecodedFunction function = program.GetFunctionById(index);
|
||||
|
||||
foreach (Block block in function.Blocks)
|
||||
{
|
||||
context.CurrBlock = block;
|
||||
|
||||
context.MarkLabel(context.GetLabel(block.Address));
|
||||
@ -201,10 +193,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
EmitOps(context, block);
|
||||
}
|
||||
|
||||
funcs.Add(new FunctionCode(context.GetOperations()));
|
||||
functions[index] = new FunctionCode(context.GetOperations());
|
||||
}
|
||||
|
||||
return funcs.ToArray();
|
||||
return functions;
|
||||
}
|
||||
|
||||
private static void EmitOutputsInitialization(EmitterContext context, ShaderConfig config)
|
||||
|
@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
public class TranslatorContext
|
||||
{
|
||||
private readonly Block[][] _cfg;
|
||||
private readonly DecodedProgram _program;
|
||||
private ShaderConfig _config;
|
||||
|
||||
public ulong Address { get; }
|
||||
@ -23,11 +23,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
|
||||
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
|
||||
|
||||
internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
|
||||
internal TranslatorContext(ulong address, DecodedProgram program, ShaderConfig config)
|
||||
{
|
||||
Address = address;
|
||||
_program = program;
|
||||
_config = config;
|
||||
_cfg = cfg;
|
||||
}
|
||||
|
||||
private static bool IsUserAttribute(Operand operand)
|
||||
@ -141,13 +141,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||
nextStage._config.UsedInputAttributesPerPatch);
|
||||
}
|
||||
|
||||
FunctionCode[] code = EmitShader(_cfg, _config, initializeOutputs: other == null, out _);
|
||||
FunctionCode[] code = EmitShader(_program, _config, initializeOutputs: other == null, out _);
|
||||
|
||||
if (other != null)
|
||||
{
|
||||
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, 0);
|
||||
|
||||
FunctionCode[] otherCode = EmitShader(other._cfg, other._config, initializeOutputs: true, out int aStart);
|
||||
FunctionCode[] otherCode = EmitShader(other._program, other._config, initializeOutputs: true, out int aStart);
|
||||
|
||||
code = Combine(otherCode, code, aStart);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user