aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs')
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs260
1 files changed, 260 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs
new file mode 100644
index 00000000..3af17cae
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs
@@ -0,0 +1,260 @@
+using System;
+
+namespace Ryujinx.Graphics.Gal.Shader
+{
+ static partial class ShaderDecode
+ {
+ private static int Read(this long OpCode, int Position, int Mask)
+ {
+ return (int)(OpCode >> Position) & Mask;
+ }
+
+ private static bool Read(this long OpCode, int Position)
+ {
+ return ((OpCode >> Position) & 1) != 0;
+ }
+
+ private static int Branch(this long OpCode)
+ {
+ return ((int)(OpCode >> 20) << 8) >> 8;
+ }
+
+ private static ShaderIrOperAbuf[] Abuf20(this long OpCode)
+ {
+ int Abuf = OpCode.Read(20, 0x3ff);
+ int Size = OpCode.Read(47, 3);
+
+ ShaderIrOperGpr Vertex = OpCode.Gpr39();
+
+ ShaderIrOperAbuf[] Opers = new ShaderIrOperAbuf[Size + 1];
+
+ for (int Index = 0; Index <= Size; Index++)
+ {
+ Opers[Index] = new ShaderIrOperAbuf(Abuf + Index * 4, Vertex);
+ }
+
+ return Opers;
+ }
+
+ private static ShaderIrOperAbuf Abuf28(this long OpCode)
+ {
+ int Abuf = OpCode.Read(28, 0x3ff);
+
+ return new ShaderIrOperAbuf(Abuf, OpCode.Gpr39());
+ }
+
+ private static ShaderIrOperCbuf Cbuf34(this long OpCode)
+ {
+ return new ShaderIrOperCbuf(
+ OpCode.Read(34, 0x1f),
+ OpCode.Read(20, 0x3fff));
+ }
+
+ private static ShaderIrOperGpr Gpr8(this long OpCode)
+ {
+ return new ShaderIrOperGpr(OpCode.Read(8, 0xff));
+ }
+
+ private static ShaderIrOperGpr Gpr20(this long OpCode)
+ {
+ return new ShaderIrOperGpr(OpCode.Read(20, 0xff));
+ }
+
+ private static ShaderIrOperGpr Gpr39(this long OpCode)
+ {
+ return new ShaderIrOperGpr(OpCode.Read(39, 0xff));
+ }
+
+ private static ShaderIrOperGpr Gpr0(this long OpCode)
+ {
+ return new ShaderIrOperGpr(OpCode.Read(0, 0xff));
+ }
+
+ private static ShaderIrOperGpr Gpr28(this long OpCode)
+ {
+ return new ShaderIrOperGpr(OpCode.Read(28, 0xff));
+ }
+
+ private static ShaderIrOperImm Imm5_39(this long OpCode)
+ {
+ return new ShaderIrOperImm(OpCode.Read(39, 0x1f));
+ }
+
+ private static ShaderIrOperImm Imm13_36(this long OpCode)
+ {
+ return new ShaderIrOperImm(OpCode.Read(36, 0x1fff));
+ }
+
+ private static ShaderIrOperImm Imm32_20(this long OpCode)
+ {
+ return new ShaderIrOperImm((int)(OpCode >> 20));
+ }
+
+ private static ShaderIrOperImmf Immf32_20(this long OpCode)
+ {
+ return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(OpCode >> 20)));
+ }
+
+ private static ShaderIrOperImm Imm19_20(this long OpCode)
+ {
+ int Value = OpCode.Read(20, 0x7ffff);
+
+ bool Neg = OpCode.Read(56);
+
+ if (Neg)
+ {
+ Value = -Value;
+ }
+
+ return new ShaderIrOperImm(Value);
+ }
+
+ private static ShaderIrOperImmf Immf19_20(this long OpCode)
+ {
+ uint Imm = (uint)(OpCode >> 20) & 0x7ffff;
+
+ bool Neg = OpCode.Read(56);
+
+ Imm <<= 12;
+
+ if (Neg)
+ {
+ Imm |= 0x80000000;
+ }
+
+ float Value = BitConverter.Int32BitsToSingle((int)Imm);
+
+ return new ShaderIrOperImmf(Value);
+ }
+
+ private static ShaderIrOperPred Pred0(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(0, 7));
+ }
+
+ private static ShaderIrOperPred Pred3(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(3, 7));
+ }
+
+ private static ShaderIrOperPred Pred12(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(12, 7));
+ }
+
+ private static ShaderIrOperPred Pred29(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(29, 7));
+ }
+
+ private static ShaderIrNode Pred39N(this long OpCode)
+ {
+ ShaderIrNode Node = OpCode.Pred39();
+
+ if (OpCode.Read(42))
+ {
+ Node = new ShaderIrOp(ShaderIrInst.Bnot, Node);
+ }
+
+ return Node;
+ }
+
+ private static ShaderIrOperPred Pred39(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(39, 7));
+ }
+
+ private static ShaderIrOperPred Pred48(this long OpCode)
+ {
+ return new ShaderIrOperPred(OpCode.Read(48, 7));
+ }
+
+ private static ShaderIrInst Cmp(this long OpCode)
+ {
+ switch (OpCode.Read(49, 7))
+ {
+ case 1: return ShaderIrInst.Clt;
+ case 2: return ShaderIrInst.Ceq;
+ case 3: return ShaderIrInst.Cle;
+ case 4: return ShaderIrInst.Cgt;
+ case 5: return ShaderIrInst.Cne;
+ case 6: return ShaderIrInst.Cge;
+ }
+
+ throw new ArgumentException(nameof(OpCode));
+ }
+
+ private static ShaderIrInst CmpF(this long OpCode)
+ {
+ switch (OpCode.Read(48, 0xf))
+ {
+ case 0x1: return ShaderIrInst.Fclt;
+ case 0x2: return ShaderIrInst.Fceq;
+ case 0x3: return ShaderIrInst.Fcle;
+ case 0x4: return ShaderIrInst.Fcgt;
+ case 0x5: return ShaderIrInst.Fcne;
+ case 0x6: return ShaderIrInst.Fcge;
+ case 0x7: return ShaderIrInst.Fcnum;
+ case 0x8: return ShaderIrInst.Fcnan;
+ case 0x9: return ShaderIrInst.Fcltu;
+ case 0xa: return ShaderIrInst.Fcequ;
+ case 0xb: return ShaderIrInst.Fcleu;
+ case 0xc: return ShaderIrInst.Fcgtu;
+ case 0xd: return ShaderIrInst.Fcneu;
+ case 0xe: return ShaderIrInst.Fcgeu;
+ }
+
+ throw new ArgumentException(nameof(OpCode));
+ }
+
+ private static ShaderIrInst BLop45(this long OpCode)
+ {
+ switch (OpCode.Read(45, 3))
+ {
+ case 0: return ShaderIrInst.Band;
+ case 1: return ShaderIrInst.Bor;
+ case 2: return ShaderIrInst.Bxor;
+ }
+
+ throw new ArgumentException(nameof(OpCode));
+ }
+
+ private static ShaderIrInst BLop24(this long OpCode)
+ {
+ switch (OpCode.Read(24, 3))
+ {
+ case 0: return ShaderIrInst.Band;
+ case 1: return ShaderIrInst.Bor;
+ case 2: return ShaderIrInst.Bxor;
+ }
+
+ throw new ArgumentException(nameof(OpCode));
+ }
+
+ private static ShaderIrNode PredNode(this long OpCode, ShaderIrNode Node)
+ {
+ ShaderIrOperPred Pred = OpCode.PredNode();
+
+ if (Pred.Index != ShaderIrOperPred.UnusedIndex)
+ {
+ bool Inv = OpCode.Read(19);
+
+ Node = new ShaderIrCond(Pred, Node, Inv);
+ }
+
+ return Node;
+ }
+
+ private static ShaderIrOperPred PredNode(this long OpCode)
+ {
+ int Pred = OpCode.Read(16, 0xf);
+
+ if (Pred != 0xf)
+ {
+ Pred &= 7;
+ }
+
+ return new ShaderIrOperPred(Pred);
+ }
+ }
+} \ No newline at end of file