aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs266
1 files changed, 266 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
new file mode 100644
index 00000000..0ba4667e
--- /dev/null
+++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs
@@ -0,0 +1,266 @@
+using Ryujinx.Graphics.Shader.Decoders;
+using Ryujinx.Graphics.Shader.IntermediateRepresentation;
+using Ryujinx.Graphics.Shader.Translation;
+using System;
+using System.Runtime.CompilerServices;
+
+using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
+
+namespace Ryujinx.Graphics.Shader.Instructions
+{
+ static class InstEmitHelper
+ {
+ public static Operand GetZF()
+ {
+ return Register(0, RegisterType.Flag);
+ }
+
+ public static Operand GetNF()
+ {
+ return Register(1, RegisterType.Flag);
+ }
+
+ public static Operand GetCF()
+ {
+ return Register(2, RegisterType.Flag);
+ }
+
+ public static Operand GetVF()
+ {
+ return Register(3, RegisterType.Flag);
+ }
+
+ public static Operand GetDest(int rd)
+ {
+ return Register(rd, RegisterType.Gpr);
+ }
+
+ public static Operand GetDest2(int rd)
+ {
+ return Register(rd | 1, RegisterType.Gpr);
+ }
+
+ public static Operand GetSrcCbuf(EmitterContext context, int cbufSlot, int cbufOffset, bool isFP64 = false)
+ {
+ if (isFP64)
+ {
+ return context.PackDouble2x32(
+ Cbuf(cbufSlot, cbufOffset),
+ Cbuf(cbufSlot, cbufOffset + 1));
+ }
+ else
+ {
+ return Cbuf(cbufSlot, cbufOffset);
+ }
+ }
+
+ public static Operand GetSrcImm(EmitterContext context, int imm, bool isFP64 = false)
+ {
+ if (isFP64)
+ {
+ return context.PackDouble2x32(Const(0), Const(imm));
+ }
+ else
+ {
+ return Const(imm);
+ }
+ }
+
+ public static Operand GetSrcReg(EmitterContext context, int reg, bool isFP64 = false)
+ {
+ if (isFP64)
+ {
+ return context.PackDouble2x32(Register(reg, RegisterType.Gpr), Register(reg | 1, RegisterType.Gpr));
+ }
+ else
+ {
+ return Register(reg, RegisterType.Gpr);
+ }
+ }
+
+ public static Operand[] GetHalfSrc(
+ EmitterContext context,
+ HalfSwizzle swizzle,
+ int ra,
+ bool negate,
+ bool absolute)
+ {
+ Operand[] operands = GetHalfUnpacked(context, GetSrcReg(context, ra), swizzle);
+
+ return FPAbsNeg(context, operands, absolute, negate);
+ }
+
+ public static Operand[] GetHalfSrc(
+ EmitterContext context,
+ HalfSwizzle swizzle,
+ int cbufSlot,
+ int cbufOffset,
+ bool negate,
+ bool absolute)
+ {
+ Operand[] operands = GetHalfUnpacked(context, GetSrcCbuf(context, cbufSlot, cbufOffset), swizzle);
+
+ return FPAbsNeg(context, operands, absolute, negate);
+ }
+
+ public static Operand[] GetHalfSrc(EmitterContext context, int immH0, int immH1)
+ {
+ ushort low = (ushort)(immH0 << 6);
+ ushort high = (ushort)(immH1 << 6);
+
+ return new Operand[]
+ {
+ ConstF((float)Unsafe.As<ushort, Half>(ref low)),
+ ConstF((float)Unsafe.As<ushort, Half>(ref high))
+ };
+ }
+
+ public static Operand[] GetHalfSrc(EmitterContext context, int imm32)
+ {
+ ushort low = (ushort)imm32;
+ ushort high = (ushort)(imm32 >> 16);
+
+ return new Operand[]
+ {
+ ConstF((float)Unsafe.As<ushort, Half>(ref low)),
+ ConstF((float)Unsafe.As<ushort, Half>(ref high))
+ };
+ }
+
+ public static Operand[] FPAbsNeg(EmitterContext context, Operand[] operands, bool abs, bool neg)
+ {
+ for (int index = 0; index < operands.Length; index++)
+ {
+ operands[index] = context.FPAbsNeg(operands[index], abs, neg);
+ }
+
+ return operands;
+ }
+
+ public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle)
+ {
+ switch (swizzle)
+ {
+ case HalfSwizzle.F16:
+ return new Operand[]
+ {
+ context.UnpackHalf2x16Low (src),
+ context.UnpackHalf2x16High(src)
+ };
+
+ case HalfSwizzle.F32: return new Operand[] { src, src };
+
+ case HalfSwizzle.H0H0:
+ return new Operand[]
+ {
+ context.UnpackHalf2x16Low(src),
+ context.UnpackHalf2x16Low(src)
+ };
+
+ case HalfSwizzle.H1H1:
+ return new Operand[]
+ {
+ context.UnpackHalf2x16High(src),
+ context.UnpackHalf2x16High(src)
+ };
+ }
+
+ throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
+ }
+
+ public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd)
+ {
+ switch (swizzle)
+ {
+ case OFmt.F16: return context.PackHalf2x16(results[0], results[1]);
+
+ case OFmt.F32: return results[0];
+
+ case OFmt.MrgH0:
+ {
+ Operand h1 = GetHalfDest(context, rd, isHigh: true);
+
+ return context.PackHalf2x16(results[0], h1);
+ }
+
+ case OFmt.MrgH1:
+ {
+ Operand h0 = GetHalfDest(context, rd, isHigh: false);
+
+ return context.PackHalf2x16(h0, results[1]);
+ }
+ }
+
+ throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
+ }
+
+ public static Operand GetHalfDest(EmitterContext context, int rd, bool isHigh)
+ {
+ if (isHigh)
+ {
+ return context.UnpackHalf2x16High(GetDest(rd));
+ }
+ else
+ {
+ return context.UnpackHalf2x16Low(GetDest(rd));
+ }
+ }
+
+ public static Operand GetPredicate(EmitterContext context, int pred, bool not)
+ {
+ Operand local = Register(pred, RegisterType.Predicate);
+
+ if (not)
+ {
+ local = context.BitwiseNot(local);
+ }
+
+ return local;
+ }
+
+ public static void SetDest(EmitterContext context, Operand value, int rd, bool isFP64)
+ {
+ if (isFP64)
+ {
+ context.Copy(GetDest(rd), context.UnpackDouble2x32Low(value));
+ context.Copy(GetDest2(rd), context.UnpackDouble2x32High(value));
+ }
+ else
+ {
+ context.Copy(GetDest(rd), value);
+ }
+ }
+
+ public static int Imm16ToSInt(int imm16)
+ {
+ return (short)imm16;
+ }
+
+ public static int Imm20ToFloat(int imm20)
+ {
+ return imm20 << 12;
+ }
+
+ public static int Imm20ToSInt(int imm20)
+ {
+ return (imm20 << 12) >> 12;
+ }
+
+ public static int Imm24ToSInt(int imm24)
+ {
+ return (imm24 << 8) >> 8;
+ }
+
+ public static Operand SignExtendTo32(EmitterContext context, Operand src, int srcBits)
+ {
+ return context.BitfieldExtractS32(src, Const(0), Const(srcBits));
+ }
+
+ public static Operand ZeroExtendTo32(EmitterContext context, Operand src, int srcBits)
+ {
+ int mask = (int)(uint.MaxValue >> (32 - srcBits));
+
+ return context.BitwiseAnd(src, Const(mask));
+ }
+ }
+} \ No newline at end of file