aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Instructions
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs44
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs20
2 files changed, 64 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
index 1d3a1101..2a8f00cc 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitAlu.cs
@@ -200,6 +200,50 @@ namespace Ryujinx.Graphics.Shader.Instructions
// TODO: CC, X, corner cases
}
+ public static void Imad(EmitterContext context)
+ {
+ OpCodeAlu op = (OpCodeAlu)context.CurrOp;
+
+ bool signedA = context.CurrOp.RawOpCode.Extract(48);
+ bool signedB = context.CurrOp.RawOpCode.Extract(53);
+ bool high = context.CurrOp.RawOpCode.Extract(54);
+
+ Operand srcA = GetSrcA(context);
+ Operand srcB = GetSrcB(context);
+ Operand srcC = GetSrcC(context);
+
+ Operand res;
+
+ if (high)
+ {
+ if (signedA && signedB)
+ {
+ res = context.MultiplyHighS32(srcA, srcB);
+ }
+ else
+ {
+ res = context.MultiplyHighU32(srcA, srcB);
+
+ if (signedA)
+ {
+ res = context.IAdd(res, context.IMultiply(srcB, context.ShiftRightS32(srcA, Const(31))));
+ }
+ else if (signedB)
+ {
+ res = context.IAdd(res, context.IMultiply(srcA, context.ShiftRightS32(srcB, Const(31))));
+ }
+ }
+ }
+ else
+ {
+ res = context.IMultiply(srcA, srcB);
+ }
+
+ res = context.IAdd(res, srcC);
+
+ context.Copy(GetDest(context), res);
+ }
+
public static void Imnmx(EmitterContext context)
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
index 3b8d7305..63d1efcb 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
@@ -59,6 +59,26 @@ namespace Ryujinx.Graphics.Shader.Instructions
SetFPZnFlags(context, dest, op.SetCondCode);
}
+ public static void Ffma32i(EmitterContext context)
+ {
+ IOpCodeFArith op = (IOpCodeFArith)context.CurrOp;
+
+ bool saturate = op.RawOpCode.Extract(55);
+ bool negateA = op.RawOpCode.Extract(56);
+ bool negateC = op.RawOpCode.Extract(57);
+
+ Operand srcA = context.FPNegate(GetSrcA(context), negateA);
+ Operand srcC = context.FPNegate(GetDest(context), negateC);
+
+ Operand srcB = GetSrcB(context);
+
+ Operand dest = GetDest(context);
+
+ context.Copy(dest, context.FPSaturate(context.FPFusedMultiplyAdd(srcA, srcB, srcC), saturate));
+
+ SetFPZnFlags(context, dest, op.SetCondCode);
+ }
+
public static void Fmnmx(EmitterContext context)
{
IOpCodeFArith op = (IOpCodeFArith)context.CurrOp;