ShaderDecodeOpCode.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. using System;
  2. namespace Ryujinx.Graphics.Gal.Shader
  3. {
  4. static partial class ShaderDecode
  5. {
  6. private static int Read(this long OpCode, int Position, int Mask)
  7. {
  8. return (int)(OpCode >> Position) & Mask;
  9. }
  10. private static bool Read(this long OpCode, int Position)
  11. {
  12. return ((OpCode >> Position) & 1) != 0;
  13. }
  14. private static int Branch(this long OpCode)
  15. {
  16. return ((int)(OpCode >> 20) << 8) >> 8;
  17. }
  18. private static bool HasArray(this long OpCode)
  19. {
  20. return OpCode.Read(0x1c);
  21. }
  22. private static ShaderIrOperAbuf[] Abuf20(this long OpCode)
  23. {
  24. int Abuf = OpCode.Read(20, 0x3ff);
  25. int Size = OpCode.Read(47, 3);
  26. ShaderIrOperGpr Vertex = OpCode.Gpr39();
  27. ShaderIrOperAbuf[] Opers = new ShaderIrOperAbuf[Size + 1];
  28. for (int Index = 0; Index <= Size; Index++)
  29. {
  30. Opers[Index] = new ShaderIrOperAbuf(Abuf + Index * 4, Vertex);
  31. }
  32. return Opers;
  33. }
  34. private static ShaderIrOperAbuf Abuf28(this long OpCode)
  35. {
  36. int Abuf = OpCode.Read(28, 0x3ff);
  37. return new ShaderIrOperAbuf(Abuf, OpCode.Gpr39());
  38. }
  39. private static ShaderIrOperCbuf Cbuf34(this long OpCode)
  40. {
  41. return new ShaderIrOperCbuf(
  42. OpCode.Read(34, 0x1f),
  43. OpCode.Read(20, 0x3fff));
  44. }
  45. private static ShaderIrOperGpr Gpr8(this long OpCode)
  46. {
  47. return new ShaderIrOperGpr(OpCode.Read(8, 0xff));
  48. }
  49. private static ShaderIrOperGpr Gpr20(this long OpCode)
  50. {
  51. return new ShaderIrOperGpr(OpCode.Read(20, 0xff));
  52. }
  53. private static ShaderIrOperGpr Gpr39(this long OpCode)
  54. {
  55. return new ShaderIrOperGpr(OpCode.Read(39, 0xff));
  56. }
  57. private static ShaderIrOperGpr Gpr0(this long OpCode)
  58. {
  59. return new ShaderIrOperGpr(OpCode.Read(0, 0xff));
  60. }
  61. private static ShaderIrOperGpr Gpr28(this long OpCode)
  62. {
  63. return new ShaderIrOperGpr(OpCode.Read(28, 0xff));
  64. }
  65. private static ShaderIrOperGpr[] GprHalfVec8(this long OpCode)
  66. {
  67. return GetGprHalfVec2(OpCode.Read(8, 0xff), OpCode.Read(47, 3));
  68. }
  69. private static ShaderIrOperGpr[] GprHalfVec20(this long OpCode)
  70. {
  71. return GetGprHalfVec2(OpCode.Read(20, 0xff), OpCode.Read(28, 3));
  72. }
  73. private static ShaderIrOperGpr[] GetGprHalfVec2(int Gpr, int Mask)
  74. {
  75. if (Mask == 1)
  76. {
  77. //This value is used for FP32, the whole 32-bits register
  78. //is used as each element on the vector.
  79. return new ShaderIrOperGpr[]
  80. {
  81. new ShaderIrOperGpr(Gpr),
  82. new ShaderIrOperGpr(Gpr)
  83. };
  84. }
  85. ShaderIrOperGpr Low = new ShaderIrOperGpr(Gpr, 0);
  86. ShaderIrOperGpr High = new ShaderIrOperGpr(Gpr, 1);
  87. return new ShaderIrOperGpr[]
  88. {
  89. (Mask & 1) != 0 ? High : Low,
  90. (Mask & 2) != 0 ? High : Low
  91. };
  92. }
  93. private static ShaderIrOperGpr GprHalf0(this long OpCode, int HalfPart)
  94. {
  95. return new ShaderIrOperGpr(OpCode.Read(0, 0xff), HalfPart);
  96. }
  97. private static ShaderIrOperGpr GprHalf28(this long OpCode, int HalfPart)
  98. {
  99. return new ShaderIrOperGpr(OpCode.Read(28, 0xff), HalfPart);
  100. }
  101. private static ShaderIrOperImm Imm5_39(this long OpCode)
  102. {
  103. return new ShaderIrOperImm(OpCode.Read(39, 0x1f));
  104. }
  105. private static ShaderIrOperImm Imm13_36(this long OpCode)
  106. {
  107. return new ShaderIrOperImm(OpCode.Read(36, 0x1fff));
  108. }
  109. private static ShaderIrOperImm Imm32_20(this long OpCode)
  110. {
  111. return new ShaderIrOperImm((int)(OpCode >> 20));
  112. }
  113. private static ShaderIrOperImmf Immf32_20(this long OpCode)
  114. {
  115. return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(OpCode >> 20)));
  116. }
  117. private static ShaderIrOperImm ImmU16_20(this long OpCode)
  118. {
  119. return new ShaderIrOperImm(OpCode.Read(20, 0xffff));
  120. }
  121. private static ShaderIrOperImm Imm19_20(this long OpCode)
  122. {
  123. int Value = OpCode.Read(20, 0x7ffff);
  124. bool Neg = OpCode.Read(56);
  125. if (Neg)
  126. {
  127. Value = -Value;
  128. }
  129. return new ShaderIrOperImm(Value);
  130. }
  131. private static ShaderIrOperImmf Immf19_20(this long OpCode)
  132. {
  133. uint Imm = (uint)(OpCode >> 20) & 0x7ffff;
  134. bool Neg = OpCode.Read(56);
  135. Imm <<= 12;
  136. if (Neg)
  137. {
  138. Imm |= 0x80000000;
  139. }
  140. float Value = BitConverter.Int32BitsToSingle((int)Imm);
  141. return new ShaderIrOperImmf(Value);
  142. }
  143. private static ShaderIrOperPred Pred0(this long OpCode)
  144. {
  145. return new ShaderIrOperPred(OpCode.Read(0, 7));
  146. }
  147. private static ShaderIrOperPred Pred3(this long OpCode)
  148. {
  149. return new ShaderIrOperPred(OpCode.Read(3, 7));
  150. }
  151. private static ShaderIrOperPred Pred12(this long OpCode)
  152. {
  153. return new ShaderIrOperPred(OpCode.Read(12, 7));
  154. }
  155. private static ShaderIrOperPred Pred29(this long OpCode)
  156. {
  157. return new ShaderIrOperPred(OpCode.Read(29, 7));
  158. }
  159. private static ShaderIrNode Pred39N(this long OpCode)
  160. {
  161. ShaderIrNode Node = OpCode.Pred39();
  162. if (OpCode.Read(42))
  163. {
  164. Node = new ShaderIrOp(ShaderIrInst.Bnot, Node);
  165. }
  166. return Node;
  167. }
  168. private static ShaderIrOperPred Pred39(this long OpCode)
  169. {
  170. return new ShaderIrOperPred(OpCode.Read(39, 7));
  171. }
  172. private static ShaderIrOperPred Pred48(this long OpCode)
  173. {
  174. return new ShaderIrOperPred(OpCode.Read(48, 7));
  175. }
  176. private static ShaderIrInst Cmp(this long OpCode)
  177. {
  178. switch (OpCode.Read(49, 7))
  179. {
  180. case 1: return ShaderIrInst.Clt;
  181. case 2: return ShaderIrInst.Ceq;
  182. case 3: return ShaderIrInst.Cle;
  183. case 4: return ShaderIrInst.Cgt;
  184. case 5: return ShaderIrInst.Cne;
  185. case 6: return ShaderIrInst.Cge;
  186. }
  187. throw new ArgumentException(nameof(OpCode));
  188. }
  189. private static ShaderIrInst CmpF(this long OpCode)
  190. {
  191. switch (OpCode.Read(48, 0xf))
  192. {
  193. case 0x1: return ShaderIrInst.Fclt;
  194. case 0x2: return ShaderIrInst.Fceq;
  195. case 0x3: return ShaderIrInst.Fcle;
  196. case 0x4: return ShaderIrInst.Fcgt;
  197. case 0x5: return ShaderIrInst.Fcne;
  198. case 0x6: return ShaderIrInst.Fcge;
  199. case 0x7: return ShaderIrInst.Fcnum;
  200. case 0x8: return ShaderIrInst.Fcnan;
  201. case 0x9: return ShaderIrInst.Fcltu;
  202. case 0xa: return ShaderIrInst.Fcequ;
  203. case 0xb: return ShaderIrInst.Fcleu;
  204. case 0xc: return ShaderIrInst.Fcgtu;
  205. case 0xd: return ShaderIrInst.Fcneu;
  206. case 0xe: return ShaderIrInst.Fcgeu;
  207. }
  208. throw new ArgumentException(nameof(OpCode));
  209. }
  210. private static ShaderIrInst BLop45(this long OpCode)
  211. {
  212. switch (OpCode.Read(45, 3))
  213. {
  214. case 0: return ShaderIrInst.Band;
  215. case 1: return ShaderIrInst.Bor;
  216. case 2: return ShaderIrInst.Bxor;
  217. }
  218. throw new ArgumentException(nameof(OpCode));
  219. }
  220. private static ShaderIrInst BLop24(this long OpCode)
  221. {
  222. switch (OpCode.Read(24, 3))
  223. {
  224. case 0: return ShaderIrInst.Band;
  225. case 1: return ShaderIrInst.Bor;
  226. case 2: return ShaderIrInst.Bxor;
  227. }
  228. throw new ArgumentException(nameof(OpCode));
  229. }
  230. private static ShaderIrNode PredNode(this long OpCode, ShaderIrNode Node)
  231. {
  232. ShaderIrOperPred Pred = OpCode.PredNode();
  233. if (Pred.Index != ShaderIrOperPred.UnusedIndex)
  234. {
  235. bool Inv = OpCode.Read(19);
  236. Node = new ShaderIrCond(Pred, Node, Inv);
  237. }
  238. return Node;
  239. }
  240. private static ShaderIrOperPred PredNode(this long OpCode)
  241. {
  242. int Pred = OpCode.Read(16, 0xf);
  243. if (Pred != 0xf)
  244. {
  245. Pred &= 7;
  246. }
  247. return new ShaderIrOperPred(Pred);
  248. }
  249. }
  250. }