InstEmitFlow.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using Ryujinx.Graphics.Shader.Translation;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  7. namespace Ryujinx.Graphics.Shader.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void Bra(EmitterContext context)
  12. {
  13. EmitBranch(context, context.CurrBlock.Branch.Address);
  14. }
  15. public static void Exit(EmitterContext context)
  16. {
  17. OpCodeExit op = (OpCodeExit)context.CurrOp;
  18. // TODO: Figure out how this is supposed to work in the
  19. // presence of other condition codes.
  20. if (op.Condition == Condition.Always)
  21. {
  22. context.Return();
  23. }
  24. }
  25. public static void Kil(EmitterContext context)
  26. {
  27. context.Discard();
  28. }
  29. public static void Ssy(EmitterContext context)
  30. {
  31. OpCodeSsy op = (OpCodeSsy)context.CurrOp;
  32. foreach (KeyValuePair<OpCodeSync, Operand> kv in op.Syncs)
  33. {
  34. OpCodeSync opSync = kv.Key;
  35. Operand local = kv.Value;
  36. int ssyIndex = opSync.Targets[op];
  37. context.Copy(local, Const(ssyIndex));
  38. }
  39. }
  40. public static void Sync(EmitterContext context)
  41. {
  42. OpCodeSync op = (OpCodeSync)context.CurrOp;
  43. if (op.Targets.Count == 1)
  44. {
  45. // If we have only one target, then the SSY is basically
  46. // a branch, we can produce better codegen for this case.
  47. OpCodeSsy opSsy = op.Targets.Keys.First();
  48. EmitBranch(context, opSsy.GetAbsoluteAddress());
  49. }
  50. else
  51. {
  52. foreach (KeyValuePair<OpCodeSsy, int> kv in op.Targets)
  53. {
  54. OpCodeSsy opSsy = kv.Key;
  55. Operand label = context.GetLabel(opSsy.GetAbsoluteAddress());
  56. Operand local = opSsy.Syncs[op];
  57. int ssyIndex = kv.Value;
  58. context.BranchIfTrue(label, context.ICompareEqual(local, Const(ssyIndex)));
  59. }
  60. }
  61. }
  62. private static void EmitBranch(EmitterContext context, ulong address)
  63. {
  64. // If we're branching to the next instruction, then the branch
  65. // is useless and we can ignore it.
  66. if (address == context.CurrOp.Address + 8)
  67. {
  68. return;
  69. }
  70. Operand label = context.GetLabel(address);
  71. Operand pred = Register(context.CurrOp.Predicate);
  72. if (context.CurrOp.Predicate.IsPT)
  73. {
  74. context.Branch(label);
  75. }
  76. else if (context.CurrOp.InvertPredicate)
  77. {
  78. context.BranchIfFalse(label, pred);
  79. }
  80. else
  81. {
  82. context.BranchIfTrue(label, pred);
  83. }
  84. }
  85. }
  86. }