InstEmitFlow32.cs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.State;
  3. using ChocolArm64.Translation;
  4. using System.Reflection.Emit;
  5. using static ChocolArm64.Instructions.InstEmit32Helper;
  6. namespace ChocolArm64.Instructions
  7. {
  8. static partial class InstEmit32
  9. {
  10. public static void B(ILEmitterCtx context)
  11. {
  12. IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
  13. if (context.CurrBlock.Branch != null)
  14. {
  15. context.Emit(OpCodes.Br, context.GetLabel(op.Imm));
  16. }
  17. else
  18. {
  19. context.EmitStoreContext();
  20. context.EmitLdc_I8(op.Imm);
  21. context.Emit(OpCodes.Ret);
  22. }
  23. }
  24. public static void Bl(ILEmitterCtx context)
  25. {
  26. Blx(context, x: false);
  27. }
  28. public static void Blx(ILEmitterCtx context)
  29. {
  30. Blx(context, x: true);
  31. }
  32. public static void Bx(ILEmitterCtx context)
  33. {
  34. IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
  35. context.EmitStoreContext();
  36. EmitLoadFromRegister(context, op.Rm);
  37. EmitBxWritePc(context);
  38. }
  39. private static void Blx(ILEmitterCtx context, bool x)
  40. {
  41. IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
  42. uint pc = op.GetPc();
  43. bool isThumb = IsThumb(context.CurrOp);
  44. if (!isThumb)
  45. {
  46. context.EmitLdc_I(op.GetPc() - 4);
  47. }
  48. else
  49. {
  50. context.EmitLdc_I(op.GetPc() | 1);
  51. }
  52. context.EmitStint(GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr));
  53. // If x is true, then this is a branch with link and exchange.
  54. // In this case we need to swap the mode between Arm <-> Thumb.
  55. if (x)
  56. {
  57. context.EmitLdc_I4(isThumb ? 0 : 1);
  58. context.EmitStflg((int)PState.TBit);
  59. }
  60. InstEmitFlowHelper.EmitCall(context, op.Imm);
  61. }
  62. }
  63. }