InstEmitFlow.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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 InstEmit
  11. {
  12. public static void B(ArmEmitterContext context)
  13. {
  14. OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
  15. context.Branch(context.GetLabel((ulong)op.Immediate));
  16. }
  17. public static void B_Cond(ArmEmitterContext context)
  18. {
  19. OpCodeBImmCond op = (OpCodeBImmCond)context.CurrOp;
  20. EmitBranch(context, op.Cond);
  21. }
  22. public static void Bl(ArmEmitterContext context)
  23. {
  24. OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
  25. context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
  26. EmitCall(context, (ulong)op.Immediate);
  27. }
  28. public static void Blr(ArmEmitterContext context)
  29. {
  30. OpCodeBReg op = (OpCodeBReg)context.CurrOp;
  31. Operand n = context.Copy(GetIntOrZR(context, op.Rn));
  32. context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
  33. EmitVirtualCall(context, n);
  34. }
  35. public static void Br(ArmEmitterContext context)
  36. {
  37. OpCodeBReg op = (OpCodeBReg)context.CurrOp;
  38. EmitVirtualJump(context, GetIntOrZR(context, op.Rn), op.Rn == RegisterAlias.Lr);
  39. }
  40. public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
  41. public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
  42. private static void EmitCb(ArmEmitterContext context, bool onNotZero)
  43. {
  44. OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp;
  45. EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero);
  46. }
  47. public static void Ret(ArmEmitterContext context)
  48. {
  49. OpCodeBReg op = (OpCodeBReg)context.CurrOp;
  50. context.Return(GetIntOrZR(context, op.Rn));
  51. }
  52. public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
  53. public static void Tbz(ArmEmitterContext context) => EmitTb(context, onNotZero: false);
  54. private static void EmitTb(ArmEmitterContext context, bool onNotZero)
  55. {
  56. OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp;
  57. Operand value = context.BitwiseAnd(GetIntOrZR(context, op.Rt), Const(1L << op.Bit));
  58. EmitBranch(context, value, onNotZero);
  59. }
  60. private static void EmitBranch(ArmEmitterContext context, Condition cond)
  61. {
  62. OpCodeBImm op = (OpCodeBImm)context.CurrOp;
  63. EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond);
  64. }
  65. private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero)
  66. {
  67. OpCodeBImm op = (OpCodeBImm)context.CurrOp;
  68. Operand lblTarget = context.GetLabel((ulong)op.Immediate);
  69. if (onNotZero)
  70. {
  71. context.BranchIfTrue(lblTarget, value);
  72. }
  73. else
  74. {
  75. context.BranchIfFalse(lblTarget, value);
  76. }
  77. }
  78. }
  79. }