From afc44850be37f57d96e981925229964771a3e9e0 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Mon, 20 Aug 2018 23:31:10 -0300 Subject: [PATCH] Avoid gpr overwritting on Ld_C instruction (#371) * Avoid gpr overwritting on LD_C instruction * Address feedback * Ignore invalid registers --- .../Gal/Shader/ShaderDecodeHelper.cs | 7 ------- Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs | 18 +++++++++++++++--- Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs | 7 +++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs index 7d7b2f6c6..2093f0706 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs @@ -35,13 +35,6 @@ namespace Ryujinx.Graphics.Gal.Shader (int)(OpCode >> 20) & 0x3fff); } - public static ShaderIrOperCbuf GetOperCbuf36(long OpCode) - { - return new ShaderIrOperCbuf( - (int)(OpCode >> 36) & 0x1f, - (int)(OpCode >> 22) & 0x3fff, GetOperGpr8(OpCode)); - } - public static ShaderIrOperGpr GetOperGpr8(long OpCode) { return new ShaderIrOperGpr((int)(OpCode >> 8) & 0xff); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs index e794e1f87..a183b0c69 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs @@ -52,23 +52,35 @@ namespace Ryujinx.Graphics.Gal.Shader public static void Ld_C(ShaderIrBlock Block, long OpCode) { - int Type = (int)(OpCode >> 48) & 7; + int CbufPos = (int)(OpCode >> 22) & 0x3fff; + int CbufIndex = (int)(OpCode >> 36) & 0x1f; + int Type = (int)(OpCode >> 48) & 7; if (Type > 5) { throw new InvalidOperationException(); } + ShaderIrOperGpr Temp = ShaderIrOperGpr.MakeTemporary(); + + Block.AddNode(new ShaderIrAsg(Temp, GetOperGpr8(OpCode))); + int Count = Type == 5 ? 2 : 1; for (int Index = 0; Index < Count; Index++) { - ShaderIrOperCbuf OperA = GetOperCbuf36(OpCode); - ShaderIrOperGpr OperD = GetOperGpr0 (OpCode); + ShaderIrOperCbuf OperA = new ShaderIrOperCbuf(CbufIndex, CbufPos, Temp); + + ShaderIrOperGpr OperD = GetOperGpr0(OpCode); OperA.Pos += Index; OperD.Index += Index; + if (!OperD.IsValidRegister) + { + break; + } + ShaderIrNode Node = OperA; if (Type < 4) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs index 5c69d6a67..9dd196e69 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs @@ -6,11 +6,18 @@ namespace Ryujinx.Graphics.Gal.Shader public bool IsConst => Index == ZRIndex; + public bool IsValidRegister => (Index <= ZRIndex); + public int Index { get; set; } public ShaderIrOperGpr(int Index) { this.Index = Index; } + + public static ShaderIrOperGpr MakeTemporary(int Index = 0) + { + return new ShaderIrOperGpr(0x100 + Index); + } } } \ No newline at end of file