/ src / Ryujinx.Graphics.Shader / Instructions / InstEmitIntegerLogical.cs
InstEmitIntegerLogical.cs
  1  using Ryujinx.Graphics.Shader.Decoders;
  2  using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3  using Ryujinx.Graphics.Shader.Translation;
  4  using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
  5  using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
  6  using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  7  
  8  namespace Ryujinx.Graphics.Shader.Instructions
  9  {
 10      static partial class InstEmit
 11      {
 12          private const int PT = RegisterConsts.PredicateTrueIndex;
 13  
 14          public static void LopR(EmitterContext context)
 15          {
 16              InstLopR op = context.GetOp<InstLopR>();
 17  
 18              var srcA = GetSrcReg(context, op.SrcA);
 19              var srcB = GetSrcReg(context, op.SrcB);
 20  
 21              EmitLop(context, op.Lop, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC);
 22          }
 23  
 24          public static void LopI(EmitterContext context)
 25          {
 26              InstLopI op = context.GetOp<InstLopI>();
 27  
 28              var srcA = GetSrcReg(context, op.SrcA);
 29              var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20));
 30  
 31              EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC);
 32          }
 33  
 34          public static void LopC(EmitterContext context)
 35          {
 36              InstLopC op = context.GetOp<InstLopC>();
 37  
 38              var srcA = GetSrcReg(context, op.SrcA);
 39              var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
 40  
 41              EmitLop(context, op.LogicOp, op.PredicateOp, srcA, srcB, op.Dest, op.DestPred, op.NegA, op.NegB, op.X, op.WriteCC);
 42          }
 43  
 44          public static void Lop32i(EmitterContext context)
 45          {
 46              InstLop32i op = context.GetOp<InstLop32i>();
 47  
 48              var srcA = GetSrcReg(context, op.SrcA);
 49              var srcB = GetSrcImm(context, op.Imm32);
 50  
 51              EmitLop(context, op.LogicOp, PredicateOp.F, srcA, srcB, op.Dest, PT, op.NegA, op.NegB, op.X, op.WriteCC);
 52          }
 53  
 54          public static void Lop3R(EmitterContext context)
 55          {
 56              InstLop3R op = context.GetOp<InstLop3R>();
 57  
 58              var srcA = GetSrcReg(context, op.SrcA);
 59              var srcB = GetSrcReg(context, op.SrcB);
 60              var srcC = GetSrcReg(context, op.SrcC);
 61  
 62              EmitLop3(context, op.Imm, op.PredicateOp, srcA, srcB, srcC, op.Dest, op.DestPred, op.X, op.WriteCC);
 63          }
 64  
 65          public static void Lop3I(EmitterContext context)
 66          {
 67              InstLop3I op = context.GetOp<InstLop3I>();
 68  
 69              var srcA = GetSrcReg(context, op.SrcA);
 70              var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20));
 71              var srcC = GetSrcReg(context, op.SrcC);
 72  
 73              EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC);
 74          }
 75  
 76          public static void Lop3C(EmitterContext context)
 77          {
 78              InstLop3C op = context.GetOp<InstLop3C>();
 79  
 80              var srcA = GetSrcReg(context, op.SrcA);
 81              var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
 82              var srcC = GetSrcReg(context, op.SrcC);
 83  
 84              EmitLop3(context, op.Imm, PredicateOp.F, srcA, srcB, srcC, op.Dest, PT, false, op.WriteCC);
 85          }
 86  
 87          private static void EmitLop(
 88              EmitterContext context,
 89              LogicOp logicOp,
 90              PredicateOp predOp,
 91              Operand srcA,
 92              Operand srcB,
 93              int rd,
 94              int destPred,
 95              bool invertA,
 96              bool invertB,
 97              bool extended,
 98              bool writeCC)
 99          {
100              srcA = context.BitwiseNot(srcA, invertA);
101              srcB = context.BitwiseNot(srcB, invertB);
102  
103              Operand res = logicOp switch
104              {
105                  LogicOp.And => context.BitwiseAnd(srcA, srcB),
106                  LogicOp.Or => context.BitwiseOr(srcA, srcB),
107                  LogicOp.Xor => context.BitwiseExclusiveOr(srcA, srcB),
108                  _ => srcB,
109              };
110  
111              EmitLopPredWrite(context, res, predOp, destPred);
112  
113              context.Copy(GetDest(rd), res);
114  
115              SetZnFlags(context, res, writeCC, extended);
116          }
117  
118          private static void EmitLop3(
119              EmitterContext context,
120              int truthTable,
121              PredicateOp predOp,
122              Operand srcA,
123              Operand srcB,
124              Operand srcC,
125              int rd,
126              int destPred,
127              bool extended,
128              bool writeCC)
129          {
130              Operand res = Lop3Expression.GetFromTruthTable(context, srcA, srcB, srcC, truthTable);
131  
132              EmitLopPredWrite(context, res, predOp, destPred);
133  
134              context.Copy(GetDest(rd), res);
135  
136              SetZnFlags(context, res, writeCC, extended);
137          }
138  
139          private static void EmitLopPredWrite(EmitterContext context, Operand result, PredicateOp predOp, int pred)
140          {
141              if (pred != RegisterConsts.PredicateTrueIndex)
142              {
143                  Operand pRes;
144  
145                  if (predOp == PredicateOp.F)
146                  {
147                      pRes = Const(IrConsts.False);
148                  }
149                  else if (predOp == PredicateOp.T)
150                  {
151                      pRes = Const(IrConsts.True);
152                  }
153                  else if (predOp == PredicateOp.Z)
154                  {
155                      pRes = context.ICompareEqual(result, Const(0));
156                  }
157                  else /* if (predOp == Pop.Nz) */
158                  {
159                      pRes = context.ICompareNotEqual(result, Const(0));
160                  }
161  
162                  context.Copy(Register(pred, RegisterType.Predicate), pRes);
163              }
164          }
165      }
166  }