Lop3Expression.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  2. using Ryujinx.Graphics.Shader.Translation;
  3. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  4. namespace Ryujinx.Graphics.Shader.Instructions
  5. {
  6. static class Lop3Expression
  7. {
  8. private enum TruthTable : byte
  9. {
  10. False = 0x00, // false
  11. True = 0xff, // true
  12. In = 0xf0, // a
  13. And2 = 0xc0, // a & b
  14. Or2 = 0xfc, // a | b
  15. Xor2 = 0x3c, // a ^ b
  16. And3 = 0x80, // a & b & c
  17. Or3 = 0xfe, // a | b | c
  18. XorAnd = 0x60, // a & (b ^ c)
  19. XorOr = 0xf6, // a | (b ^ c)
  20. OrAnd = 0xe0, // a & (b | c)
  21. AndOr = 0xf8, // a | (b & c)
  22. Onehot = 0x16, // (a & !b & !c) | (!a & b & !c) | (!a & !b & c) - Only one value is true.
  23. Majority = 0xe8, // Popcount(a, b, c) >= 2
  24. Gamble = 0x81, // (a & b & c) | (!a & !b & !c) - All on or all off
  25. InverseGamble = 0x7e, // Inverse of Gamble
  26. Dot = 0x1a, // a ^ (c | (a & b))
  27. Mux = 0xca, // a ? b : c
  28. AndXor = 0x78, // a ^ (b & c)
  29. OrXor = 0x1e, // a ^ (b | c)
  30. Xor3 = 0x96, // a ^ b ^ c
  31. }
  32. public static Operand GetFromTruthTable(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int imm)
  33. {
  34. for (int i = 0; i < 0x40; i++)
  35. {
  36. TruthTable currImm = (TruthTable)imm;
  37. Operand x = srcA;
  38. Operand y = srcB;
  39. Operand z = srcC;
  40. if ((i & 0x01) != 0)
  41. {
  42. (x, y) = (y, x);
  43. currImm = PermuteTable(currImm, 7, 6, 3, 2, 5, 4, 1, 0);
  44. }
  45. if ((i & 0x02) != 0)
  46. {
  47. (x, z) = (z, x);
  48. currImm = PermuteTable(currImm, 7, 3, 5, 1, 6, 2, 4, 0);
  49. }
  50. if ((i & 0x04) != 0)
  51. {
  52. (y, z) = (z, y);
  53. currImm = PermuteTable(currImm, 7, 5, 6, 4, 3, 1, 2, 0);
  54. }
  55. if ((i & 0x08) != 0)
  56. {
  57. x = context.BitwiseNot(x);
  58. currImm = PermuteTable(currImm, 3, 2, 1, 0, 7, 6, 5, 4);
  59. }
  60. if ((i & 0x10) != 0)
  61. {
  62. y = context.BitwiseNot(y);
  63. currImm = PermuteTable(currImm, 5, 4, 7, 6, 1, 0, 3, 2);
  64. }
  65. if ((i & 0x20) != 0)
  66. {
  67. z = context.BitwiseNot(z);
  68. currImm = PermuteTable(currImm, 6, 7, 4, 5, 2, 3, 0, 1);
  69. }
  70. Operand result = GetExpr(currImm, context, x, y, z);
  71. if (result != null)
  72. {
  73. return result;
  74. }
  75. Operand notResult = GetExpr((TruthTable)((~(int)currImm) & 0xff), context, x, y, z);
  76. if (notResult != null)
  77. {
  78. return context.BitwiseNot(notResult);
  79. }
  80. }
  81. return null;
  82. }
  83. private static Operand GetExpr(TruthTable imm, EmitterContext context, Operand x, Operand y, Operand z)
  84. {
  85. return imm switch
  86. {
  87. TruthTable.False => Const(0),
  88. TruthTable.True => Const(-1),
  89. TruthTable.In => x,
  90. TruthTable.And2 => context.BitwiseAnd(x, y),
  91. TruthTable.Or2 => context.BitwiseOr(x, y),
  92. TruthTable.Xor2 => context.BitwiseExclusiveOr(x, y),
  93. TruthTable.And3 => context.BitwiseAnd(x, context.BitwiseAnd(y, z)),
  94. TruthTable.Or3 => context.BitwiseOr(x, context.BitwiseOr(y, z)),
  95. TruthTable.XorAnd => context.BitwiseAnd(x, context.BitwiseExclusiveOr(y, z)),
  96. TruthTable.XorOr => context.BitwiseOr(x, context.BitwiseExclusiveOr(y, z)),
  97. TruthTable.OrAnd => context.BitwiseAnd(x, context.BitwiseOr(y, z)),
  98. TruthTable.AndOr => context.BitwiseOr(x, context.BitwiseAnd(y, z)),
  99. TruthTable.Onehot => context.BitwiseExclusiveOr(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
  100. TruthTable.Majority => context.BitwiseAnd(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
  101. TruthTable.InverseGamble => context.BitwiseOr(context.BitwiseExclusiveOr(x, y), context.BitwiseExclusiveOr(x, z)),
  102. TruthTable.Dot => context.BitwiseAnd(context.BitwiseExclusiveOr(x, z), context.BitwiseOr(context.BitwiseNot(y), z)),
  103. TruthTable.Mux => context.BitwiseOr(context.BitwiseAnd(x, y), context.BitwiseAnd(context.BitwiseNot(x), z)),
  104. TruthTable.AndXor => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)),
  105. TruthTable.OrXor => context.BitwiseExclusiveOr(x, context.BitwiseOr(y, z)),
  106. TruthTable.Xor3 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)),
  107. _ => null
  108. };
  109. }
  110. private static TruthTable PermuteTable(TruthTable imm, int bit7, int bit6, int bit5, int bit4, int bit3, int bit2, int bit1, int bit0)
  111. {
  112. int result = 0;
  113. result |= (((int)imm >> 0) & 1) << bit0;
  114. result |= (((int)imm >> 1) & 1) << bit1;
  115. result |= (((int)imm >> 2) & 1) << bit2;
  116. result |= (((int)imm >> 3) & 1) << bit3;
  117. result |= (((int)imm >> 4) & 1) << bit4;
  118. result |= (((int)imm >> 5) & 1) << bit5;
  119. result |= (((int)imm >> 6) & 1) << bit6;
  120. result |= (((int)imm >> 7) & 1) << bit7;
  121. return (TruthTable)result;
  122. }
  123. }
  124. }