InstEmitFlow.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.IntermediateRepresentation;
  3. using ChocolArm64.State;
  4. using ChocolArm64.Translation;
  5. using System.Reflection.Emit;
  6. using static ChocolArm64.Instructions.InstEmitFlowHelper;
  7. namespace ChocolArm64.Instructions
  8. {
  9. static partial class InstEmit
  10. {
  11. public static void B(ILEmitterCtx context)
  12. {
  13. OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp;
  14. if (context.CurrBlock.Branch != null)
  15. {
  16. context.Emit(OpCodes.Br, context.GetLabel(op.Imm));
  17. }
  18. else
  19. {
  20. context.EmitStoreContext();
  21. context.EmitLdc_I8(op.Imm);
  22. context.Emit(OpCodes.Ret);
  23. }
  24. }
  25. public static void B_Cond(ILEmitterCtx context)
  26. {
  27. OpCodeBImmCond64 op = (OpCodeBImmCond64)context.CurrOp;
  28. EmitBranch(context, op.Cond);
  29. }
  30. public static void Bl(ILEmitterCtx context)
  31. {
  32. OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp;
  33. context.EmitLdc_I(op.Position + 4);
  34. context.EmitStint(RegisterAlias.Lr);
  35. EmitCall(context, op.Imm);
  36. }
  37. public static void Blr(ILEmitterCtx context)
  38. {
  39. OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;
  40. context.EmitLdintzr(op.Rn);
  41. context.EmitLdc_I(op.Position + 4);
  42. context.EmitStint(RegisterAlias.Lr);
  43. context.EmitStoreContext();
  44. EmitVirtualCall(context);
  45. }
  46. public static void Br(ILEmitterCtx context)
  47. {
  48. OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;
  49. context.HasIndirectJump = true;
  50. context.EmitStoreContext();
  51. context.EmitLdintzr(op.Rn);
  52. EmitVirtualJump(context);
  53. }
  54. public static void Cbnz(ILEmitterCtx context) => EmitCb(context, OpCodes.Bne_Un);
  55. public static void Cbz(ILEmitterCtx context) => EmitCb(context, OpCodes.Beq);
  56. private static void EmitCb(ILEmitterCtx context, OpCode ilOp)
  57. {
  58. OpCodeBImmCmp64 op = (OpCodeBImmCmp64)context.CurrOp;
  59. context.EmitLdintzr(op.Rt);
  60. context.EmitLdc_I(0);
  61. EmitBranch(context, ilOp);
  62. }
  63. public static void Ret(ILEmitterCtx context)
  64. {
  65. context.EmitStoreContext();
  66. context.EmitLdint(RegisterAlias.Lr);
  67. context.Emit(OpCodes.Ret);
  68. }
  69. public static void Tbnz(ILEmitterCtx context) => EmitTb(context, OpCodes.Bne_Un);
  70. public static void Tbz(ILEmitterCtx context) => EmitTb(context, OpCodes.Beq);
  71. private static void EmitTb(ILEmitterCtx context, OpCode ilOp)
  72. {
  73. OpCodeBImmTest64 op = (OpCodeBImmTest64)context.CurrOp;
  74. context.EmitLdintzr(op.Rt);
  75. context.EmitLdc_I(1L << op.Pos);
  76. context.Emit(OpCodes.And);
  77. context.EmitLdc_I(0);
  78. EmitBranch(context, ilOp);
  79. }
  80. private static void EmitBranch(ILEmitterCtx context, Condition cond)
  81. {
  82. OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp;
  83. if (context.CurrBlock.Branch != null)
  84. {
  85. context.EmitCondBranch(context.GetLabel(op.Imm), cond);
  86. if (context.CurrBlock.Next == null)
  87. {
  88. context.EmitStoreContext();
  89. context.EmitLdc_I8(op.Position + 4);
  90. context.Emit(OpCodes.Ret);
  91. }
  92. }
  93. else
  94. {
  95. context.EmitStoreContext();
  96. ILLabel lblTaken = new ILLabel();
  97. context.EmitCondBranch(lblTaken, cond);
  98. context.EmitLdc_I8(op.Position + 4);
  99. context.Emit(OpCodes.Ret);
  100. context.MarkLabel(lblTaken);
  101. context.EmitLdc_I8(op.Imm);
  102. context.Emit(OpCodes.Ret);
  103. }
  104. }
  105. private static void EmitBranch(ILEmitterCtx context, OpCode ilOp)
  106. {
  107. OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp;
  108. if (context.CurrBlock.Branch != null)
  109. {
  110. context.Emit(ilOp, context.GetLabel(op.Imm));
  111. if (context.CurrBlock.Next == null)
  112. {
  113. context.EmitStoreContext();
  114. context.EmitLdc_I8(op.Position + 4);
  115. context.Emit(OpCodes.Ret);
  116. }
  117. }
  118. else
  119. {
  120. context.EmitStoreContext();
  121. ILLabel lblTaken = new ILLabel();
  122. context.Emit(ilOp, lblTaken);
  123. context.EmitLdc_I8(op.Position + 4);
  124. context.Emit(OpCodes.Ret);
  125. context.MarkLabel(lblTaken);
  126. context.EmitLdc_I8(op.Imm);
  127. context.Emit(OpCodes.Ret);
  128. }
  129. }
  130. }
  131. }