Block.cs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Shader.Decoders
  4. {
  5. class Block
  6. {
  7. public ulong Address { get; set; }
  8. public ulong EndAddress { get; set; }
  9. public Block Next { get; set; }
  10. public Block Branch { get; set; }
  11. public OpCodeBranchIndir BrIndir { get; set; }
  12. public List<OpCode> OpCodes { get; }
  13. public List<OpCodePush> PushOpCodes { get; }
  14. public Block(ulong address)
  15. {
  16. Address = address;
  17. OpCodes = new List<OpCode>();
  18. PushOpCodes = new List<OpCodePush>();
  19. }
  20. public void Split(Block rightBlock)
  21. {
  22. int splitIndex = BinarySearch(OpCodes, rightBlock.Address);
  23. if (OpCodes[splitIndex].Address < rightBlock.Address)
  24. {
  25. splitIndex++;
  26. }
  27. int splitCount = OpCodes.Count - splitIndex;
  28. if (splitCount <= 0)
  29. {
  30. throw new ArgumentException("Can't split at right block address.");
  31. }
  32. rightBlock.EndAddress = EndAddress;
  33. rightBlock.Next = Next;
  34. rightBlock.Branch = Branch;
  35. rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount));
  36. rightBlock.UpdatePushOps();
  37. EndAddress = rightBlock.Address;
  38. Next = rightBlock;
  39. Branch = null;
  40. OpCodes.RemoveRange(splitIndex, splitCount);
  41. UpdatePushOps();
  42. }
  43. private static int BinarySearch(List<OpCode> opCodes, ulong address)
  44. {
  45. int left = 0;
  46. int middle = 0;
  47. int right = opCodes.Count - 1;
  48. while (left <= right)
  49. {
  50. int size = right - left;
  51. middle = left + (size >> 1);
  52. OpCode opCode = opCodes[middle];
  53. if (address == opCode.Address)
  54. {
  55. break;
  56. }
  57. if (address < opCode.Address)
  58. {
  59. right = middle - 1;
  60. }
  61. else
  62. {
  63. left = middle + 1;
  64. }
  65. }
  66. return middle;
  67. }
  68. public OpCode GetLastOp()
  69. {
  70. if (OpCodes.Count != 0)
  71. {
  72. return OpCodes[OpCodes.Count - 1];
  73. }
  74. return null;
  75. }
  76. public void UpdatePushOps()
  77. {
  78. PushOpCodes.Clear();
  79. for (int index = 0; index < OpCodes.Count; index++)
  80. {
  81. if (!(OpCodes[index] is OpCodePush op))
  82. {
  83. continue;
  84. }
  85. PushOpCodes.Add(op);
  86. }
  87. }
  88. }
  89. }