InstEmitConversion.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
  6. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  7. namespace Ryujinx.Graphics.Shader.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void F2F(EmitterContext context)
  12. {
  13. OpCodeFArith op = (OpCodeFArith)context.CurrOp;
  14. FPType srcType = (FPType)op.RawOpCode.Extract(8, 2);
  15. FPType dstType = (FPType)op.RawOpCode.Extract(10, 2);
  16. bool pass = op.RawOpCode.Extract(40);
  17. bool negateB = op.RawOpCode.Extract(45);
  18. bool absoluteB = op.RawOpCode.Extract(49);
  19. pass &= op.RoundingMode == RoundingMode.TowardsNegativeInfinity;
  20. Operand srcB = context.FPAbsNeg(GetSrcB(context, srcType), absoluteB, negateB);
  21. if (!pass)
  22. {
  23. switch (op.RoundingMode)
  24. {
  25. case RoundingMode.ToNearest:
  26. srcB = context.FPRound(srcB);
  27. break;
  28. case RoundingMode.TowardsNegativeInfinity:
  29. srcB = context.FPFloor(srcB);
  30. break;
  31. case RoundingMode.TowardsPositiveInfinity:
  32. srcB = context.FPCeiling(srcB);
  33. break;
  34. case RoundingMode.TowardsZero:
  35. srcB = context.FPTruncate(srcB);
  36. break;
  37. }
  38. }
  39. srcB = context.FPSaturate(srcB, op.Saturate);
  40. WriteFP(context, dstType, srcB);
  41. // TODO: CC.
  42. }
  43. public static void F2I(EmitterContext context)
  44. {
  45. OpCodeFArith op = (OpCodeFArith)context.CurrOp;
  46. IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2);
  47. bool isSmallInt = intType <= IntegerType.U16;
  48. FPType floatType = (FPType)op.RawOpCode.Extract(10, 2);
  49. bool isSignedInt = op.RawOpCode.Extract(12);
  50. bool negateB = op.RawOpCode.Extract(45);
  51. bool absoluteB = op.RawOpCode.Extract(49);
  52. if (isSignedInt)
  53. {
  54. intType |= IntegerType.S8;
  55. }
  56. Operand srcB = context.FPAbsNeg(GetSrcB(context, floatType), absoluteB, negateB);
  57. switch (op.RoundingMode)
  58. {
  59. case RoundingMode.TowardsNegativeInfinity:
  60. srcB = context.FPFloor(srcB);
  61. break;
  62. case RoundingMode.TowardsPositiveInfinity:
  63. srcB = context.FPCeiling(srcB);
  64. break;
  65. case RoundingMode.TowardsZero:
  66. srcB = context.FPTruncate(srcB);
  67. break;
  68. }
  69. srcB = context.FPConvertToS32(srcB);
  70. // TODO: S/U64, conversion overflow handling.
  71. if (intType != IntegerType.S32)
  72. {
  73. int min = GetIntMin(intType);
  74. int max = GetIntMax(intType);
  75. srcB = isSignedInt
  76. ? context.IClampS32(srcB, Const(min), Const(max))
  77. : context.IClampU32(srcB, Const(min), Const(max));
  78. }
  79. Operand dest = GetDest(context);
  80. context.Copy(dest, srcB);
  81. // TODO: CC.
  82. }
  83. public static void I2F(EmitterContext context)
  84. {
  85. OpCodeAlu op = (OpCodeAlu)context.CurrOp;
  86. FPType dstType = (FPType)op.RawOpCode.Extract(8, 2);
  87. IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2);
  88. bool isSmallInt = srcType <= IntegerType.U16;
  89. bool isSignedInt = op.RawOpCode.Extract(13);
  90. bool negateB = op.RawOpCode.Extract(45);
  91. bool absoluteB = op.RawOpCode.Extract(49);
  92. Operand srcB = context.IAbsNeg(GetSrcB(context), absoluteB, negateB);
  93. if (isSmallInt)
  94. {
  95. int size = srcType == IntegerType.U16 ? 16 : 8;
  96. srcB = isSignedInt
  97. ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size))
  98. : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size));
  99. }
  100. srcB = isSignedInt
  101. ? context.IConvertS32ToFP(srcB)
  102. : context.IConvertU32ToFP(srcB);
  103. WriteFP(context, dstType, srcB);
  104. // TODO: CC.
  105. }
  106. public static void I2I(EmitterContext context)
  107. {
  108. OpCodeAlu op = (OpCodeAlu)context.CurrOp;
  109. IntegerType dstType = (IntegerType)op.RawOpCode.Extract(8, 2);
  110. IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2);
  111. if (srcType == IntegerType.U64 || dstType == IntegerType.U64)
  112. {
  113. // TODO: Warning. This instruction doesn't support 64-bits integers
  114. }
  115. bool srcIsSmallInt = srcType <= IntegerType.U16;
  116. bool dstIsSignedInt = op.RawOpCode.Extract(12);
  117. bool srcIsSignedInt = op.RawOpCode.Extract(13);
  118. bool negateB = op.RawOpCode.Extract(45);
  119. bool absoluteB = op.RawOpCode.Extract(49);
  120. Operand srcB = GetSrcB(context);
  121. if (srcIsSmallInt)
  122. {
  123. int size = srcType == IntegerType.U16 ? 16 : 8;
  124. srcB = srcIsSignedInt
  125. ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size))
  126. : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size));
  127. }
  128. srcB = context.IAbsNeg(srcB, absoluteB, negateB);
  129. if (op.Saturate)
  130. {
  131. if (dstIsSignedInt)
  132. {
  133. dstType |= IntegerType.S8;
  134. }
  135. int min = GetIntMin(dstType);
  136. int max = GetIntMax(dstType);
  137. srcB = dstIsSignedInt
  138. ? context.IClampS32(srcB, Const(min), Const(max))
  139. : context.IClampU32(srcB, Const(min), Const(max));
  140. }
  141. context.Copy(GetDest(context), srcB);
  142. // TODO: CC.
  143. }
  144. private static void WriteFP(EmitterContext context, FPType type, Operand srcB)
  145. {
  146. Operand dest = GetDest(context);
  147. if (type == FPType.FP32)
  148. {
  149. context.Copy(dest, srcB);
  150. }
  151. else if (type == FPType.FP16)
  152. {
  153. context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0)));
  154. }
  155. else
  156. {
  157. // TODO.
  158. }
  159. }
  160. }
  161. }