From 6edc9298944d16c29e7423da5b1f3ce3e1025ac7 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 23 Mar 2020 13:32:30 -0300 Subject: [PATCH] Implement ICMP shader instruction (#1010) --- .../Decoders/OpCodeTable.cs | 4 ++ .../Instructions/InstEmitAlu.cs | 42 ++++++++++++------- .../Instructions/InstEmitMove.cs | 2 - 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs index 72f66f4a..3878dd87 100644 --- a/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs +++ b/Ryujinx.Graphics.Shader/Decoders/OpCodeTable.cs @@ -120,6 +120,10 @@ namespace Ryujinx.Graphics.Shader.Decoders Set("010011001100xx", InstEmit.Iadd3, typeof(OpCodeAluCbuf)); Set("0011100x1100xx", InstEmit.Iadd3, typeof(OpCodeAluImm)); Set("010111001100xx", InstEmit.Iadd3, typeof(OpCodeAluReg)); + Set("010010110100xx", InstEmit.Icmp, typeof(OpCodeAluCbuf)); + Set("0011011x0100xx", InstEmit.Icmp, typeof(OpCodeAluImm)); + Set("010110110100xx", InstEmit.Icmp, typeof(OpCodeAluReg)); + Set("010100110100xx", InstEmit.Icmp, typeof(OpCodeAluRegCbuf)); Set("010010100xxxxx", InstEmit.Imad, typeof(OpCodeAluCbuf)); Set("0011010x0xxxxx", InstEmit.Imad, typeof(OpCodeAluImm)); Set("010110100xxxxx", InstEmit.Imad, typeof(OpCodeAluReg)); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs index 92354cec..5a919c77 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs @@ -200,10 +200,27 @@ namespace Ryujinx.Graphics.Shader.Instructions // TODO: CC, X, corner cases } + public static void Icmp(EmitterContext context) + { + OpCode op = context.CurrOp; + + bool isSigned = op.RawOpCode.Extract(48); + + IntegerCondition cmpOp = (IntegerCondition)op.RawOpCode.Extract(49, 3); + + Operand srcA = GetSrcA(context); + Operand srcB = GetSrcB(context); + Operand srcC = GetSrcC(context); + + Operand cmpRes = GetIntComparison(context, cmpOp, srcC, Const(0), isSigned); + + Operand res = context.ConditionalSelect(cmpRes, srcA, srcB); + + context.Copy(GetDest(context), res); + } + public static void Imad(EmitterContext context) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - bool signedA = context.CurrOp.RawOpCode.Extract(48); bool signedB = context.CurrOp.RawOpCode.Extract(53); bool high = context.CurrOp.RawOpCode.Extract(54); @@ -731,19 +748,16 @@ namespace Ryujinx.Graphics.Shader.Instructions } else { - Instruction inst; - - switch (cond) + var inst = cond switch { - case IntegerCondition.Less: inst = Instruction.CompareLessU32; break; - case IntegerCondition.Equal: inst = Instruction.CompareEqual; break; - case IntegerCondition.LessOrEqual: inst = Instruction.CompareLessOrEqualU32; break; - case IntegerCondition.Greater: inst = Instruction.CompareGreaterU32; break; - case IntegerCondition.NotEqual: inst = Instruction.CompareNotEqual; break; - case IntegerCondition.GreaterOrEqual: inst = Instruction.CompareGreaterOrEqualU32; break; - - default: throw new InvalidOperationException($"Unexpected condition \"{cond}\"."); - } + IntegerCondition.Less => Instruction.CompareLessU32, + IntegerCondition.Equal => Instruction.CompareEqual, + IntegerCondition.LessOrEqual => Instruction.CompareLessOrEqualU32, + IntegerCondition.Greater => Instruction.CompareGreaterU32, + IntegerCondition.NotEqual => Instruction.CompareNotEqual, + IntegerCondition.GreaterOrEqual => Instruction.CompareGreaterOrEqualU32, + _ => throw new InvalidOperationException($"Unexpected condition \"{cond}\".") + }; if (isSigned) { diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index ffc4c430..efc80b0c 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -97,8 +97,6 @@ namespace Ryujinx.Graphics.Shader.Instructions public static void Sel(EmitterContext context) { - OpCodeAlu op = (OpCodeAlu)context.CurrOp; - Operand pred = GetPredicate39(context); Operand srcA = GetSrcA(context);