forked from Mirror/Ryujinx
Avoid gpr overwritting on Ld_C instruction (#371)
* Avoid gpr overwritting on LD_C instruction * Address feedback * Ignore invalid registers
This commit is contained in:
parent
afdeee2b86
commit
afc44850be
3 changed files with 22 additions and 10 deletions
|
@ -35,13 +35,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
(int)(OpCode >> 20) & 0x3fff);
|
(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)
|
public static ShaderIrOperGpr GetOperGpr8(long OpCode)
|
||||||
{
|
{
|
||||||
return new ShaderIrOperGpr((int)(OpCode >> 8) & 0xff);
|
return new ShaderIrOperGpr((int)(OpCode >> 8) & 0xff);
|
||||||
|
|
|
@ -52,23 +52,35 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
public static void Ld_C(ShaderIrBlock Block, long OpCode)
|
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)
|
if (Type > 5)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderIrOperGpr Temp = ShaderIrOperGpr.MakeTemporary();
|
||||||
|
|
||||||
|
Block.AddNode(new ShaderIrAsg(Temp, GetOperGpr8(OpCode)));
|
||||||
|
|
||||||
int Count = Type == 5 ? 2 : 1;
|
int Count = Type == 5 ? 2 : 1;
|
||||||
|
|
||||||
for (int Index = 0; Index < Count; Index++)
|
for (int Index = 0; Index < Count; Index++)
|
||||||
{
|
{
|
||||||
ShaderIrOperCbuf OperA = GetOperCbuf36(OpCode);
|
ShaderIrOperCbuf OperA = new ShaderIrOperCbuf(CbufIndex, CbufPos, Temp);
|
||||||
ShaderIrOperGpr OperD = GetOperGpr0 (OpCode);
|
|
||||||
|
ShaderIrOperGpr OperD = GetOperGpr0(OpCode);
|
||||||
|
|
||||||
OperA.Pos += Index;
|
OperA.Pos += Index;
|
||||||
OperD.Index += Index;
|
OperD.Index += Index;
|
||||||
|
|
||||||
|
if (!OperD.IsValidRegister)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ShaderIrNode Node = OperA;
|
ShaderIrNode Node = OperA;
|
||||||
|
|
||||||
if (Type < 4)
|
if (Type < 4)
|
||||||
|
|
|
@ -6,11 +6,18 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
public bool IsConst => Index == ZRIndex;
|
public bool IsConst => Index == ZRIndex;
|
||||||
|
|
||||||
|
public bool IsValidRegister => (Index <= ZRIndex);
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
public ShaderIrOperGpr(int Index)
|
public ShaderIrOperGpr(int Index)
|
||||||
{
|
{
|
||||||
this.Index = Index;
|
this.Index = Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ShaderIrOperGpr MakeTemporary(int Index = 0)
|
||||||
|
{
|
||||||
|
return new ShaderIrOperGpr(0x100 + Index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue