InstEmitFlow32.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.State;
  4. using ARMeilleure.Translation;
  5. using static ARMeilleure.Instructions.InstEmitFlowHelper;
  6. using static ARMeilleure.Instructions.InstEmitHelper;
  7. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  8. namespace ARMeilleure.Instructions
  9. {
  10. static partial class InstEmit32
  11. {
  12. public static void B(ArmEmitterContext context)
  13. {
  14. IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
  15. context.Branch(context.GetLabel((ulong)op.Immediate));
  16. }
  17. public static void Bl(ArmEmitterContext context)
  18. {
  19. Blx(context, x: false);
  20. }
  21. public static void Blx(ArmEmitterContext context)
  22. {
  23. Blx(context, x: true);
  24. }
  25. private static void Blx(ArmEmitterContext context, bool x)
  26. {
  27. IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
  28. uint pc = op.GetPc();
  29. bool isThumb = ((OpCode32)context.CurrOp).IsThumb();
  30. uint currentPc = isThumb
  31. ? pc | 1
  32. : pc - 4;
  33. SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
  34. // If x is true, then this is a branch with link and exchange.
  35. // In this case we need to swap the mode between Arm <-> Thumb.
  36. if (x)
  37. {
  38. SetFlag(context, PState.TFlag, Const(isThumb ? 0 : 1));
  39. }
  40. EmitCall(context, (ulong)op.Immediate);
  41. }
  42. public static void Blxr(ArmEmitterContext context)
  43. {
  44. IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
  45. uint pc = op.GetPc();
  46. Operand addr = context.Copy(GetIntA32(context, op.Rm));
  47. Operand bitOne = context.BitwiseAnd(addr, Const(1));
  48. bool isThumb = ((OpCode32)context.CurrOp).IsThumb();
  49. uint currentPc = isThumb
  50. ? (pc - 2) | 1
  51. : pc - 4;
  52. SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
  53. SetFlag(context, PState.TFlag, bitOne);
  54. EmitBxWritePc(context, addr);
  55. }
  56. public static void Bx(ArmEmitterContext context)
  57. {
  58. IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
  59. EmitBxWritePc(context, GetIntA32(context, op.Rm), op.Rm);
  60. }
  61. public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
  62. public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
  63. private static void EmitCb(ArmEmitterContext context, bool onNotZero)
  64. {
  65. OpCodeT16BImmCmp op = (OpCodeT16BImmCmp)context.CurrOp;
  66. Operand value = GetIntOrZR(context, op.Rn);
  67. Operand lblTarget = context.GetLabel((ulong)op.Immediate);
  68. if (onNotZero)
  69. {
  70. context.BranchIfTrue(lblTarget, value);
  71. }
  72. else
  73. {
  74. context.BranchIfFalse(lblTarget, value);
  75. }
  76. }
  77. public static void It(ArmEmitterContext context)
  78. {
  79. OpCodeT16IfThen op = (OpCodeT16IfThen)context.CurrOp;
  80. context.SetIfThenBlockState(op.IfThenBlockConds);
  81. }
  82. }
  83. }