TruthTable

This commit is contained in:
merry 2022-03-08 13:25:04 +00:00
parent 739c2178ab
commit b6d9cc824e

View file

@ -7,6 +7,26 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
static class Lop3Expression static class Lop3Expression
{ {
private enum TruthTable : byte
{
False = 0x00, // false
True = 0xff, // true
In = 0xf0, // a
And2 = 0xc0, // a & b
Xor2 = 0x3c, // a ^ b
And3 = 0x80, // a & b & c
XorAnd = 0x60, // a & (b ^ c)
OrAnd = 0xe0, // a & (b | c)
Onehot = 0x16, // (a & !b & !c) | (!a & b & !c) | (!a & !b & c) - Only one value is true.
Majority = 0xe8, // Popcount(a, b, c) >= 2
Gamble = 0x81, // (a & b & c) | (!a & !b & !c) - All on or all off
InverseGamble = 0x7e, // Inverse of Gamble
Dot = 0x1a, // a ^ (c | (a & b))
Mux = 0xca, // a ? b : c
AndXor = 0x78, // a ^ (b & c)
Xor3 = 0x96, // a ^ b ^ c
}
public static Operand GetFromTruthTable(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int imm) public static Operand GetFromTruthTable(EmitterContext context, Operand srcA, Operand srcB, Operand srcC, int imm)
{ {
Operand notSrcA = context.BitwiseNot(srcA); Operand notSrcA = context.BitwiseNot(srcA);
@ -15,7 +35,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
for (int i = 0; i < 0x40; i++) for (int i = 0; i < 0x40; i++)
{ {
int currImm = imm; TruthTable currImm = (TruthTable)imm;
Operand x = srcA; Operand x = srcA;
Operand y = srcB; Operand y = srcB;
@ -24,37 +44,37 @@ namespace Ryujinx.Graphics.Shader.Instructions
if ((i & 0x01) != 0) if ((i & 0x01) != 0)
{ {
x = notSrcA; x = notSrcA;
currImm = PermuteByte(currImm, 3, 2, 1, 0, 7, 6, 5, 4); currImm = PermuteTable(currImm, 3, 2, 1, 0, 7, 6, 5, 4);
} }
if ((i & 0x02) != 0) if ((i & 0x02) != 0)
{ {
y = notSrcB; y = notSrcB;
currImm = PermuteByte(currImm, 5, 4, 7, 6, 1, 0, 3, 2); currImm = PermuteTable(currImm, 5, 4, 7, 6, 1, 0, 3, 2);
} }
if ((i & 0x04) != 0) if ((i & 0x04) != 0)
{ {
z = notSrcC; z = notSrcC;
currImm = PermuteByte(currImm, 6, 7, 4, 5, 2, 3, 0, 1); currImm = PermuteTable(currImm, 6, 7, 4, 5, 2, 3, 0, 1);
} }
if ((i & 0x08) != 0) if ((i & 0x08) != 0)
{ {
(x, y) = (y, x); (x, y) = (y, x);
currImm = PermuteByte(currImm, 7, 6, 3, 2, 5, 4, 1, 0); currImm = PermuteTable(currImm, 7, 6, 3, 2, 5, 4, 1, 0);
} }
if ((i & 0x10) != 0) if ((i & 0x10) != 0)
{ {
(x, z) = (z, x); (x, z) = (z, x);
currImm = PermuteByte(currImm, 7, 3, 5, 1, 6, 2, 4, 0); currImm = PermuteTable(currImm, 7, 3, 5, 1, 6, 2, 4, 0);
} }
if ((i & 0x20) != 0) if ((i & 0x20) != 0)
{ {
(y, z) = (z, y); (y, z) = (z, y);
currImm = PermuteByte(currImm, 7, 5, 6, 4, 3, 1, 2, 0); currImm = PermuteTable(currImm, 7, 5, 6, 4, 3, 1, 2, 0);
} }
Operand result = GetExpr(currImm, context, x, y, z); Operand result = GetExpr(currImm, context, x, y, z);
@ -63,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
return result; return result;
} }
Operand notResult = GetExpr((~currImm) & 0xff, context, x, y, z); Operand notResult = GetExpr((TruthTable)((~(int)currImm) & 0xff), context, x, y, z);
if (notResult != null) if (notResult != null)
{ {
return context.BitwiseNot(notResult); return context.BitwiseNot(notResult);
@ -73,59 +93,43 @@ namespace Ryujinx.Graphics.Shader.Instructions
return null; return null;
} }
private static Operand GetExpr(int imm, EmitterContext context, Operand x, Operand y, Operand z) private static Operand GetExpr(TruthTable imm, EmitterContext context, Operand x, Operand y, Operand z)
{ {
return imm switch return imm switch
{ {
// False TruthTable.False => Const(IrConsts.False),
0x00 => Const(IrConsts.False), TruthTable.True => Const(IrConsts.True),
// True TruthTable.In => x,
0xff => Const(IrConsts.True), TruthTable.And2 => context.BitwiseAnd(x, y),
// In TruthTable.Xor2 => context.BitwiseExclusiveOr(x, y),
0xf0 => x, TruthTable.And3 => context.BitwiseAnd(x, context.BitwiseAnd(y, z)),
// And2 TruthTable.XorAnd => context.BitwiseAnd(x, context.BitwiseExclusiveOr(y, z)),
0xc0 => context.BitwiseAnd(x, y), TruthTable.OrAnd => context.BitwiseAnd(x, context.BitwiseOr(y, z)),
// Xor2 TruthTable.Onehot => context.BitwiseExclusiveOr(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
0x3c => context.BitwiseExclusiveOr(x, y), TruthTable.Majority => context.BitwiseAnd(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
// And3 TruthTable.InverseGamble => context.BitwiseOr(context.BitwiseExclusiveOr(x, y), context.BitwiseExclusiveOr(x, z)),
0x80 => context.BitwiseAnd(x, context.BitwiseAnd(y, z)), TruthTable.Dot => context.BitwiseAnd(context.BitwiseExclusiveOr(x, z), context.BitwiseOr(context.BitwiseNot(y), z)),
// XorAnd TruthTable.Mux => context.BitwiseOr(context.BitwiseAnd(x, y), context.BitwiseAnd(context.BitwiseNot(x), z)),
0x60 => context.BitwiseAnd(x, context.BitwiseExclusiveOr(y, z)), TruthTable.AndXor => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)),
// OrAnd TruthTable.Xor3 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)),
0xe0 => context.BitwiseAnd(x, context.BitwiseOr(y, z)), _ => null
// Onehot
0x16 => context.BitwiseExclusiveOr(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
// Majority
0xe8 => context.BitwiseAnd(context.BitwiseOr(x, y), context.BitwiseOr(z, context.BitwiseAnd(x, y))),
// Inverse Gamble
0x7e => context.BitwiseOr(context.BitwiseExclusiveOr(x, y), context.BitwiseExclusiveOr(x, z)),
// Dot
0x1a => context.BitwiseAnd(context.BitwiseExclusiveOr(x, z), context.BitwiseOr(context.BitwiseNot(y), z)),
// Mux
0xca => context.BitwiseOr(context.BitwiseAnd(x, y), context.BitwiseAnd(context.BitwiseNot(x), z)),
// AndXor
0x78 => context.BitwiseExclusiveOr(x, context.BitwiseAnd(y, z)),
// Xor3
0x96 => context.BitwiseExclusiveOr(x, context.BitwiseExclusiveOr(y, z)),
// Not one of the base cases
_ => null
}; };
} }
private static int PermuteByte(int imm, int bit7, int bit6, int bit5, int bit4, int bit3, int bit2, int bit1, int bit0) private static TruthTable PermuteTable(TruthTable imm, int bit7, int bit6, int bit5, int bit4, int bit3, int bit2, int bit1, int bit0)
{ {
int result = 0; int result = 0;
result |= ((imm >> 0) & 1) << bit0; result |= (((int)imm >> 0) & 1) << bit0;
result |= ((imm >> 1) & 1) << bit1; result |= (((int)imm >> 1) & 1) << bit1;
result |= ((imm >> 2) & 1) << bit2; result |= (((int)imm >> 2) & 1) << bit2;
result |= ((imm >> 3) & 1) << bit3; result |= (((int)imm >> 3) & 1) << bit3;
result |= ((imm >> 4) & 1) << bit4; result |= (((int)imm >> 4) & 1) << bit4;
result |= ((imm >> 5) & 1) << bit5; result |= (((int)imm >> 5) & 1) << bit5;
result |= ((imm >> 6) & 1) << bit6; result |= (((int)imm >> 6) & 1) << bit6;
result |= ((imm >> 7) & 1) << bit7; result |= (((int)imm >> 7) & 1) << bit7;
return result; return (TruthTable)result;
} }
} }
} }