/ src / ARMeilleure / Instructions / InstEmitFlow.cs
InstEmitFlow.cs
  1  using ARMeilleure.Decoders;
  2  using ARMeilleure.IntermediateRepresentation;
  3  using ARMeilleure.State;
  4  using ARMeilleure.Translation;
  5  
  6  using static ARMeilleure.Instructions.InstEmitFlowHelper;
  7  using static ARMeilleure.Instructions.InstEmitHelper;
  8  using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  9  
 10  namespace ARMeilleure.Instructions
 11  {
 12      static partial class InstEmit
 13      {
 14          public static void B(ArmEmitterContext context)
 15          {
 16              OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
 17  
 18              context.Branch(context.GetLabel((ulong)op.Immediate));
 19          }
 20  
 21          public static void B_Cond(ArmEmitterContext context)
 22          {
 23              OpCodeBImmCond op = (OpCodeBImmCond)context.CurrOp;
 24  
 25              EmitBranch(context, op.Cond);
 26          }
 27  
 28          public static void Bl(ArmEmitterContext context)
 29          {
 30              OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
 31  
 32              context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
 33  
 34              EmitCall(context, (ulong)op.Immediate);
 35          }
 36  
 37          public static void Blr(ArmEmitterContext context)
 38          {
 39              OpCodeBReg op = (OpCodeBReg)context.CurrOp;
 40  
 41              Operand n = context.Copy(GetIntOrZR(context, op.Rn));
 42  
 43              context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
 44  
 45              EmitVirtualCall(context, n);
 46          }
 47  
 48          public static void Br(ArmEmitterContext context)
 49          {
 50              OpCodeBReg op = (OpCodeBReg)context.CurrOp;
 51  
 52              EmitVirtualJump(context, GetIntOrZR(context, op.Rn), op.Rn == RegisterAlias.Lr);
 53          }
 54  
 55          public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true);
 56          public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false);
 57  
 58          private static void EmitCb(ArmEmitterContext context, bool onNotZero)
 59          {
 60              OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp;
 61  
 62              EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero);
 63          }
 64  
 65          public static void Ret(ArmEmitterContext context)
 66          {
 67              OpCodeBReg op = (OpCodeBReg)context.CurrOp;
 68  
 69              context.Return(GetIntOrZR(context, op.Rn));
 70          }
 71  
 72          public static void Tbnz(ArmEmitterContext context) => EmitTb(context, onNotZero: true);
 73          public static void Tbz(ArmEmitterContext context) => EmitTb(context, onNotZero: false);
 74  
 75          private static void EmitTb(ArmEmitterContext context, bool onNotZero)
 76          {
 77              OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp;
 78  
 79              Operand value = context.BitwiseAnd(GetIntOrZR(context, op.Rt), Const(1L << op.Bit));
 80  
 81              EmitBranch(context, value, onNotZero);
 82          }
 83  
 84          private static void EmitBranch(ArmEmitterContext context, Condition cond)
 85          {
 86              OpCodeBImm op = (OpCodeBImm)context.CurrOp;
 87  
 88              EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond);
 89          }
 90  
 91          private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero)
 92          {
 93              OpCodeBImm op = (OpCodeBImm)context.CurrOp;
 94  
 95              Operand lblTarget = context.GetLabel((ulong)op.Immediate);
 96  
 97              if (onNotZero)
 98              {
 99                  context.BranchIfTrue(lblTarget, value);
100              }
101              else
102              {
103                  context.BranchIfFalse(lblTarget, value);
104              }
105          }
106      }
107  }