InstEmitAluHelper.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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(IntegerType type)
  12. {
  13. switch (type)
  14. {
  15. case IntegerType.U8: return byte.MinValue;
  16. case IntegerType.S8: return sbyte.MinValue;
  17. case IntegerType.U16: return ushort.MinValue;
  18. case IntegerType.S16: return short.MinValue;
  19. case IntegerType.U32: return uint.MinValue;
  20. case IntegerType.S32: return int.MinValue;
  21. }
  22. throw new ArgumentException($"The type \"{type}\" is not a supported int type.");
  23. }
  24. public static long GetIntMax(IntegerType type)
  25. {
  26. switch (type)
  27. {
  28. case IntegerType.U8: return byte.MaxValue;
  29. case IntegerType.S8: return sbyte.MaxValue;
  30. case IntegerType.U16: return ushort.MaxValue;
  31. case IntegerType.S16: return short.MaxValue;
  32. case IntegerType.U32: return uint.MaxValue;
  33. case IntegerType.S32: return int.MaxValue;
  34. }
  35. throw new ArgumentException($"The type \"{type}\" is not a supported int type.");
  36. }
  37. public static Operand GetPredLogicalOp(
  38. EmitterContext context,
  39. LogicalOperation logicalOp,
  40. Operand input,
  41. Operand pred)
  42. {
  43. switch (logicalOp)
  44. {
  45. case LogicalOperation.And: return context.BitwiseAnd (input, pred);
  46. case LogicalOperation.Or: return context.BitwiseOr (input, pred);
  47. case LogicalOperation.ExclusiveOr: return context.BitwiseExclusiveOr(input, pred);
  48. }
  49. return input;
  50. }
  51. public static void SetZnFlags(EmitterContext context, Operand dest, bool setCC, bool extended = false)
  52. {
  53. if (!setCC)
  54. {
  55. return;
  56. }
  57. if (extended)
  58. {
  59. // When the operation is extended, it means we are doing
  60. // the operation on a long word with any number of bits,
  61. // so we need to AND the zero flag from result with the
  62. // previous result when extended is specified, to ensure
  63. // we have ZF set only if all words are zero, and not just
  64. // the last one.
  65. Operand oldZF = GetZF();
  66. Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF);
  67. context.Copy(GetZF(), res);
  68. }
  69. else
  70. {
  71. context.Copy(GetZF(), context.ICompareEqual(dest, Const(0)));
  72. }
  73. context.Copy(GetNF(), context.ICompareLess(dest, Const(0)));
  74. }
  75. public static void SetFPZnFlags(EmitterContext context, Operand dest, bool setCC, Instruction fpType = Instruction.FP32)
  76. {
  77. if (setCC)
  78. {
  79. Operand zero = ConstF(0);
  80. if (fpType == Instruction.FP64)
  81. {
  82. zero = context.FP32ConvertToFP64(zero);
  83. }
  84. context.Copy(GetZF(), context.FPCompareEqual(dest, zero, fpType));
  85. context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
  86. }
  87. }
  88. public static Operand AddWithCarry(EmitterContext context, Operand lhs, Operand rhs, out Operand carryOut)
  89. {
  90. Operand result = context.IAdd(lhs, rhs);
  91. // C = Rd < Rn
  92. carryOut = context.INegate(context.ICompareLessUnsigned(result, lhs));
  93. return result;
  94. }
  95. }
  96. }