/ src / Ryujinx.Graphics.Shader / Instructions / InstEmitMultifunction.cs
InstEmitMultifunction.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  
 7  namespace Ryujinx.Graphics.Shader.Instructions
 8  {
 9      static partial class InstEmit
10      {
11          public static void RroR(EmitterContext context)
12          {
13              InstRroR op = context.GetOp<InstRroR>();
14  
15              EmitRro(context, GetSrcReg(context, op.SrcB), op.Dest, op.AbsB, op.NegB);
16          }
17  
18          public static void RroI(EmitterContext context)
19          {
20              InstRroI op = context.GetOp<InstRroI>();
21  
22              EmitRro(context, GetSrcImm(context, Imm20ToFloat(op.Imm20)), op.Dest, op.AbsB, op.NegB);
23          }
24  
25          public static void RroC(EmitterContext context)
26          {
27              InstRroC op = context.GetOp<InstRroC>();
28  
29              EmitRro(context, GetSrcCbuf(context, op.CbufSlot, op.CbufOffset), op.Dest, op.AbsB, op.NegB);
30          }
31  
32          public static void Mufu(EmitterContext context)
33          {
34              InstMufu op = context.GetOp<InstMufu>();
35  
36              Operand res = context.FPAbsNeg(GetSrcReg(context, op.SrcA), op.AbsA, op.NegA);
37  
38              switch (op.MufuOp)
39              {
40                  case MufuOp.Cos:
41                      res = context.FPCosine(res);
42                      break;
43  
44                  case MufuOp.Sin:
45                      res = context.FPSine(res);
46                      break;
47  
48                  case MufuOp.Ex2:
49                      res = context.FPExponentB2(res);
50                      break;
51  
52                  case MufuOp.Lg2:
53                      res = context.FPLogarithmB2(res);
54                      break;
55  
56                  case MufuOp.Rcp:
57                      res = context.FPReciprocal(res);
58                      break;
59  
60                  case MufuOp.Rsq:
61                      res = context.FPReciprocalSquareRoot(res);
62                      break;
63  
64                  case MufuOp.Rcp64h:
65                      res = context.PackDouble2x32(OperandHelper.Const(0), res);
66                      res = context.UnpackDouble2x32High(context.FPReciprocal(res, Instruction.FP64));
67                      break;
68  
69                  case MufuOp.Rsq64h:
70                      res = context.PackDouble2x32(OperandHelper.Const(0), res);
71                      res = context.UnpackDouble2x32High(context.FPReciprocalSquareRoot(res, Instruction.FP64));
72                      break;
73  
74                  case MufuOp.Sqrt:
75                      res = context.FPSquareRoot(res);
76                      break;
77  
78                  default:
79                      context.TranslatorContext.GpuAccessor.Log($"Invalid MUFU operation \"{op.MufuOp}\".");
80                      break;
81              }
82  
83              context.Copy(GetDest(op.Dest), context.FPSaturate(res, op.Sat));
84          }
85  
86          private static void EmitRro(EmitterContext context, Operand srcB, int rd, bool absB, bool negB)
87          {
88              // This is the range reduction operator,
89              // we translate it as a simple move, as it
90              // should be always followed by a matching
91              // MUFU instruction.
92              srcB = context.FPAbsNeg(srcB, absB, negB);
93  
94              context.Copy(GetDest(rd), srcB);
95          }
96      }
97  }