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 }