/ src / Ryujinx.Graphics.Shader / Instructions / InstEmitBitfield.cs
InstEmitBitfield.cs
  1  using Ryujinx.Graphics.Shader.Decoders;
  2  using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3  using Ryujinx.Graphics.Shader.Translation;
  4  
  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          public static void BfeR(EmitterContext context)
 13          {
 14              InstBfeR op = context.GetOp<InstBfeR>();
 15  
 16              var srcA = GetSrcReg(context, op.SrcA);
 17              var srcB = GetSrcReg(context, op.SrcB);
 18  
 19              EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed);
 20          }
 21  
 22          public static void BfeI(EmitterContext context)
 23          {
 24              InstBfeI op = context.GetOp<InstBfeI>();
 25  
 26              var srcA = GetSrcReg(context, op.SrcA);
 27              var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20));
 28  
 29              EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed);
 30          }
 31  
 32          public static void BfeC(EmitterContext context)
 33          {
 34              InstBfeC op = context.GetOp<InstBfeC>();
 35  
 36              var srcA = GetSrcReg(context, op.SrcA);
 37              var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
 38  
 39              EmitBfe(context, srcA, srcB, op.Dest, op.Brev, op.Signed);
 40          }
 41  
 42          public static void BfiR(EmitterContext context)
 43          {
 44              InstBfiR op = context.GetOp<InstBfiR>();
 45  
 46              var srcA = GetSrcReg(context, op.SrcA);
 47              var srcB = GetSrcReg(context, op.SrcB);
 48              var srcC = GetSrcReg(context, op.SrcC);
 49  
 50              EmitBfi(context, srcA, srcB, srcC, op.Dest);
 51          }
 52  
 53          public static void BfiI(EmitterContext context)
 54          {
 55              InstBfiI op = context.GetOp<InstBfiI>();
 56  
 57              var srcA = GetSrcReg(context, op.SrcA);
 58              var srcB = GetSrcImm(context, Imm20ToSInt(op.Imm20));
 59              var srcC = GetSrcReg(context, op.SrcC);
 60  
 61              EmitBfi(context, srcA, srcB, srcC, op.Dest);
 62          }
 63  
 64          public static void BfiC(EmitterContext context)
 65          {
 66              InstBfiC op = context.GetOp<InstBfiC>();
 67  
 68              var srcA = GetSrcReg(context, op.SrcA);
 69              var srcB = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
 70              var srcC = GetSrcReg(context, op.SrcC);
 71  
 72              EmitBfi(context, srcA, srcB, srcC, op.Dest);
 73          }
 74  
 75          public static void BfiRc(EmitterContext context)
 76          {
 77              InstBfiRc op = context.GetOp<InstBfiRc>();
 78  
 79              var srcA = GetSrcReg(context, op.SrcA);
 80              var srcB = GetSrcReg(context, op.SrcC);
 81              var srcC = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset);
 82  
 83              EmitBfi(context, srcA, srcB, srcC, op.Dest);
 84          }
 85  
 86          public static void FloR(EmitterContext context)
 87          {
 88              InstFloR op = context.GetOp<InstFloR>();
 89  
 90              EmitFlo(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB, op.Sh, op.Signed);
 91          }
 92  
 93          public static void FloI(EmitterContext context)
 94          {
 95              InstFloI op = context.GetOp<InstFloI>();
 96  
 97              EmitFlo(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB, op.Sh, op.Signed);
 98          }
 99  
100          public static void FloC(EmitterContext context)
101          {
102              InstFloC op = context.GetOp<InstFloC>();
103  
104              EmitFlo(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB, op.Sh, op.Signed);
105          }
106  
107          public static void PopcR(EmitterContext context)
108          {
109              InstPopcR op = context.GetOp<InstPopcR>();
110  
111              EmitPopc(context, GetSrcReg(context, op.SrcB), op.Dest, op.NegB);
112          }
113  
114          public static void PopcI(EmitterContext context)
115          {
116              InstPopcI op = context.GetOp<InstPopcI>();
117  
118              EmitPopc(context, GetSrcImm(context, Imm20ToSInt(op.Imm20)), op.Dest, op.NegB);
119          }
120  
121          public static void PopcC(EmitterContext context)
122          {
123              InstPopcC op = context.GetOp<InstPopcC>();
124  
125              EmitPopc(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.NegB);
126          }
127  
128          private static void EmitBfe(
129              EmitterContext context,
130              Operand srcA,
131              Operand srcB,
132              int rd,
133              bool bitReverse,
134              bool isSigned)
135          {
136              if (bitReverse)
137              {
138                  srcA = context.BitfieldReverse(srcA);
139              }
140  
141              Operand position = context.BitwiseAnd(srcB, Const(0xff));
142  
143              Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8));
144  
145              Operand res = isSigned
146                  ? context.BitfieldExtractS32(srcA, position, size)
147                  : context.BitfieldExtractU32(srcA, position, size);
148  
149              context.Copy(GetDest(rd), res);
150  
151              // TODO: CC, X, corner cases.
152          }
153  
154          private static void EmitBfi(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int rd)
155          {
156              Operand position = context.BitwiseAnd(srcB, Const(0xff));
157  
158              Operand size = context.BitfieldExtractU32(srcB, Const(8), Const(8));
159  
160              Operand res = context.BitfieldInsert(srcC, srcA, position, size);
161  
162              context.Copy(GetDest(rd), res);
163          }
164  
165          private static void EmitFlo(EmitterContext context, Operand src, int rd, bool invert, bool sh, bool isSigned)
166          {
167              Operand srcB = context.BitwiseNot(src, invert);
168  
169              Operand res;
170  
171              if (sh)
172              {
173                  res = context.FindLSB(context.BitfieldReverse(srcB));
174              }
175              else
176              {
177                  res = isSigned
178                      ? context.FindMSBS32(srcB)
179                      : context.FindMSBU32(srcB);
180              }
181  
182              context.Copy(GetDest(rd), res);
183          }
184  
185          private static void EmitPopc(EmitterContext context, Operand src, int rd, bool invert)
186          {
187              Operand srcB = context.BitwiseNot(src, invert);
188  
189              Operand res = context.BitCount(srcB);
190  
191              context.Copy(GetDest(rd), res);
192          }
193      }
194  }