aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Instructions
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-11-14 14:20:30 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commitf0a59f345c633b757ebd2a22fca23d7dab0f9f99 (patch)
tree444aa5ac024119594bc9f5b51e3710483537e6e6 /Ryujinx.Graphics.Shader/Instructions
parentd274328c3192fd85b9eec661b00f1599d673776c (diff)
Add partial support for the BRX shader instruction
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs16
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs60
2 files changed, 53 insertions, 23 deletions
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
index 4f7072eb..79d92c2d 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs
@@ -97,14 +97,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
switch (op.Scale)
{
- case FmulScale.None: break;
-
- case FmulScale.Divide2: srcA = context.FPDivide (srcA, ConstF(2)); break;
- case FmulScale.Divide4: srcA = context.FPDivide (srcA, ConstF(4)); break;
- case FmulScale.Divide8: srcA = context.FPDivide (srcA, ConstF(8)); break;
- case FmulScale.Multiply2: srcA = context.FPMultiply(srcA, ConstF(2)); break;
- case FmulScale.Multiply4: srcA = context.FPMultiply(srcA, ConstF(4)); break;
- case FmulScale.Multiply8: srcA = context.FPMultiply(srcA, ConstF(8)); break;
+ case FPMultiplyScale.None: break;
+
+ case FPMultiplyScale.Divide2: srcA = context.FPDivide (srcA, ConstF(2)); break;
+ case FPMultiplyScale.Divide4: srcA = context.FPDivide (srcA, ConstF(4)); break;
+ case FPMultiplyScale.Divide8: srcA = context.FPDivide (srcA, ConstF(8)); break;
+ case FPMultiplyScale.Multiply2: srcA = context.FPMultiply(srcA, ConstF(2)); break;
+ case FPMultiplyScale.Multiply4: srcA = context.FPMultiply(srcA, ConstF(4)); break;
+ case FPMultiplyScale.Multiply8: srcA = context.FPMultiply(srcA, ConstF(8)); break;
default: break; //TODO: Warning.
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
index e17c9d6c..4a9f5f7f 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs
@@ -20,6 +20,36 @@ namespace Ryujinx.Graphics.Shader.Instructions
EmitBrkOrSync(context);
}
+ public static void Brx(EmitterContext context)
+ {
+ OpCodeBranchIndir op = (OpCodeBranchIndir)context.CurrOp;
+
+ int offset = (int)op.Address + 8 + op.Offset;
+
+ Operand address = context.IAdd(Register(op.Ra), Const(offset));
+
+ // Sorting the target addresses in descending order improves the code,
+ // since it will always check the most distant targets first, then the
+ // near ones. This can be easily transformed into if/else statements.
+ IOrderedEnumerable<Block> sortedTargets = op.PossibleTargets.OrderByDescending(x => x.Address);
+
+ Block lastTarget = sortedTargets.LastOrDefault();
+
+ foreach (Block possibleTarget in sortedTargets)
+ {
+ Operand label = context.GetLabel(possibleTarget.Address);
+
+ if (possibleTarget != lastTarget)
+ {
+ context.BranchIfTrue(label, context.ICompareEqual(address, Const((int)possibleTarget.Address)));
+ }
+ else
+ {
+ context.Branch(label);
+ }
+ }
+ }
+
public static void Exit(EmitterContext context)
{
OpCodeExit op = (OpCodeExit)context.CurrOp;
@@ -54,45 +84,45 @@ namespace Ryujinx.Graphics.Shader.Instructions
private static void EmitPbkOrSsy(EmitterContext context)
{
- OpCodeSsy op = (OpCodeSsy)context.CurrOp;
+ OpCodePush op = (OpCodePush)context.CurrOp;
- foreach (KeyValuePair<OpCodeSync, Operand> kv in op.Syncs)
+ foreach (KeyValuePair<OpCodeBranchPop, Operand> kv in op.PopOps)
{
- OpCodeSync opSync = kv.Key;
+ OpCodeBranchPop opSync = kv.Key;
Operand local = kv.Value;
- int ssyIndex = opSync.Targets[op];
+ int pushOpIndex = opSync.Targets[op];
- context.Copy(local, Const(ssyIndex));
+ context.Copy(local, Const(pushOpIndex));
}
}
private static void EmitBrkOrSync(EmitterContext context)
{
- OpCodeSync op = (OpCodeSync)context.CurrOp;
+ OpCodeBranchPop op = (OpCodeBranchPop)context.CurrOp;
if (op.Targets.Count == 1)
{
- // If we have only one target, then the SSY is basically
+ // If we have only one target, then the SSY/PBK is basically
// a branch, we can produce better codegen for this case.
- OpCodeSsy opSsy = op.Targets.Keys.First();
+ OpCodePush pushOp = op.Targets.Keys.First();
- EmitBranch(context, opSsy.GetAbsoluteAddress());
+ EmitBranch(context, pushOp.GetAbsoluteAddress());
}
else
{
- foreach (KeyValuePair<OpCodeSsy, int> kv in op.Targets)
+ foreach (KeyValuePair<OpCodePush, int> kv in op.Targets)
{
- OpCodeSsy opSsy = kv.Key;
+ OpCodePush pushOp = kv.Key;
- Operand label = context.GetLabel(opSsy.GetAbsoluteAddress());
+ Operand label = context.GetLabel(pushOp.GetAbsoluteAddress());
- Operand local = opSsy.Syncs[op];
+ Operand local = pushOp.PopOps[op];
- int ssyIndex = kv.Value;
+ int pushOpIndex = kv.Value;
- context.BranchIfTrue(label, context.ICompareEqual(local, Const(ssyIndex)));
+ context.BranchIfTrue(label, context.ICompareEqual(local, Const(pushOpIndex)));
}
}
}