Add IADDI32, IADD and SEL shader instructions

This commit is contained in:
ReinUsesLisp 2018-07-04 22:17:51 -03:00
parent 514218ab98
commit 5eed749649
3 changed files with 98 additions and 0 deletions

View file

@ -144,6 +144,35 @@ namespace Ryujinx.Graphics.Gal.Shader
EmitFsetp(Block, OpCode, ShaderOper.RR);
}
public static void Iadd_I32_1c0(ShaderIrBlock Block, long OpCode)
{
ShaderIrNode OperA = GetOperGpr0 (OpCode);
ShaderIrNode OperB = GetOperImm32_20(OpCode);
bool NegA = ((OpCode >> 56) & 1) != 0;
OperA = GetAluIneg(OperA, NegA);
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Add, OperA, OperB);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
public static void Iadd_C(ShaderIrBlock Block, long OpCode)
{
EmitIadd(Block, OpCode, ShaderOper.CR);
}
public static void Iadd_I(ShaderIrBlock Block, long OpCode)
{
EmitIadd(Block, OpCode, ShaderOper.Imm);
}
public static void Iadd_R(ShaderIrBlock Block, long OpCode)
{
EmitIadd(Block, OpCode, ShaderOper.RR);
}
public static void Imnmx_C(ShaderIrBlock Block, long OpCode)
{
EmitImnmx(Block, OpCode, ShaderOper.CR);
@ -533,6 +562,31 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
private static void EmitIadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
ShaderIrNode OperA = GetOperGpr8(OpCode);
ShaderIrNode OperB;
switch (Oper)
{
case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper));
}
bool NegA = ((OpCode >> 49) & 1) != 0;
bool NegB = ((OpCode >> 48) & 1) != 0;
OperA = GetAluIneg(OperA, NegA);
OperB = GetAluIneg(OperB, NegB);
ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Add, OperA, OperB);
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
}
private static void EmitIscadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegB = ((OpCode >> 48) & 1) != 0;

View file

@ -113,6 +113,21 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Gpr), OpCode));
}
public static void Sel_C(ShaderIrBlock Block, long OpCode)
{
EmitSel(Block, OpCode, ShaderOper.CR);
}
public static void Sel_I(ShaderIrBlock Block, long OpCode)
{
EmitSel(Block, OpCode, ShaderOper.Imm);
}
public static void Sel_R(ShaderIrBlock Block, long OpCode)
{
EmitSel(Block, OpCode, ShaderOper.RR);
}
private static void EmitF2f(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
bool NegA = ((OpCode >> 45) & 1) != 0;
@ -340,6 +355,28 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode));
}
private static void EmitSel(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
{
ShaderIrOperGpr Dst = GetOperGpr0 (OpCode);
ShaderIrNode Pred = GetOperPred39N(OpCode);
ShaderIrNode ResultA = GetOperGpr8(OpCode);
ShaderIrNode ResultB;
switch (Oper)
{
case ShaderOper.CR: ResultB = GetOperCbuf34 (OpCode); break;
case ShaderOper.Imm: ResultB = GetOperImm19_20(OpCode); break;
case ShaderOper.RR: ResultB = GetOperGpr20 (OpCode); break;
default: throw new ArgumentException(nameof(Oper));
}
Block.AddNode(GetPredNode(new ShaderIrCond(Pred, new ShaderIrAsg(Dst, ResultA), false), OpCode));
Block.AddNode(GetPredNode(new ShaderIrCond(Pred, new ShaderIrAsg(Dst, ResultB), true), OpCode));
}
private static IntType GetIntType(long OpCode)
{
bool Signed = ((OpCode >> 13) & 1) != 0;

View file

@ -64,6 +64,10 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("0100110011100x", ShaderDecode.I2i_C);
Set("0011100x11100x", ShaderDecode.I2i_I);
Set("0101110011100x", ShaderDecode.I2i_R);
Set("0001110xxxxxxx", ShaderDecode.Iadd_I32_1c0);
Set("0100110000010x", ShaderDecode.Iadd_C);
Set("0011100000010x", ShaderDecode.Iadd_I);
Set("0101110000010x", ShaderDecode.Iadd_R);
Set("0100110000100x", ShaderDecode.Imnmx_C);
Set("0011100x00100x", ShaderDecode.Imnmx_I);
Set("0101110000100x", ShaderDecode.Imnmx_R);
@ -87,6 +91,9 @@ namespace Ryujinx.Graphics.Gal.Shader
Set("0100110010010x", ShaderDecode.Rro_C);
Set("0011100x10010x", ShaderDecode.Rro_I);
Set("0101110010010x", ShaderDecode.Rro_R);
Set("0100110010100x", ShaderDecode.Sel_C);
Set("0011100010100x", ShaderDecode.Sel_I);
Set("0101110010100x", ShaderDecode.Sel_R);
Set("0100110001001x", ShaderDecode.Shl_C);
Set("0011100x01001x", ShaderDecode.Shl_I);
Set("0101110001001x", ShaderDecode.Shl_R);