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