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
31 changed files with 1309 additions and 179 deletions
|
@ -6,6 +6,8 @@ namespace Ryujinx.Graphics.GAL
|
||||||
public bool HasVectorIndexingBug { get; }
|
public bool HasVectorIndexingBug { get; }
|
||||||
|
|
||||||
public bool SupportsAstcCompression { get; }
|
public bool SupportsAstcCompression { get; }
|
||||||
|
public bool SupportsFragmentShaderInterlock { get; }
|
||||||
|
public bool SupportsFragmentShaderOrderingIntel { get; }
|
||||||
public bool SupportsImageLoadFormatted { get; }
|
public bool SupportsImageLoadFormatted { get; }
|
||||||
public bool SupportsMismatchingViewFormat { get; }
|
public bool SupportsMismatchingViewFormat { get; }
|
||||||
public bool SupportsNonConstantTextureOffset { get; }
|
public bool SupportsNonConstantTextureOffset { get; }
|
||||||
|
@ -22,6 +24,8 @@ namespace Ryujinx.Graphics.GAL
|
||||||
bool hasFrontFacingBug,
|
bool hasFrontFacingBug,
|
||||||
bool hasVectorIndexingBug,
|
bool hasVectorIndexingBug,
|
||||||
bool supportsAstcCompression,
|
bool supportsAstcCompression,
|
||||||
|
bool supportsFragmentShaderInterlock,
|
||||||
|
bool supportsFragmentShaderOrderingIntel,
|
||||||
bool supportsImageLoadFormatted,
|
bool supportsImageLoadFormatted,
|
||||||
bool supportsMismatchingViewFormat,
|
bool supportsMismatchingViewFormat,
|
||||||
bool supportsNonConstantTextureOffset,
|
bool supportsNonConstantTextureOffset,
|
||||||
|
@ -36,6 +40,8 @@ namespace Ryujinx.Graphics.GAL
|
||||||
HasFrontFacingBug = hasFrontFacingBug;
|
HasFrontFacingBug = hasFrontFacingBug;
|
||||||
HasVectorIndexingBug = hasVectorIndexingBug;
|
HasVectorIndexingBug = hasVectorIndexingBug;
|
||||||
SupportsAstcCompression = supportsAstcCompression;
|
SupportsAstcCompression = supportsAstcCompression;
|
||||||
|
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
|
||||||
|
SupportsFragmentShaderOrderingIntel = supportsFragmentShaderOrderingIntel;
|
||||||
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
SupportsImageLoadFormatted = supportsImageLoadFormatted;
|
||||||
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
SupportsMismatchingViewFormat = supportsMismatchingViewFormat;
|
||||||
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset;
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the codegen (to be changed when codegen or guest format change).
|
/// Version of the codegen (to be changed when codegen or guest format change).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const ulong ShaderCodeGenVersion = 2741;
|
private const ulong ShaderCodeGenVersion = 2768;
|
||||||
|
|
||||||
// Progress reporting helpers
|
// Progress reporting helpers
|
||||||
private volatile int _shaderCount;
|
private volatile int _shaderCount;
|
||||||
|
|
|
@ -36,6 +36,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <returns>Host storage buffer alignment in bytes</returns>
|
/// <returns>Host storage buffer alignment in bytes</returns>
|
||||||
public int QueryHostStorageBufferOffsetAlignment() => _context.Capabilities.StorageBufferOffsetAlignment;
|
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>
|
/// <summary>
|
||||||
/// Queries host support for readable images without a explicit format declaration on the shader.
|
/// Queries host support for readable images without a explicit format declaration on the shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
static class HwCapabilities
|
static class HwCapabilities
|
||||||
{
|
{
|
||||||
private static readonly Lazy<bool> _supportsAstcCompression = new Lazy<bool>(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
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> _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> _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> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||||
private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck);
|
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> _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> _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> _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> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
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 UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
||||||
|
|
||||||
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
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 SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||||
|
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||||
public static bool SupportsQuads => _supportsQuads.Value;
|
public static bool SupportsQuads => _supportsQuads.Value;
|
||||||
|
@ -49,7 +54,6 @@ namespace Ryujinx.Graphics.OpenGL
|
||||||
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
||||||
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
||||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.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 SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
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.IntelWindows,
|
||||||
HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
|
HwCapabilities.Vendor == HwCapabilities.GpuVendor.AmdWindows,
|
||||||
HwCapabilities.SupportsAstcCompression,
|
HwCapabilities.SupportsAstcCompression,
|
||||||
|
HwCapabilities.SupportsFragmentShaderInterlock,
|
||||||
|
HwCapabilities.SupportsFragmentShaderOrdering,
|
||||||
HwCapabilities.SupportsImageLoadFormatted,
|
HwCapabilities.SupportsImageLoadFormatted,
|
||||||
HwCapabilities.SupportsMismatchingViewFormat,
|
HwCapabilities.SupportsMismatchingViewFormat,
|
||||||
HwCapabilities.SupportsNonConstantTextureOffset,
|
HwCapabilities.SupportsNonConstantTextureOffset,
|
||||||
|
|
|
@ -32,6 +32,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
{
|
{
|
||||||
context.AppendLine("#extension GL_ARB_compute_shader : enable");
|
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)
|
if (context.Config.GpPassthrough)
|
||||||
{
|
{
|
||||||
|
@ -431,6 +442,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
|
|
||||||
string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType());
|
string imageTypeName = descriptor.Type.ToGlslImageType(descriptor.Format.GetComponentType());
|
||||||
|
|
||||||
|
if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
|
||||||
|
{
|
||||||
|
imageTypeName = "coherent " + imageTypeName;
|
||||||
|
}
|
||||||
|
|
||||||
string layout = descriptor.Format.ToGlslFormat();
|
string layout = descriptor.Format.ToGlslFormat();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(layout))
|
if (!string.IsNullOrEmpty(layout))
|
||||||
|
|
|
@ -117,7 +117,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||||
{
|
{
|
||||||
if (node is AstOperation operation)
|
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)
|
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.InstGenBallot;
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall;
|
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.InstGenHelper;
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
|
||||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
|
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
|
||||||
|
@ -144,6 +145,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
case Instruction.Call:
|
case Instruction.Call:
|
||||||
return Call(context, operation);
|
return Call(context, operation);
|
||||||
|
|
||||||
|
case Instruction.FSIBegin:
|
||||||
|
return FSIBegin(context);
|
||||||
|
|
||||||
|
case Instruction.FSIEnd:
|
||||||
|
return FSIEnd(context);
|
||||||
|
|
||||||
case Instruction.ImageLoad:
|
case Instruction.ImageLoad:
|
||||||
case Instruction.ImageStore:
|
case Instruction.ImageStore:
|
||||||
case Instruction.ImageAtomic:
|
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.EmitVertex, InstType.CallNullary, "EmitVertex");
|
||||||
Add(Instruction.EndPrimitive, InstType.CallNullary, "EndPrimitive");
|
Add(Instruction.EndPrimitive, InstType.CallNullary, "EndPrimitive");
|
||||||
Add(Instruction.ExponentB2, InstType.CallUnary, "exp2");
|
Add(Instruction.ExponentB2, InstType.CallUnary, "exp2");
|
||||||
|
Add(Instruction.FSIBegin, InstType.Special);
|
||||||
|
Add(Instruction.FSIEnd, InstType.Special);
|
||||||
Add(Instruction.FindFirstSetS32, InstType.CallUnary, "findMSB");
|
Add(Instruction.FindFirstSetS32, InstType.CallUnary, "findMSB");
|
||||||
Add(Instruction.FindFirstSetU32, InstType.CallUnary, "findMSB");
|
Add(Instruction.FindFirstSetU32, InstType.CallUnary, "findMSB");
|
||||||
Add(Instruction.Floor, InstType.CallUnary, "floor");
|
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
|
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>();
|
DecodedFunction EnqueueFunction(ulong address)
|
||||||
HashSet<ulong> funcVisited = new HashSet<ulong>();
|
|
||||||
|
|
||||||
void EnqueueFunction(ulong funcAddress)
|
|
||||||
{
|
{
|
||||||
if (funcVisited.Add(funcAddress))
|
if (!functionsVisited.TryGetValue(address, out DecodedFunction function))
|
||||||
{
|
{
|
||||||
funcQueue.Enqueue(funcAddress);
|
functionsVisited.Add(address, function = new DecodedFunction(address));
|
||||||
}
|
functionsQueue.Enqueue(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
funcQueue.Enqueue(0);
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
while (funcQueue.TryDequeue(out ulong funcAddress))
|
DecodedFunction mainFunction = EnqueueFunction(0);
|
||||||
|
|
||||||
|
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
||||||
{
|
{
|
||||||
List<Block> blocks = new List<Block>();
|
List<Block> blocks = new List<Block>();
|
||||||
Queue<Block> workQueue = new Queue<Block>();
|
Queue<Block> workQueue = new Queue<Block>();
|
||||||
|
@ -46,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetBlock(funcAddress);
|
GetBlock(currentFunction.Address);
|
||||||
|
|
||||||
bool hasNewTarget;
|
bool hasNewTarget;
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
if (lastOp.Name == InstName.Cal)
|
if (lastOp.Name == InstName.Cal)
|
||||||
{
|
{
|
||||||
EnqueueFunction(lastOp.GetAbsoluteAddress());
|
EnqueueFunction(lastOp.GetAbsoluteAddress()).AddCaller(currentFunction);
|
||||||
}
|
}
|
||||||
else if (lastOp.Name == InstName.Bra)
|
else if (lastOp.Name == InstName.Bra)
|
||||||
{
|
{
|
||||||
|
@ -157,10 +158,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
}
|
}
|
||||||
while (hasNewTarget);
|
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)
|
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,
|
Attr = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CacheOp
|
enum CacheOpLd
|
||||||
{
|
{
|
||||||
|
Ca = 0,
|
||||||
Cg = 1,
|
Cg = 1,
|
||||||
Ci = 2,
|
Ci = 2,
|
||||||
Cv = 3,
|
Cv = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CacheOpSt
|
||||||
|
{
|
||||||
|
Wb = 0,
|
||||||
|
Cg = 1,
|
||||||
|
Ci = 2,
|
||||||
|
Wt = 3,
|
||||||
|
}
|
||||||
|
|
||||||
enum LsSize
|
enum LsSize
|
||||||
{
|
{
|
||||||
U8 = 0,
|
U8 = 0,
|
||||||
|
@ -1163,19 +1172,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3);
|
public CctltOp CctltOp => (CctltOp)((_opcode >> 0) & 0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstContUnsup
|
struct InstCont
|
||||||
{
|
{
|
||||||
private ulong _opcode;
|
private ulong _opcode;
|
||||||
public InstContUnsup(ulong opcode) => _opcode = opcode;
|
public InstCont(ulong opcode) => _opcode = opcode;
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F);
|
public Ccc Ccc => (Ccc)((_opcode >> 0) & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstCsetUnsup
|
struct InstCset
|
||||||
{
|
{
|
||||||
private ulong _opcode;
|
private ulong _opcode;
|
||||||
public InstCsetUnsup(ulong opcode) => _opcode = opcode;
|
public InstCset(ulong opcode) => _opcode = opcode;
|
||||||
public int Dest => (int)((_opcode >> 0) & 0xFF);
|
public int Dest => (int)((_opcode >> 0) & 0xFF);
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
|
@ -3507,7 +3516,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public int SrcPred => (int)((_opcode >> 58) & 0x7);
|
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 LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
|
||||||
public bool E => (_opcode & 0x10000000000000) != 0;
|
public bool E => (_opcode & 0x10000000000000) != 0;
|
||||||
public int Imm32 => (int)(_opcode >> 20);
|
public int Imm32 => (int)(_opcode >> 20);
|
||||||
|
@ -3536,7 +3545,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public LsSize LsSize => (LsSize)((_opcode >> 48) & 0x7);
|
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 bool E => (_opcode & 0x200000000000) != 0;
|
||||||
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
@ -4502,7 +4511,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public int SrcPred => (int)((_opcode >> 58) & 0x7);
|
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 LsSize LsSize => (LsSize)((_opcode >> 53) & 0x7);
|
||||||
public bool E => (_opcode & 0x10000000000000) != 0;
|
public bool E => (_opcode & 0x10000000000000) != 0;
|
||||||
public int Imm32 => (int)(_opcode >> 20);
|
public int Imm32 => (int)(_opcode >> 20);
|
||||||
|
@ -4517,7 +4526,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7);
|
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 bool E => (_opcode & 0x200000000000) != 0;
|
||||||
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
@ -4531,7 +4540,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int Pred => (int)((_opcode >> 16) & 0x7);
|
public int Pred => (int)((_opcode >> 16) & 0x7);
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public LsSize2 LsSize => (LsSize2)((_opcode >> 48) & 0x7);
|
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);
|
public int Imm24 => (int)((_opcode >> 20) & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4662,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
||||||
public int DestPred2 => (int)((_opcode >> 30) & 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 bool Ba => (_opcode & 0x800000) != 0;
|
||||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||||
}
|
}
|
||||||
|
@ -4670,7 +4679,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
||||||
public int DestPred2 => (int)((_opcode >> 30) & 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 bool Ba => (_opcode & 0x800000) != 0;
|
||||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||||
}
|
}
|
||||||
|
@ -4687,7 +4696,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
||||||
public int DestPred2 => (int)((_opcode >> 30) & 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);
|
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4703,7 +4712,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
||||||
public int DestPred2 => (int)((_opcode >> 30) & 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);
|
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4750,7 +4759,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
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 bool Ba => (_opcode & 0x800000) != 0;
|
||||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||||
}
|
}
|
||||||
|
@ -4766,7 +4775,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
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 bool Ba => (_opcode & 0x800000) != 0;
|
||||||
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
public SuSize Size => (SuSize)((_opcode >> 20) & 0x7);
|
||||||
}
|
}
|
||||||
|
@ -4782,7 +4791,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public bool PredInv => (_opcode & 0x80000) != 0;
|
public bool PredInv => (_opcode & 0x80000) != 0;
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
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);
|
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4797,7 +4806,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
public Clamp Clamp => (Clamp)((_opcode >> 49) & 0x3);
|
||||||
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
public int TidB => (int)((_opcode >> 36) & 0x1FFF);
|
||||||
public SuDim Dim => (SuDim)((_opcode >> 33) & 0x7);
|
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);
|
public SuRgba Rgba => (SuRgba)((_opcode >> 20) & 0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,22 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
Rd2 = 1 << 1,
|
Rd2 = 1 << 1,
|
||||||
Ra = 1 << 2,
|
Ra = 1 << 2,
|
||||||
Rb = 1 << 3,
|
Rb = 1 << 3,
|
||||||
Ib = 1 << 4,
|
Rb2 = 1 << 4,
|
||||||
Rc = 1 << 5,
|
Ib = 1 << 5,
|
||||||
Pd = 1 << 6,
|
Rc = 1 << 6,
|
||||||
Pd2 = 1 << 7,
|
|
||||||
Pdn = 1 << 8,
|
Pd = 1 << 7,
|
||||||
Tex = 1 << 9,
|
LPd = 2 << 7,
|
||||||
TexB = 1 << 10,
|
SPd = 3 << 7,
|
||||||
Bra = 1 << 11,
|
TPd = 4 << 7,
|
||||||
NoPred = 1 << 12
|
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
|
#region Instructions
|
||||||
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
|
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
|
||||||
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, 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("11101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atom, InstEmit.Atom, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("111011101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomCas, InstEmit.AtomCas, 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("11101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Atoms, InstEmit.Atoms, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("111011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.AtomsCas, InstEmit.AtomsCas, 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("1111000010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.B2r, InstEmit.B2r, InstProps.Rd | InstProps.Ra | InstProps.VPd);
|
||||||
Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra);
|
Add("1111000010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bar, InstEmit.Bar, InstProps.Ra | InstProps.Ps);
|
||||||
Add("0101110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
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("0011100x00000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Bfe, InstEmit.BfeC, InstProps.Rd | InstProps.Ra);
|
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("1110101111110xx0000000000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt);
|
||||||
Add("1110101111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt, InstProps.Rc);
|
Add("1110101111101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cctlt, InstEmit.Cctlt, InstProps.Rc);
|
||||||
Add("111000110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cont, InstEmit.Cont);
|
Add("111000110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cont, InstEmit.Cont);
|
||||||
Add("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd);
|
Add("0101000010011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cset, InstEmit.Cset, InstProps.Rd | InstProps.Ps);
|
||||||
Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn);
|
Add("0101000010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Csetp, InstEmit.Csetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||||
Add("0101000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cs2r, InstEmit.Cs2r, InstProps.Rd);
|
Add("0101000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Cs2r, InstEmit.Cs2r, InstProps.Rd);
|
||||||
Add("0101110001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
Add("0101110001110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x01110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dadd, InstEmit.DaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
Add("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("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("010010110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("010100110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dfma, InstEmit.DfmaRc, 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("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);
|
Add("0011100x01010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("0100110001010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmnmx, InstEmit.DmnmxC, InstProps.Rd | InstProps.Ra);
|
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("0101110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x10000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
Add("0011100x10000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulC, InstProps.Rd | InstProps.Ra);
|
Add("0100110010000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dmul, InstEmit.DmulC, InstProps.Rd | InstProps.Ra);
|
||||||
Add("010110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
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);
|
Add("0011001x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("010010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dset, InstEmit.DsetC, InstProps.Rd | InstProps.Ra);
|
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);
|
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);
|
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);
|
Add("010010111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Dsetp, InstEmit.DsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||||
Add("111000110000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Exit, InstEmit.Exit, InstProps.Bra);
|
Add("111000110000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Exit, InstEmit.Exit, InstProps.Bra);
|
||||||
Add("0101110010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fR, InstProps.Rd | InstProps.Rb);
|
Add("0101110010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fR, InstProps.Rd | InstProps.Rb);
|
||||||
Add("0011100x10101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.F2f, InstEmit.F2fI, InstProps.Rd | InstProps.Ib);
|
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("0101110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloR, InstProps.Rd | InstProps.Rb);
|
||||||
Add("0011100x00110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloI, InstProps.Rd | InstProps.Ib);
|
Add("0011100x00110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloI, InstProps.Rd | InstProps.Ib);
|
||||||
Add("0100110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloC, InstProps.Rd);
|
Add("0100110000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Flo, InstEmit.FloC, InstProps.Rd);
|
||||||
Add("0101110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
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);
|
Add("0011100x01100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("0100110001100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmnmx, InstEmit.FmnmxC, InstProps.Rd | InstProps.Ra);
|
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("0101110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x01101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
Add("0011100x01101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulC, InstProps.Rd | InstProps.Ra);
|
Add("0100110001101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul, InstEmit.FmulC, InstProps.Rd | InstProps.Ra);
|
||||||
Add("00011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fmul32i, InstEmit.Fmul32i, 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("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);
|
Add("0011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("01001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fset, InstEmit.FsetC, InstProps.Rd | InstProps.Ra);
|
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);
|
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);
|
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);
|
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("0101000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Fswzadd, InstEmit.Fswzadd, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("111000101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getcrsptr, InstEmit.Getcrsptr, InstProps.Rd | InstProps.NoPred);
|
Add("111000101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getcrsptr, InstEmit.Getcrsptr, InstProps.Rd | InstProps.NoPred);
|
||||||
Add("111000101101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Getlmembase, InstEmit.Getlmembase, 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("0111100x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2I, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0111100x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2C, InstProps.Rd | InstProps.Ra);
|
Add("0111100x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul2, InstEmit.Hmul2C, InstProps.Rd | InstProps.Ra);
|
||||||
Add("0010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hmul232i, InstEmit.Hmul232i, 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("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);
|
Add("0111110x0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2I, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("0111110x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Hset2, InstEmit.Hset2C, InstProps.Rd | InstProps.Ra);
|
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);
|
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);
|
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);
|
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("0101110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fR, InstProps.Rd | InstProps.Rb);
|
||||||
Add("0011100x10111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fI, InstProps.Rd | InstProps.Ib);
|
Add("0011100x10111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fI, InstProps.Rd | InstProps.Ib);
|
||||||
Add("0100110010111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.I2f, InstEmit.I2fC, InstProps.Rd);
|
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("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("010010101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("010100101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imadsp, InstEmit.ImadspRc, 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("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);
|
Add("0011100x00100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("0100110000100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imnmx, InstEmit.ImnmxC, InstProps.Rd | InstProps.Ra);
|
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("0101110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x00111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
Add("0011100x00111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110000111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Imul, InstEmit.ImulC, InstProps.Rd | InstProps.Ra);
|
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("0011100x00011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddC, InstProps.Rd | InstProps.Ra);
|
Add("0100110000011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd, InstEmit.IscaddC, InstProps.Rd | InstProps.Ra);
|
||||||
Add("000101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iscadd32i, InstEmit.Iscadd32i, 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("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);
|
Add("0011011x0101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("010010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Iset, InstEmit.IsetC, InstProps.Rd | InstProps.Ra);
|
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);
|
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);
|
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);
|
Add("010010110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Isetp, InstEmit.IsetpC, InstProps.Ra | InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||||
Add("111000100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jcal, InstEmit.Jcal, InstProps.Bra);
|
Add("111000100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jcal, InstEmit.Jcal, InstProps.Bra);
|
||||||
Add("111000100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmp, InstEmit.Jmp, InstProps.Ra | InstProps.Bra);
|
Add("111000100001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmp, InstEmit.Jmp, InstProps.Ra | InstProps.Bra);
|
||||||
Add("111000100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Jmx, InstEmit.Jmx, 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("1110111011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldg, InstEmit.Ldg, InstProps.Rd | InstProps.Ra);
|
||||||
Add("1110111101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldl, InstEmit.Ldl, 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("1110111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lds, InstEmit.Lds, InstProps.Rd | InstProps.Ra);
|
||||||
Add("0101101111010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lea, InstEmit.LeaR, InstProps.Rd | InstProps.Ra | InstProps.Rb | 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.Pd);
|
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.Pd);
|
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.Pd);
|
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.Pd);
|
Add("000110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.LeaHi, InstEmit.LeaHiC, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.LPd);
|
||||||
Add("0101000011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lepc, InstEmit.Lepc);
|
Add("0101000011010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lepc, InstEmit.Lepc);
|
||||||
Add("111000110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Longjmp, InstEmit.Longjmp, InstProps.Bra);
|
Add("111000110001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Longjmp, InstEmit.Longjmp, InstProps.Bra);
|
||||||
Add("0101110001000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop, InstEmit.LopR, InstProps.Rd | InstProps.Ra | InstProps.Rb | 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.Pd);
|
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.Pd);
|
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.Pd);
|
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("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("0000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop3, InstEmit.Lop3C, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Lop32i, InstEmit.Lop32i, InstProps.Rd | InstProps.Ra);
|
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("111000101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pbk, InstEmit.Pbk, InstProps.NoPred);
|
||||||
Add("111000101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pcnt, InstEmit.Pcnt, InstProps.NoPred);
|
Add("111000101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pcnt, InstEmit.Pcnt, InstProps.NoPred);
|
||||||
Add("111000100011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pexit, InstEmit.Pexit);
|
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("111000101000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Plongjmp, InstEmit.Plongjmp, InstProps.Bra | InstProps.NoPred);
|
||||||
Add("0101110000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcR, InstProps.Rd | InstProps.Rb);
|
Add("0101110000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcR, InstProps.Rd | InstProps.Rb);
|
||||||
Add("0011100x00001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Popc, InstEmit.PopcI, InstProps.Rd | InstProps.Ib);
|
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("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("010010111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("010100111100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prmt, InstEmit.PrmtRc, 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("0101000010001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pset, InstEmit.Pset, InstProps.Rd | InstProps.Ps);
|
||||||
Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn);
|
Add("0101000010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Psetp, InstEmit.Psetp, InstProps.Pd | InstProps.Pdn | InstProps.Ps);
|
||||||
Add("1111000011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2b, InstEmit.R2b, InstProps.Rb);
|
Add("1111000011000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2b, InstEmit.R2b, InstProps.Rb);
|
||||||
Add("0101110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pR, InstProps.Ra | InstProps.Rb);
|
Add("0101110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pR, InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x11110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pI, InstProps.Ra | InstProps.Ib);
|
Add("0011100x11110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pI, InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pC, InstProps.Ra);
|
Add("0100110011110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.R2p, InstEmit.R2pC, InstProps.Ra);
|
||||||
Add("111000111000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ram, InstEmit.Ram, InstProps.NoPred);
|
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("111000110010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ret, InstEmit.Ret, InstProps.Bra);
|
||||||
Add("0101110010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroR, InstProps.Rd | InstProps.Rb);
|
Add("0101110010010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroR, InstProps.Rd | InstProps.Rb);
|
||||||
Add("0011100x10010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rro, InstEmit.RroI, InstProps.Rd | InstProps.Ib);
|
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("111000110110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Rtt, InstEmit.Rtt, InstProps.NoPred);
|
||||||
Add("1111000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.S2r, InstEmit.S2r, InstProps.Rd);
|
Add("1111000011001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.S2r, InstEmit.S2r, InstProps.Rd);
|
||||||
Add("111000110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sam, InstEmit.Sam, InstProps.NoPred);
|
Add("111000110111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sam, InstEmit.Sam, InstProps.NoPred);
|
||||||
Add("0101110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
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);
|
Add("0011100x10100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Ps);
|
||||||
Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra);
|
Add("0100110010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sel, InstEmit.SelC, InstProps.Rd | InstProps.Ra | InstProps.Ps);
|
||||||
Add("111000101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setcrsptr, InstEmit.Setcrsptr, InstProps.Ra | InstProps.NoPred);
|
Add("111000101110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setcrsptr, InstEmit.Setcrsptr, InstProps.Ra | InstProps.NoPred);
|
||||||
Add("111000101111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Setlmembase, InstEmit.Setlmembase, 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("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("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("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("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("0101110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlR, InstProps.Rd | InstProps.Ra | InstProps.Rb);
|
||||||
Add("0011100x01001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
Add("0011100x01001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlI, InstProps.Rd | InstProps.Ra | InstProps.Ib);
|
||||||
Add("0100110001001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Shl, InstEmit.ShlC, InstProps.Rd | InstProps.Ra);
|
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("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("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("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("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.Pd2);
|
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.Pd2 | InstProps.TexB);
|
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.Pd2 | InstProps.Tex);
|
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.Pd2 | InstProps.TexB);
|
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.Pd2 | InstProps.Tex);
|
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("111010110101xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SuredB, InstEmit.SuredB, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||||
Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra);
|
Add("1110101101011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sured, InstEmit.Sured, InstProps.Rd | InstProps.Ra);
|
||||||
Add("111010110011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.SustDB, InstEmit.SustDB, InstProps.Rd | InstProps.Ra | InstProps.Rc | InstProps.TexB);
|
Add("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("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("11101011001x1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sust, InstEmit.Sust, InstProps.Rd | InstProps.Ra | InstProps.Tex);
|
||||||
Add("1111000011111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Sync, InstEmit.Sync, InstProps.Bra);
|
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("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.Pd | InstProps.TexB);
|
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("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("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("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.Pd | InstProps.TexB);
|
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("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("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("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.Pd | InstProps.TexB);
|
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("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("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("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("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("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("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.Pd | InstProps.TexB);
|
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("1101111101001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Txq, InstEmit.Txq, InstProps.Rd | InstProps.Ra | InstProps.Tex);
|
||||||
Add("1101111101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxqB, InstEmit.TxqB, InstProps.Rd | InstProps.Ra | InstProps.TexB);
|
Add("1101111101010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.TxqB, InstEmit.TxqB, InstProps.Rd | InstProps.Ra | InstProps.TexB);
|
||||||
Add("01010100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vabsdiff, InstEmit.Vabsdiff, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
Add("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("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("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("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("0101000011100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Votevtg, InstEmit.Votevtg);
|
||||||
Add("0100000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vset, InstEmit.Vset, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
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("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("01010110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Vshr, InstEmit.Vshr, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
||||||
Add("0101101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
Add("0101101100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadR, InstProps.Rd | InstProps.Ra | InstProps.Rb | InstProps.Rc);
|
||||||
|
|
|
@ -61,6 +61,16 @@ namespace Ryujinx.Graphics.Shader
|
||||||
return 16;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QueryHostSupportsFragmentShaderInterlock()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QueryHostSupportsFragmentShaderOrderingIntel()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool QueryHostSupportsImageLoadFormatted()
|
bool QueryHostSupportsImageLoadFormatted()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -56,14 +56,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
public static void Cont(EmitterContext context)
|
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.");
|
context.Config.GpuAccessor.Log("Shader instruction ContUnsup is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Cset(EmitterContext context)
|
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.");
|
context.Config.GpuAccessor.Log("Shader instruction CsetUnsup is not implemented.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,24 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
{
|
{
|
||||||
InstCal op = context.GetOp<InstCal>();
|
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)
|
public static void Exit(EmitterContext context)
|
||||||
|
|
|
@ -109,28 +109,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
{
|
{
|
||||||
InstSuldDB op = context.GetOp<InstSuldDB>();
|
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)
|
public static void SuldD(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSuldD op = context.GetOp<InstSuldD>();
|
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)
|
public static void SuldB(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSuldB op = context.GetOp<InstSuldB>();
|
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)
|
public static void Suld(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSuld op = context.GetOp<InstSuld>();
|
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)
|
public static void SuredB(EmitterContext context)
|
||||||
|
@ -151,28 +151,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
{
|
{
|
||||||
InstSustDB op = context.GetOp<InstSustDB>();
|
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)
|
public static void SustD(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSustD op = context.GetOp<InstSustD>();
|
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)
|
public static void SustB(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSustB op = context.GetOp<InstSustB>();
|
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)
|
public static void Sust(EmitterContext context)
|
||||||
{
|
{
|
||||||
InstSust op = context.GetOp<InstSust>();
|
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(
|
private static void EmitSuatom(
|
||||||
|
@ -299,6 +299,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
private static void EmitSuld(
|
private static void EmitSuld(
|
||||||
EmitterContext context,
|
EmitterContext context,
|
||||||
|
CacheOpLd cacheOp,
|
||||||
SuDim dimensions,
|
SuDim dimensions,
|
||||||
SuSize size,
|
SuSize size,
|
||||||
int imm,
|
int imm,
|
||||||
|
@ -363,6 +364,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
|
|
||||||
|
if (cacheOp == CacheOpLd.Cg)
|
||||||
|
{
|
||||||
|
flags |= TextureFlags.Coherent;
|
||||||
|
}
|
||||||
|
|
||||||
if (useComponents)
|
if (useComponents)
|
||||||
{
|
{
|
||||||
for (int compMask = (int)componentMask, compIndex = 0; compMask != 0; compMask >>= 1, compIndex++)
|
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(
|
private static void EmitSust(
|
||||||
EmitterContext context,
|
EmitterContext context,
|
||||||
|
CacheOpSt cacheOp,
|
||||||
SuDim dimensions,
|
SuDim dimensions,
|
||||||
SuSize size,
|
SuSize size,
|
||||||
int imm,
|
int imm,
|
||||||
|
@ -654,6 +661,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
|
|
||||||
|
if (cacheOp == CacheOpSt.Cg)
|
||||||
|
{
|
||||||
|
flags |= TextureFlags.Coherent;
|
||||||
|
}
|
||||||
|
|
||||||
TextureOperation operation = context.CreateTextureOperation(
|
TextureOperation operation = context.CreateTextureOperation(
|
||||||
Instruction.ImageStore,
|
Instruction.ImageStore,
|
||||||
type,
|
type,
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
EmitVertex,
|
EmitVertex,
|
||||||
EndPrimitive,
|
EndPrimitive,
|
||||||
ExponentB2,
|
ExponentB2,
|
||||||
|
FSIBegin,
|
||||||
|
FSIEnd,
|
||||||
FindFirstSetS32,
|
FindFirstSetS32,
|
||||||
FindFirstSetU32,
|
FindFirstSetU32,
|
||||||
Floor,
|
Floor,
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
LodLevel = 1 << 5,
|
LodLevel = 1 << 5,
|
||||||
Offset = 1 << 6,
|
Offset = 1 << 6,
|
||||||
Offsets = 1 << 7,
|
Offsets = 1 << 7,
|
||||||
|
Coherent = 1 << 8,
|
||||||
|
|
||||||
AtomicMask = 15 << 16,
|
AtomicMask = 15 << 16,
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
|
OperandType.Argument => VariableType.S32,
|
||||||
OperandType.Attribute => VariableType.F32,
|
OperandType.Attribute => VariableType.F32,
|
||||||
OperandType.AttributePerPatch => VariableType.F32,
|
OperandType.AttributePerPatch => VariableType.F32,
|
||||||
OperandType.Constant => VariableType.S32,
|
OperandType.Constant => VariableType.S32,
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Shader
|
||||||
// Integer sampled textures must be noted for resolution scaling.
|
// Integer sampled textures must be noted for resolution scaling.
|
||||||
ResScaleUnsupported = 1 << 0,
|
ResScaleUnsupported = 1 << 0,
|
||||||
NeedsScaleValue = 1 << 1,
|
NeedsScaleValue = 1 << 1,
|
||||||
ImageStore = 1 << 2
|
ImageStore = 1 << 2,
|
||||||
|
ImageCoherent = 1 << 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
class EmitterContext
|
class EmitterContext
|
||||||
{
|
{
|
||||||
public Block CurrBlock { get; set; }
|
public DecodedProgram Program { get; }
|
||||||
public InstOp CurrOp { get; set; }
|
|
||||||
|
|
||||||
public ShaderConfig Config { get; }
|
public ShaderConfig Config { get; }
|
||||||
|
|
||||||
public bool IsNonMain { get; }
|
public bool IsNonMain { get; }
|
||||||
|
|
||||||
|
public Block CurrBlock { get; set; }
|
||||||
|
public InstOp CurrOp { get; set; }
|
||||||
|
|
||||||
public int OperationsCount => _operations.Count;
|
public int OperationsCount => _operations.Count;
|
||||||
|
|
||||||
private readonly IReadOnlyDictionary<ulong, int> _funcs;
|
|
||||||
private readonly List<Operation> _operations;
|
private readonly List<Operation> _operations;
|
||||||
private readonly Dictionary<ulong, Operand> _labels;
|
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;
|
Config = config;
|
||||||
IsNonMain = isNonMain;
|
IsNonMain = isNonMain;
|
||||||
_funcs = funcs;
|
|
||||||
_operations = new List<Operation>();
|
_operations = new List<Operation>();
|
||||||
_labels = new Dictionary<ulong, Operand>();
|
_labels = new Dictionary<ulong, Operand>();
|
||||||
}
|
}
|
||||||
|
@ -154,11 +154,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetFunctionId(ulong address)
|
|
||||||
{
|
|
||||||
return _funcs[address];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PrepareForReturn()
|
public void PrepareForReturn()
|
||||||
{
|
{
|
||||||
if (!IsNonMain && Config.Stage == ShaderStage.Fragment)
|
if (!IsNonMain && Config.Stage == ShaderStage.Fragment)
|
||||||
|
|
|
@ -361,6 +361,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return context.Add(Instruction.SwizzleAdd, Local(), a, b, Const(mask));
|
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)
|
public static Operand GroupMemoryBarrier(this EmitterContext context)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.GroupMemoryBarrier);
|
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 isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool accurateType = inst != Instruction.Lod;
|
bool accurateType = inst != Instruction.Lod;
|
||||||
|
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
||||||
|
|
||||||
if (isImage)
|
if (isImage)
|
||||||
{
|
{
|
||||||
SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false);
|
SetUsedTextureOrImage(_usedImages, cbufSlot, handle, type, format, true, isWrite, false, coherent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool intCoords = flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
|
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,
|
TextureFormat format,
|
||||||
bool intCoords,
|
bool intCoords,
|
||||||
bool write,
|
bool write,
|
||||||
bool accurateType)
|
bool accurateType,
|
||||||
|
bool coherent)
|
||||||
{
|
{
|
||||||
var dimensions = type.GetDimensions();
|
var dimensions = type.GetDimensions();
|
||||||
var isIndexed = type.HasFlag(SamplerType.Indexed);
|
var isIndexed = type.HasFlag(SamplerType.Indexed);
|
||||||
|
@ -361,6 +363,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
usageFlags |= TextureUsageFlags.ImageStore;
|
usageFlags |= TextureUsageFlags.ImageStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coherent)
|
||||||
|
{
|
||||||
|
usageFlags |= TextureUsageFlags.ImageCoherent;
|
||||||
|
}
|
||||||
|
|
||||||
int arraySize = isIndexed ? SamplerArraySize : 1;
|
int arraySize = isIndexed ? SamplerArraySize : 1;
|
||||||
|
|
||||||
for (int layer = 0; layer < arraySize; layer++)
|
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.StructuredIr;
|
||||||
using Ryujinx.Graphics.Shader.Translation.Optimizations;
|
using Ryujinx.Graphics.Shader.Translation.Optimizations;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
@ -33,9 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
counts ??= new TranslationCounts();
|
counts ??= new TranslationCounts();
|
||||||
|
|
||||||
Block[][] cfg = DecodeShader(address, gpuAccessor, options, counts, out ShaderConfig config);
|
return DecodeShader(address, gpuAccessor, options, counts);
|
||||||
|
|
||||||
return new TranslatorContext(address, cfg, config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
|
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
|
||||||
|
@ -112,35 +110,29 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Block[][] DecodeShader(
|
private static TranslatorContext DecodeShader(ulong address, IGpuAccessor gpuAccessor, TranslationOptions options, TranslationCounts counts)
|
||||||
ulong address,
|
|
||||||
IGpuAccessor gpuAccessor,
|
|
||||||
TranslationOptions options,
|
|
||||||
TranslationCounts counts,
|
|
||||||
out ShaderConfig config)
|
|
||||||
{
|
{
|
||||||
Block[][] cfg;
|
ShaderConfig config;
|
||||||
|
DecodedProgram program;
|
||||||
ulong maxEndAddress = 0;
|
ulong maxEndAddress = 0;
|
||||||
|
|
||||||
if ((options.Flags & TranslationFlags.Compute) != 0)
|
if ((options.Flags & TranslationFlags.Compute) != 0)
|
||||||
{
|
{
|
||||||
config = new ShaderConfig(gpuAccessor, options, counts);
|
config = new ShaderConfig(gpuAccessor, options, counts);
|
||||||
|
|
||||||
cfg = Decoder.Decode(config, address);
|
program = Decoder.Decode(config, address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
config = new ShaderConfig(new ShaderHeader(gpuAccessor, address), gpuAccessor, options, counts);
|
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)
|
if (maxEndAddress < block.EndAddress)
|
||||||
{
|
{
|
||||||
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));
|
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;
|
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);
|
EmitOutputsInitialization(context, config);
|
||||||
initializationOperations = context.OperationsCount;
|
initializationOperations = context.OperationsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int blkIndex = 0; blkIndex < cfg[funcIndex].Length; blkIndex++)
|
DecodedFunction function = program.GetFunctionById(index);
|
||||||
{
|
|
||||||
Block block = cfg[funcIndex][blkIndex];
|
|
||||||
|
|
||||||
|
foreach (Block block in function.Blocks)
|
||||||
|
{
|
||||||
context.CurrBlock = block;
|
context.CurrBlock = block;
|
||||||
|
|
||||||
context.MarkLabel(context.GetLabel(block.Address));
|
context.MarkLabel(context.GetLabel(block.Address));
|
||||||
|
@ -201,10 +193,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
EmitOps(context, block);
|
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)
|
private static void EmitOutputsInitialization(EmitterContext context, ShaderConfig config)
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
public class TranslatorContext
|
public class TranslatorContext
|
||||||
{
|
{
|
||||||
private readonly Block[][] _cfg;
|
private readonly DecodedProgram _program;
|
||||||
private ShaderConfig _config;
|
private ShaderConfig _config;
|
||||||
|
|
||||||
public ulong Address { get; }
|
public ulong Address { get; }
|
||||||
|
@ -23,11 +23,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
|
|
||||||
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
|
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
|
||||||
|
|
||||||
internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
|
internal TranslatorContext(ulong address, DecodedProgram program, ShaderConfig config)
|
||||||
{
|
{
|
||||||
Address = address;
|
Address = address;
|
||||||
|
_program = program;
|
||||||
_config = config;
|
_config = config;
|
||||||
_cfg = cfg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsUserAttribute(Operand operand)
|
private static bool IsUserAttribute(Operand operand)
|
||||||
|
@ -141,13 +141,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
nextStage._config.UsedInputAttributesPerPatch);
|
nextStage._config.UsedInputAttributesPerPatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionCode[] code = EmitShader(_cfg, _config, initializeOutputs: other == null, out _);
|
FunctionCode[] code = EmitShader(_program, _config, initializeOutputs: other == null, out _);
|
||||||
|
|
||||||
if (other != null)
|
if (other != null)
|
||||||
{
|
{
|
||||||
other._config.MergeOutputUserAttributes(_config.UsedOutputAttributes, 0);
|
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);
|
code = Combine(otherCode, code, aStart);
|
||||||
|
|
||||||
|
|
Reference in a new issue