AInstEmitFlow.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using ChocolArm64.Decoder;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System.Reflection.Emit;
  5. namespace ChocolArm64.Instruction
  6. {
  7. static partial class AInstEmit
  8. {
  9. public static void B(AILEmitterCtx Context)
  10. {
  11. AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
  12. Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm));
  13. }
  14. public static void B_Cond(AILEmitterCtx Context)
  15. {
  16. AOpCodeBImmCond Op = (AOpCodeBImmCond)Context.CurrOp;
  17. Context.EmitCondBranch(Context.GetLabel(Op.Imm), Op.Cond);
  18. }
  19. public static void Bl(AILEmitterCtx Context)
  20. {
  21. AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
  22. Context.EmitLdc_I(Op.Position + 4);
  23. Context.EmitStint(AThreadState.LRIndex);
  24. Context.EmitStoreState();
  25. if (Context.TryOptEmitSubroutineCall())
  26. {
  27. //Note: the return value of the called method will be placed
  28. //at the Stack, the return value is always a Int64 with the
  29. //return address of the function. We check if the address is
  30. //correct, if it isn't we keep returning until we reach the dispatcher.
  31. Context.Emit(OpCodes.Dup);
  32. Context.EmitLdc_I8(Op.Position + 4);
  33. AILLabel LblContinue = new AILLabel();
  34. Context.Emit(OpCodes.Beq_S, LblContinue);
  35. Context.Emit(OpCodes.Ret);
  36. Context.MarkLabel(LblContinue);
  37. Context.Emit(OpCodes.Pop);
  38. if (Context.CurrBlock.Next != null)
  39. {
  40. Context.EmitLoadState(Context.CurrBlock.Next);
  41. }
  42. }
  43. else
  44. {
  45. Context.EmitLdc_I8(Op.Imm);
  46. Context.Emit(OpCodes.Ret);
  47. }
  48. }
  49. public static void Blr(AILEmitterCtx Context)
  50. {
  51. AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
  52. Context.EmitLdc_I(Op.Position + 4);
  53. Context.EmitStint(AThreadState.LRIndex);
  54. Context.EmitStoreState();
  55. Context.EmitLdintzr(Op.Rn);
  56. Context.Emit(OpCodes.Ret);
  57. }
  58. public static void Br(AILEmitterCtx Context)
  59. {
  60. AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
  61. Context.EmitStoreState();
  62. Context.EmitLdintzr(Op.Rn);
  63. Context.Emit(OpCodes.Ret);
  64. }
  65. public static void Cbnz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Bne_Un);
  66. public static void Cbz(AILEmitterCtx Context) => EmitCb(Context, OpCodes.Beq);
  67. private static void EmitCb(AILEmitterCtx Context, OpCode ILOp)
  68. {
  69. AOpCodeBImmCmp Op = (AOpCodeBImmCmp)Context.CurrOp;
  70. Context.EmitLdintzr(Op.Rt);
  71. Context.EmitLdc_I(0);
  72. Context.Emit(ILOp, Context.GetLabel(Op.Imm));
  73. }
  74. public static void Ret(AILEmitterCtx Context)
  75. {
  76. Context.EmitStoreState();
  77. Context.EmitLdint(AThreadState.LRIndex);
  78. Context.Emit(OpCodes.Ret);
  79. }
  80. public static void Tbnz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Bne_Un);
  81. public static void Tbz(AILEmitterCtx Context) => EmitTb(Context, OpCodes.Beq);
  82. private static void EmitTb(AILEmitterCtx Context, OpCode ILOp)
  83. {
  84. AOpCodeBImmTest Op = (AOpCodeBImmTest)Context.CurrOp;
  85. Context.EmitLdintzr(Op.Rt);
  86. Context.EmitLdc_I(1L << Op.Pos);
  87. Context.Emit(OpCodes.And);
  88. Context.EmitLdc_I(0);
  89. Context.Emit(ILOp, Context.GetLabel(Op.Imm));
  90. }
  91. }
  92. }