ShaderDecodeAlu.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. using System;
  2. using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
  3. namespace Ryujinx.Graphics.Gal.Shader
  4. {
  5. static partial class ShaderDecode
  6. {
  7. public static void Bfe_C(ShaderIrBlock Block, long OpCode)
  8. {
  9. EmitBfe(Block, OpCode, ShaderOper.CR);
  10. }
  11. public static void Bfe_I(ShaderIrBlock Block, long OpCode)
  12. {
  13. EmitBfe(Block, OpCode, ShaderOper.Imm);
  14. }
  15. public static void Bfe_R(ShaderIrBlock Block, long OpCode)
  16. {
  17. EmitBfe(Block, OpCode, ShaderOper.RR);
  18. }
  19. public static void Fadd_C(ShaderIrBlock Block, long OpCode)
  20. {
  21. EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fadd);
  22. }
  23. public static void Fadd_I(ShaderIrBlock Block, long OpCode)
  24. {
  25. EmitAluBinaryF(Block, OpCode, ShaderOper.Immf, ShaderIrInst.Fadd);
  26. }
  27. public static void Fadd_R(ShaderIrBlock Block, long OpCode)
  28. {
  29. EmitAluBinaryF(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fadd);
  30. }
  31. public static void Ffma_CR(ShaderIrBlock Block, long OpCode)
  32. {
  33. EmitFfma(Block, OpCode, ShaderOper.CR);
  34. }
  35. public static void Ffma_I(ShaderIrBlock Block, long OpCode)
  36. {
  37. EmitFfma(Block, OpCode, ShaderOper.Immf);
  38. }
  39. public static void Ffma_RC(ShaderIrBlock Block, long OpCode)
  40. {
  41. EmitFfma(Block, OpCode, ShaderOper.RC);
  42. }
  43. public static void Ffma_RR(ShaderIrBlock Block, long OpCode)
  44. {
  45. EmitFfma(Block, OpCode, ShaderOper.RR);
  46. }
  47. public static void Fmnmx_C(ShaderIrBlock Block, long OpCode)
  48. {
  49. EmitFmnmx(Block, OpCode, ShaderOper.CR);
  50. }
  51. public static void Fmnmx_I(ShaderIrBlock Block, long OpCode)
  52. {
  53. EmitFmnmx(Block, OpCode, ShaderOper.Immf);
  54. }
  55. public static void Fmnmx_R(ShaderIrBlock Block, long OpCode)
  56. {
  57. EmitFmnmx(Block, OpCode, ShaderOper.RR);
  58. }
  59. public static void Fmul_I32(ShaderIrBlock Block, long OpCode)
  60. {
  61. ShaderIrNode OperA = GetOperGpr8 (OpCode);
  62. ShaderIrNode OperB = GetOperImmf32_20(OpCode);
  63. ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Fmul, OperA, OperB);
  64. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  65. }
  66. public static void Fmul_C(ShaderIrBlock Block, long OpCode)
  67. {
  68. EmitAluBinaryF(Block, OpCode, ShaderOper.CR, ShaderIrInst.Fmul);
  69. }
  70. public static void Fmul_I(ShaderIrBlock Block, long OpCode)
  71. {
  72. EmitAluBinaryF(Block, OpCode, ShaderOper.Immf, ShaderIrInst.Fmul);
  73. }
  74. public static void Fmul_R(ShaderIrBlock Block, long OpCode)
  75. {
  76. EmitAluBinaryF(Block, OpCode, ShaderOper.RR, ShaderIrInst.Fmul);
  77. }
  78. public static void Fset_C(ShaderIrBlock Block, long OpCode)
  79. {
  80. EmitFset(Block, OpCode, ShaderOper.CR);
  81. }
  82. public static void Fset_I(ShaderIrBlock Block, long OpCode)
  83. {
  84. EmitFset(Block, OpCode, ShaderOper.Immf);
  85. }
  86. public static void Fset_R(ShaderIrBlock Block, long OpCode)
  87. {
  88. EmitFset(Block, OpCode, ShaderOper.RR);
  89. }
  90. public static void Fsetp_C(ShaderIrBlock Block, long OpCode)
  91. {
  92. EmitFsetp(Block, OpCode, ShaderOper.CR);
  93. }
  94. public static void Fsetp_I(ShaderIrBlock Block, long OpCode)
  95. {
  96. EmitFsetp(Block, OpCode, ShaderOper.Immf);
  97. }
  98. public static void Fsetp_R(ShaderIrBlock Block, long OpCode)
  99. {
  100. EmitFsetp(Block, OpCode, ShaderOper.RR);
  101. }
  102. public static void Ipa(ShaderIrBlock Block, long OpCode)
  103. {
  104. ShaderIrNode OperA = GetOperAbuf28(OpCode);
  105. ShaderIrNode OperB = GetOperGpr20 (OpCode);
  106. ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ipa, OperA, OperB);
  107. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  108. }
  109. public static void Iscadd_C(ShaderIrBlock Block, long OpCode)
  110. {
  111. EmitIscadd(Block, OpCode, ShaderOper.CR);
  112. }
  113. public static void Iscadd_I(ShaderIrBlock Block, long OpCode)
  114. {
  115. EmitIscadd(Block, OpCode, ShaderOper.Imm);
  116. }
  117. public static void Iscadd_R(ShaderIrBlock Block, long OpCode)
  118. {
  119. EmitIscadd(Block, OpCode, ShaderOper.RR);
  120. }
  121. public static void Isetp_C(ShaderIrBlock Block, long OpCode)
  122. {
  123. EmitIsetp(Block, OpCode, ShaderOper.CR);
  124. }
  125. public static void Isetp_I(ShaderIrBlock Block, long OpCode)
  126. {
  127. EmitIsetp(Block, OpCode, ShaderOper.Imm);
  128. }
  129. public static void Isetp_R(ShaderIrBlock Block, long OpCode)
  130. {
  131. EmitIsetp(Block, OpCode, ShaderOper.RR);
  132. }
  133. public static void Lop_I32(ShaderIrBlock Block, long OpCode)
  134. {
  135. int SubOp = (int)(OpCode >> 53) & 3;
  136. bool InvA = ((OpCode >> 55) & 1) != 0;
  137. bool InvB = ((OpCode >> 56) & 1) != 0;
  138. ShaderIrInst Inst = 0;
  139. switch (SubOp)
  140. {
  141. case 0: Inst = ShaderIrInst.And; break;
  142. case 1: Inst = ShaderIrInst.Or; break;
  143. case 2: Inst = ShaderIrInst.Xor; break;
  144. }
  145. ShaderIrNode OperA = GetAluNot(GetOperGpr8(OpCode), InvA);
  146. //SubOp == 3 is pass, used by the not instruction
  147. //which just moves the inverted register value.
  148. if (SubOp < 3)
  149. {
  150. ShaderIrNode OperB = GetAluNot(GetOperImm32_20(OpCode), InvB);
  151. ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB);
  152. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  153. }
  154. else
  155. {
  156. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), OperA), OpCode));
  157. }
  158. }
  159. public static void Mufu(ShaderIrBlock Block, long OpCode)
  160. {
  161. int SubOp = (int)(OpCode >> 20) & 7;
  162. bool AbsA = ((OpCode >> 46) & 1) != 0;
  163. bool NegA = ((OpCode >> 48) & 1) != 0;
  164. ShaderIrInst Inst = 0;
  165. switch (SubOp)
  166. {
  167. case 0: Inst = ShaderIrInst.Fcos; break;
  168. case 1: Inst = ShaderIrInst.Fsin; break;
  169. case 2: Inst = ShaderIrInst.Fex2; break;
  170. case 3: Inst = ShaderIrInst.Flg2; break;
  171. case 4: Inst = ShaderIrInst.Frcp; break;
  172. case 5: Inst = ShaderIrInst.Frsq; break;
  173. default: throw new NotImplementedException(SubOp.ToString());
  174. }
  175. ShaderIrNode OperA = GetOperGpr8(OpCode);
  176. ShaderIrOp Op = new ShaderIrOp(Inst, GetAluFabsFneg(OperA, AbsA, NegA));
  177. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  178. }
  179. public static void Shl_C(ShaderIrBlock Block, long OpCode)
  180. {
  181. EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Lsl);
  182. }
  183. public static void Shl_I(ShaderIrBlock Block, long OpCode)
  184. {
  185. EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Lsl);
  186. }
  187. public static void Shl_R(ShaderIrBlock Block, long OpCode)
  188. {
  189. EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Lsl);
  190. }
  191. public static void Shr_C(ShaderIrBlock Block, long OpCode)
  192. {
  193. EmitAluBinary(Block, OpCode, ShaderOper.CR, GetShrInst(OpCode));
  194. }
  195. public static void Shr_I(ShaderIrBlock Block, long OpCode)
  196. {
  197. EmitAluBinary(Block, OpCode, ShaderOper.Imm, GetShrInst(OpCode));
  198. }
  199. public static void Shr_R(ShaderIrBlock Block, long OpCode)
  200. {
  201. EmitAluBinary(Block, OpCode, ShaderOper.RR, GetShrInst(OpCode));
  202. }
  203. private static ShaderIrInst GetShrInst(long OpCode)
  204. {
  205. bool Signed = ((OpCode >> 48) & 1) != 0;
  206. return Signed ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
  207. }
  208. private static void EmitAluBinary(
  209. ShaderIrBlock Block,
  210. long OpCode,
  211. ShaderOper Oper,
  212. ShaderIrInst Inst)
  213. {
  214. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  215. switch (Oper)
  216. {
  217. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  218. case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
  219. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  220. default: throw new ArgumentException(nameof(Oper));
  221. }
  222. ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
  223. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  224. }
  225. private static void EmitAluBinaryF(
  226. ShaderIrBlock Block,
  227. long OpCode,
  228. ShaderOper Oper,
  229. ShaderIrInst Inst)
  230. {
  231. bool NegB = ((OpCode >> 45) & 1) != 0;
  232. bool AbsA = ((OpCode >> 46) & 1) != 0;
  233. bool NegA = ((OpCode >> 48) & 1) != 0;
  234. bool AbsB = ((OpCode >> 49) & 1) != 0;
  235. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  236. if (Inst == ShaderIrInst.Fadd)
  237. {
  238. OperA = GetAluFabsFneg(OperA, AbsA, NegA);
  239. }
  240. switch (Oper)
  241. {
  242. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  243. case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
  244. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  245. default: throw new ArgumentException(nameof(Oper));
  246. }
  247. OperB = GetAluFabsFneg(OperB, AbsB, NegB);
  248. ShaderIrNode Op = new ShaderIrOp(Inst, OperA, OperB);
  249. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  250. }
  251. private static void EmitBfe(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  252. {
  253. //TODO: Handle the case where position + length
  254. //is greater than the word size, in this case the sign bit
  255. //needs to be replicated to fill the remaining space.
  256. bool NegB = ((OpCode >> 48) & 1) != 0;
  257. bool NegA = ((OpCode >> 49) & 1) != 0;
  258. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  259. switch (Oper)
  260. {
  261. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  262. case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
  263. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  264. default: throw new ArgumentException(nameof(Oper));
  265. }
  266. ShaderIrNode Op;
  267. bool Signed = ((OpCode >> 48) & 1) != 0; //?
  268. if (OperB is ShaderIrOperImm PosLen)
  269. {
  270. int Position = (PosLen.Value >> 0) & 0xff;
  271. int Length = (PosLen.Value >> 8) & 0xff;
  272. int LSh = 32 - (Position + Length);
  273. ShaderIrInst RightShift = Signed
  274. ? ShaderIrInst.Asr
  275. : ShaderIrInst.Lsr;
  276. Op = new ShaderIrOp(ShaderIrInst.Lsl, OperA, new ShaderIrOperImm(LSh));
  277. Op = new ShaderIrOp(RightShift, Op, new ShaderIrOperImm(LSh + Position));
  278. }
  279. else
  280. {
  281. ShaderIrOperImm Shift = new ShaderIrOperImm(8);
  282. ShaderIrOperImm Mask = new ShaderIrOperImm(0xff);
  283. ShaderIrNode OpPos, OpLen;
  284. OpPos = new ShaderIrOp(ShaderIrInst.And, OperB, Mask);
  285. OpLen = new ShaderIrOp(ShaderIrInst.Lsr, OperB, Shift);
  286. OpLen = new ShaderIrOp(ShaderIrInst.And, OpLen, Mask);
  287. Op = new ShaderIrOp(ShaderIrInst.Lsr, OperA, OpPos);
  288. Op = ExtendTo32(Op, Signed, OpLen);
  289. }
  290. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  291. }
  292. private static void EmitFfma(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  293. {
  294. bool NegB = ((OpCode >> 48) & 1) != 0;
  295. bool NegC = ((OpCode >> 49) & 1) != 0;
  296. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB, OperC;
  297. switch (Oper)
  298. {
  299. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  300. case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
  301. case ShaderOper.RC: OperB = GetOperGpr39 (OpCode); break;
  302. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  303. default: throw new ArgumentException(nameof(Oper));
  304. }
  305. OperB = GetAluFneg(OperB, NegB);
  306. if (Oper == ShaderOper.RC)
  307. {
  308. OperC = GetAluFneg(GetOperCbuf34(OpCode), NegC);
  309. }
  310. else
  311. {
  312. OperC = GetAluFneg(GetOperGpr39(OpCode), NegC);
  313. }
  314. ShaderIrOp Op = new ShaderIrOp(ShaderIrInst.Ffma, OperA, OperB, OperC);
  315. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  316. }
  317. private static void EmitFmnmx(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  318. {
  319. bool NegB = ((OpCode >> 45) & 1) != 0;
  320. bool AbsA = ((OpCode >> 46) & 1) != 0;
  321. bool NegA = ((OpCode >> 48) & 1) != 0;
  322. bool AbsB = ((OpCode >> 49) & 1) != 0;
  323. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  324. OperA = GetAluFabsFneg(OperA, AbsA, NegA);
  325. switch (Oper)
  326. {
  327. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  328. case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
  329. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  330. default: throw new ArgumentException(nameof(Oper));
  331. }
  332. OperB = GetAluFabsFneg(OperB, AbsB, NegB);
  333. ShaderIrOperPred Pred = GetOperPred39(OpCode);
  334. ShaderIrOp Op;
  335. if (Pred.IsConst)
  336. {
  337. bool IsMax = ((OpCode >> 42) & 1) != 0;
  338. Op = new ShaderIrOp(IsMax
  339. ? ShaderIrInst.Fmax
  340. : ShaderIrInst.Fmin, OperA, OperB);
  341. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), Op), OpCode));
  342. }
  343. else
  344. {
  345. ShaderIrNode PredN = GetOperPred39N(OpCode);
  346. ShaderIrOp OpMax = new ShaderIrOp(ShaderIrInst.Fmax, OperA, OperB);
  347. ShaderIrOp OpMin = new ShaderIrOp(ShaderIrInst.Fmin, OperA, OperB);
  348. ShaderIrAsg AsgMax = new ShaderIrAsg(GetOperGpr0(OpCode), OpMax);
  349. ShaderIrAsg AsgMin = new ShaderIrAsg(GetOperGpr0(OpCode), OpMin);
  350. Block.AddNode(GetPredNode(new ShaderIrCond(PredN, AsgMax, Not: true), OpCode));
  351. Block.AddNode(GetPredNode(new ShaderIrCond(PredN, AsgMin, Not: false), OpCode));
  352. }
  353. }
  354. private static void EmitIscadd(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  355. {
  356. bool NegB = ((OpCode >> 48) & 1) != 0;
  357. bool NegA = ((OpCode >> 49) & 1) != 0;
  358. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  359. ShaderIrOperImm Scale = GetOperImm5_39(OpCode);
  360. switch (Oper)
  361. {
  362. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  363. case ShaderOper.Imm: OperB = GetOperImm19_20(OpCode); break;
  364. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  365. default: throw new ArgumentException(nameof(Oper));
  366. }
  367. OperA = GetAluIneg(OperA, NegA);
  368. OperB = GetAluIneg(OperB, NegB);
  369. ShaderIrOp ScaleOp = new ShaderIrOp(ShaderIrInst.Lsl, OperA, Scale);
  370. ShaderIrOp AddOp = new ShaderIrOp(ShaderIrInst.Add, OperB, ScaleOp);
  371. Block.AddNode(GetPredNode(new ShaderIrAsg(GetOperGpr0(OpCode), AddOp), OpCode));
  372. }
  373. private static void EmitFset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  374. {
  375. EmitSet(Block, OpCode, true, Oper);
  376. }
  377. private static void EmitIset(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  378. {
  379. EmitSet(Block, OpCode, false, Oper);
  380. }
  381. private static void EmitSet(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
  382. {
  383. bool NegA = ((OpCode >> 43) & 1) != 0;
  384. bool AbsB = ((OpCode >> 44) & 1) != 0;
  385. bool BoolFloat = ((OpCode >> 52) & 1) != 0;
  386. bool NegB = ((OpCode >> 53) & 1) != 0;
  387. bool AbsA = ((OpCode >> 54) & 1) != 0;
  388. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  389. switch (Oper)
  390. {
  391. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  392. case ShaderOper.Imm: OperB = GetOperImm19_20 (OpCode); break;
  393. case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
  394. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  395. default: throw new ArgumentException(nameof(Oper));
  396. }
  397. ShaderIrInst CmpInst;
  398. if (IsFloat)
  399. {
  400. OperA = GetAluFabsFneg(OperA, AbsA, NegA);
  401. OperB = GetAluFabsFneg(OperB, AbsB, NegB);
  402. CmpInst = GetCmpF(OpCode);
  403. }
  404. else
  405. {
  406. CmpInst = GetCmp(OpCode);
  407. }
  408. ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);
  409. ShaderIrInst LopInst = GetBLop(OpCode);
  410. ShaderIrOperPred PNode = GetOperPred39(OpCode);
  411. ShaderIrNode Imm0, Imm1;
  412. if (BoolFloat)
  413. {
  414. Imm0 = new ShaderIrOperImmf(0);
  415. Imm1 = new ShaderIrOperImmf(1);
  416. }
  417. else
  418. {
  419. Imm0 = new ShaderIrOperImm(0);
  420. Imm1 = new ShaderIrOperImm(-1);
  421. }
  422. ShaderIrNode Asg0 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm0);
  423. ShaderIrNode Asg1 = new ShaderIrAsg(GetOperGpr0(OpCode), Imm1);
  424. if (LopInst != ShaderIrInst.Band || !PNode.IsConst)
  425. {
  426. ShaderIrOp Op2 = new ShaderIrOp(LopInst, Op, PNode);
  427. Asg0 = new ShaderIrCond(Op2, Asg0, Not: true);
  428. Asg1 = new ShaderIrCond(Op2, Asg1, Not: false);
  429. }
  430. else
  431. {
  432. Asg0 = new ShaderIrCond(Op, Asg0, Not: true);
  433. Asg1 = new ShaderIrCond(Op, Asg1, Not: false);
  434. }
  435. Block.AddNode(GetPredNode(Asg0, OpCode));
  436. Block.AddNode(GetPredNode(Asg1, OpCode));
  437. }
  438. private static void EmitFsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  439. {
  440. EmitSetp(Block, OpCode, true, Oper);
  441. }
  442. private static void EmitIsetp(ShaderIrBlock Block, long OpCode, ShaderOper Oper)
  443. {
  444. EmitSetp(Block, OpCode, false, Oper);
  445. }
  446. private static void EmitSetp(ShaderIrBlock Block, long OpCode, bool IsFloat, ShaderOper Oper)
  447. {
  448. bool AbsA = ((OpCode >> 7) & 1) != 0;
  449. bool NegP = ((OpCode >> 42) & 1) != 0;
  450. bool NegA = ((OpCode >> 43) & 1) != 0;
  451. bool AbsB = ((OpCode >> 44) & 1) != 0;
  452. ShaderIrNode OperA = GetOperGpr8(OpCode), OperB;
  453. switch (Oper)
  454. {
  455. case ShaderOper.CR: OperB = GetOperCbuf34 (OpCode); break;
  456. case ShaderOper.Imm: OperB = GetOperImm19_20 (OpCode); break;
  457. case ShaderOper.Immf: OperB = GetOperImmf19_20(OpCode); break;
  458. case ShaderOper.RR: OperB = GetOperGpr20 (OpCode); break;
  459. default: throw new ArgumentException(nameof(Oper));
  460. }
  461. ShaderIrInst CmpInst;
  462. if (IsFloat)
  463. {
  464. OperA = GetAluFabsFneg(OperA, AbsA, NegA);
  465. OperB = GetAluFabs (OperB, AbsB);
  466. CmpInst = GetCmpF(OpCode);
  467. }
  468. else
  469. {
  470. CmpInst = GetCmp(OpCode);
  471. }
  472. ShaderIrOp Op = new ShaderIrOp(CmpInst, OperA, OperB);
  473. ShaderIrOperPred P0Node = GetOperPred3 (OpCode);
  474. ShaderIrOperPred P1Node = GetOperPred0 (OpCode);
  475. ShaderIrOperPred P2Node = GetOperPred39(OpCode);
  476. Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
  477. ShaderIrInst LopInst = GetBLop(OpCode);
  478. if (LopInst == ShaderIrInst.Band && P1Node.IsConst && P2Node.IsConst)
  479. {
  480. return;
  481. }
  482. ShaderIrNode P2NNode = P2Node;
  483. if (NegP)
  484. {
  485. P2NNode = new ShaderIrOp(ShaderIrInst.Bnot, P2NNode);
  486. }
  487. Op = new ShaderIrOp(ShaderIrInst.Bnot, P0Node);
  488. Op = new ShaderIrOp(LopInst, Op, P2NNode);
  489. Block.AddNode(GetPredNode(new ShaderIrAsg(P1Node, Op), OpCode));
  490. Op = new ShaderIrOp(LopInst, P0Node, P2NNode);
  491. Block.AddNode(GetPredNode(new ShaderIrAsg(P0Node, Op), OpCode));
  492. }
  493. }
  494. }