diff options
| author | gdk <gab.dark.100@gmail.com> | 2019-11-14 14:20:30 -0300 |
|---|---|---|
| committer | Thog <thog@protonmail.com> | 2020-01-09 02:13:00 +0100 |
| commit | f0a59f345c633b757ebd2a22fca23d7dab0f9f99 (patch) | |
| tree | 444aa5ac024119594bc9f5b51e3710483537e6e6 /Ryujinx.Graphics.Shader/Instructions | |
| parent | d274328c3192fd85b9eec661b00f1599d673776c (diff) | |
Add partial support for the BRX shader instruction
Diffstat (limited to 'Ryujinx.Graphics.Shader/Instructions')
| -rw-r--r-- | Ryujinx.Graphics.Shader/Instructions/InstEmitFArith.cs | 16 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Shader/Instructions/InstEmitFlow.cs | 60 |
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))); } } } |
