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 }