InstEmitAluHelper.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using System;
  5. using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
  6. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  7. namespace Ryujinx.Graphics.Shader.Instructions
  8. {
  9. static class InstEmitAluHelper
  10. {
  11. public static long GetIntMin(IDstFmt type)
  12. {
  13. return type switch
  14. {
  15. IDstFmt.U16 => ushort.MinValue,
  16. IDstFmt.S16 => short.MinValue,
  17. IDstFmt.U32 => uint.MinValue,
  18. IDstFmt.S32 => int.MinValue,
  19. _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
  20. };
  21. }
  22. public static long GetIntMax(IDstFmt type)
  23. {
  24. return type switch
  25. {
  26. IDstFmt.U16 => ushort.MaxValue,
  27. IDstFmt.S16 => short.MaxValue,
  28. IDstFmt.U32 => uint.MaxValue,
  29. IDstFmt.S32 => int.MaxValue,
  30. _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
  31. };
  32. }
  33. public static Operand GetPredLogicalOp(EmitterContext context, BoolOp logicOp, Operand input, Operand pred)
  34. {
  35. return logicOp switch
  36. {
  37. BoolOp.And => context.BitwiseAnd(input, pred),
  38. BoolOp.Or => context.BitwiseOr(input, pred),
  39. BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
  40. _ => input
  41. };
  42. }
  43. public static void SetZnFlags(EmitterContext context, Operand dest, bool setCC, bool extended = false)
  44. {
  45. if (!setCC)
  46. {
  47. return;
  48. }
  49. if (extended)
  50. {
  51. // When the operation is extended, it means we are doing
  52. // the operation on a long word with any number of bits,
  53. // so we need to AND the zero flag from result with the
  54. // previous result when extended is specified, to ensure
  55. // we have ZF set only if all words are zero, and not just
  56. // the last one.
  57. Operand oldZF = GetZF();
  58. Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF);
  59. context.Copy(GetZF(), res);
  60. }
  61. else
  62. {
  63. context.Copy(GetZF(), context.ICompareEqual(dest, Const(0)));
  64. }
  65. context.Copy(GetNF(), context.ICompareLess(dest, Const(0)));
  66. }
  67. public static void SetFPZnFlags(EmitterContext context, Operand dest, bool setCC, Instruction fpType = Instruction.FP32)
  68. {
  69. if (setCC)
  70. {
  71. Operand zero = ConstF(0);
  72. if (fpType == Instruction.FP64)
  73. {
  74. zero = context.FP32ConvertToFP64(zero);
  75. }
  76. context.Copy(GetZF(), context.FPCompareEqual(dest, zero, fpType));
  77. context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
  78. }
  79. }
  80. public static Operand AddWithCarry(EmitterContext context, Operand lhs, Operand rhs, out Operand carryOut)
  81. {
  82. Operand result = context.IAdd(lhs, rhs);
  83. // C = Rd < Rn
  84. carryOut = context.INegate(context.ICompareLessUnsigned(result, lhs));
  85. return result;
  86. }
  87. }
  88. }