InstEmitMultifunction.cs 3.1 KB

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