InstEmitConversion.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. if (intType == IntegerType.U64)
  48. {
  49. // TODO: Warning. This instruction supports 64-bits integers, but it is not implemented.
  50. return;
  51. }
  52. bool isSmallInt = intType <= IntegerType.U16;
  53. FPType floatType = (FPType)op.RawOpCode.Extract(10, 2);
  54. bool isSignedInt = op.RawOpCode.Extract(12);
  55. bool negateB = op.RawOpCode.Extract(45);
  56. bool absoluteB = op.RawOpCode.Extract(49);
  57. if (isSignedInt)
  58. {
  59. intType |= IntegerType.S8;
  60. }
  61. Operand srcB = context.FPAbsNeg(GetSrcB(context, floatType), absoluteB, negateB);
  62. switch (op.RoundingMode)
  63. {
  64. case RoundingMode.TowardsNegativeInfinity:
  65. srcB = context.FPFloor(srcB);
  66. break;
  67. case RoundingMode.TowardsPositiveInfinity:
  68. srcB = context.FPCeiling(srcB);
  69. break;
  70. case RoundingMode.TowardsZero:
  71. srcB = context.FPTruncate(srcB);
  72. break;
  73. }
  74. srcB = context.FPConvertToS32(srcB);
  75. // TODO: S/U64, conversion overflow handling.
  76. if (intType != IntegerType.S32)
  77. {
  78. int min = GetIntMin(intType);
  79. int max = GetIntMax(intType);
  80. srcB = isSignedInt
  81. ? context.IClampS32(srcB, Const(min), Const(max))
  82. : context.IClampU32(srcB, Const(min), Const(max));
  83. }
  84. Operand dest = GetDest(context);
  85. context.Copy(dest, srcB);
  86. // TODO: CC.
  87. }
  88. public static void I2F(EmitterContext context)
  89. {
  90. OpCodeAlu op = (OpCodeAlu)context.CurrOp;
  91. FPType dstType = (FPType)op.RawOpCode.Extract(8, 2);
  92. IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2);
  93. // TODO: Handle S/U64.
  94. bool isSmallInt = srcType <= IntegerType.U16;
  95. bool isSignedInt = op.RawOpCode.Extract(13);
  96. bool negateB = op.RawOpCode.Extract(45);
  97. bool absoluteB = op.RawOpCode.Extract(49);
  98. Operand srcB = context.IAbsNeg(GetSrcB(context), absoluteB, negateB);
  99. if (isSmallInt)
  100. {
  101. int size = srcType == IntegerType.U16 ? 16 : 8;
  102. srcB = isSignedInt
  103. ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size))
  104. : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size));
  105. }
  106. srcB = isSignedInt
  107. ? context.IConvertS32ToFP(srcB)
  108. : context.IConvertU32ToFP(srcB);
  109. WriteFP(context, dstType, srcB);
  110. // TODO: CC.
  111. }
  112. public static void I2I(EmitterContext context)
  113. {
  114. OpCodeAlu op = (OpCodeAlu)context.CurrOp;
  115. IntegerType dstType = (IntegerType)op.RawOpCode.Extract(8, 2);
  116. IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2);
  117. if (srcType == IntegerType.U64 || dstType == IntegerType.U64)
  118. {
  119. // TODO: Warning. This instruction doesn't support 64-bits integers.
  120. return;
  121. }
  122. bool srcIsSmallInt = srcType <= IntegerType.U16;
  123. bool dstIsSignedInt = op.RawOpCode.Extract(12);
  124. bool srcIsSignedInt = op.RawOpCode.Extract(13);
  125. bool negateB = op.RawOpCode.Extract(45);
  126. bool absoluteB = op.RawOpCode.Extract(49);
  127. Operand srcB = GetSrcB(context);
  128. if (srcIsSmallInt)
  129. {
  130. int size = srcType == IntegerType.U16 ? 16 : 8;
  131. srcB = srcIsSignedInt
  132. ? context.BitfieldExtractS32(srcB, Const(op.ByteSelection * 8), Const(size))
  133. : context.BitfieldExtractU32(srcB, Const(op.ByteSelection * 8), Const(size));
  134. }
  135. srcB = context.IAbsNeg(srcB, absoluteB, negateB);
  136. if (op.Saturate)
  137. {
  138. if (dstIsSignedInt)
  139. {
  140. dstType |= IntegerType.S8;
  141. }
  142. int min = GetIntMin(dstType);
  143. int max = GetIntMax(dstType);
  144. srcB = dstIsSignedInt
  145. ? context.IClampS32(srcB, Const(min), Const(max))
  146. : context.IClampU32(srcB, Const(min), Const(max));
  147. }
  148. context.Copy(GetDest(context), srcB);
  149. // TODO: CC.
  150. }
  151. private static void WriteFP(EmitterContext context, FPType type, Operand srcB)
  152. {
  153. Operand dest = GetDest(context);
  154. if (type == FPType.FP32)
  155. {
  156. context.Copy(dest, srcB);
  157. }
  158. else if (type == FPType.FP16)
  159. {
  160. context.Copy(dest, context.PackHalf2x16(srcB, ConstF(0)));
  161. }
  162. else
  163. {
  164. // TODO.
  165. }
  166. }
  167. }
  168. }