InstEmitAluHelper.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 long GetIntMin(ISrcDstFmt type)
  34. {
  35. return type switch
  36. {
  37. ISrcDstFmt.U8 => byte.MinValue,
  38. ISrcDstFmt.S8 => sbyte.MinValue,
  39. ISrcDstFmt.U16 => ushort.MinValue,
  40. ISrcDstFmt.S16 => short.MinValue,
  41. ISrcDstFmt.U32 => uint.MinValue,
  42. ISrcDstFmt.S32 => int.MinValue,
  43. _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
  44. };
  45. }
  46. public static long GetIntMax(ISrcDstFmt type)
  47. {
  48. return type switch
  49. {
  50. ISrcDstFmt.U8 => byte.MaxValue,
  51. ISrcDstFmt.S8 => sbyte.MaxValue,
  52. ISrcDstFmt.U16 => ushort.MaxValue,
  53. ISrcDstFmt.S16 => short.MaxValue,
  54. ISrcDstFmt.U32 => uint.MaxValue,
  55. ISrcDstFmt.S32 => int.MaxValue,
  56. _ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
  57. };
  58. }
  59. public static Operand GetPredLogicalOp(EmitterContext context, BoolOp logicOp, Operand input, Operand pred)
  60. {
  61. return logicOp switch
  62. {
  63. BoolOp.And => context.BitwiseAnd(input, pred),
  64. BoolOp.Or => context.BitwiseOr(input, pred),
  65. BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
  66. _ => input
  67. };
  68. }
  69. public static void SetZnFlags(EmitterContext context, Operand dest, bool setCC, bool extended = false)
  70. {
  71. if (!setCC)
  72. {
  73. return;
  74. }
  75. if (extended)
  76. {
  77. // When the operation is extended, it means we are doing
  78. // the operation on a long word with any number of bits,
  79. // so we need to AND the zero flag from result with the
  80. // previous result when extended is specified, to ensure
  81. // we have ZF set only if all words are zero, and not just
  82. // the last one.
  83. Operand oldZF = GetZF();
  84. Operand res = context.BitwiseAnd(context.ICompareEqual(dest, Const(0)), oldZF);
  85. context.Copy(GetZF(), res);
  86. }
  87. else
  88. {
  89. context.Copy(GetZF(), context.ICompareEqual(dest, Const(0)));
  90. }
  91. context.Copy(GetNF(), context.ICompareLess(dest, Const(0)));
  92. }
  93. public static void SetFPZnFlags(EmitterContext context, Operand dest, bool setCC, Instruction fpType = Instruction.FP32)
  94. {
  95. if (setCC)
  96. {
  97. Operand zero = ConstF(0);
  98. if (fpType == Instruction.FP64)
  99. {
  100. zero = context.FP32ConvertToFP64(zero);
  101. }
  102. context.Copy(GetZF(), context.FPCompareEqual(dest, zero, fpType));
  103. context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
  104. }
  105. }
  106. public static Operand AddWithCarry(EmitterContext context, Operand lhs, Operand rhs, out Operand carryOut)
  107. {
  108. Operand result = context.IAdd(lhs, rhs);
  109. // C = Rd < Rn
  110. carryOut = context.INegate(context.ICompareLessUnsigned(result, lhs));
  111. return result;
  112. }
  113. }
  114. }