InstEmitFlow32.cs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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.OperandHelper;
  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. if (context.CurrBlock.Branch != null)
  16. {
  17. context.Branch(context.GetLabel((ulong)op.Immediate));
  18. }
  19. else
  20. {
  21. context.StoreToContext();
  22. context.Return(Const(op.Immediate));
  23. }
  24. }
  25. public static void Bl(ArmEmitterContext context)
  26. {
  27. Blx(context, x: false);
  28. }
  29. public static void Blx(ArmEmitterContext context)
  30. {
  31. Blx(context, x: true);
  32. }
  33. private static void Blx(ArmEmitterContext context, bool x)
  34. {
  35. IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
  36. uint pc = op.GetPc();
  37. bool isThumb = IsThumb(context.CurrOp);
  38. uint currentPc = isThumb
  39. ? pc | 1
  40. : pc - 4;
  41. SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
  42. // If x is true, then this is a branch with link and exchange.
  43. // In this case we need to swap the mode between Arm <-> Thumb.
  44. if (x)
  45. {
  46. SetFlag(context, PState.TFlag, Const(isThumb ? 0 : 1));
  47. }
  48. InstEmitFlowHelper.EmitCall(context, (ulong)op.Immediate);
  49. }
  50. public static void Blxr(ArmEmitterContext context)
  51. {
  52. IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
  53. uint pc = op.GetPc();
  54. Operand addr = GetIntA32(context, op.Rm);
  55. Operand bitOne = context.BitwiseAnd(addr, Const(1));
  56. addr = context.BitwiseOr(addr, Const((int)CallFlag)); // Set call flag.
  57. bool isThumb = IsThumb(context.CurrOp);
  58. uint currentPc = isThumb
  59. ? pc | 1
  60. : pc - 4;
  61. SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
  62. SetFlag(context, PState.TFlag, bitOne);
  63. context.Return(addr); // Call.
  64. }
  65. public static void Bx(ArmEmitterContext context)
  66. {
  67. IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
  68. context.StoreToContext();
  69. EmitBxWritePc(context, GetIntA32(context, op.Rm));
  70. }
  71. }
  72. }