private static void EmitBranch(ArmEmitterContext context, Condition cond) { OpCodeBImm op = (OpCodeBImm)context.CurrOp; if (context.CurrBlock.Branch != null) { EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond); if (context.CurrBlock.Next == null) { EmitTailContinue(context, Const(op.Address + 4)); } } else { Operand lblTaken = Label(); EmitCondBranch(context, lblTaken, cond); EmitTailContinue(context, Const(op.Address + 4)); context.MarkLabel(lblTaken); EmitTailContinue(context, Const(op.Immediate)); } }
private static void EmitNativeCall(ArmEmitterContext context, Operand nativeContextPtr, Operand funcAddr, bool isJump = false) { context.StoreToContext(); if (isJump) { context.Tailcall(funcAddr, nativeContextPtr); } else { OpCode op = context.CurrOp; Operand returnAddress = context.Call(funcAddr, OperandType.I64, nativeContextPtr); context.LoadFromContext(); // Note: The return value of a translated function is always an Int64 with the address execution has // returned to. We expect this address to be immediately after the current instruction, if it isn't we // keep returning until we reach the dispatcher. Operand nextAddr = Const((long)op.Address + op.OpCodeSizeInBytes); // Try to continue within this block. // If the return address isn't to our next instruction, we need to return so the JIT can figure out // what to do. Operand lblContinue = context.GetLabel(nextAddr.Value); // We need to clear out the call flag for the return address before comparing it. context.BranchIf(lblContinue, context.BitwiseAnd(returnAddress, Const(~CallFlag)), nextAddr, Comparison.Equal); context.Return(returnAddress); } }
public static void B(ArmEmitterContext context) { OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; if (context.CurrBlock.Branch != null) { context.Branch(context.GetLabel((ulong)op.Immediate)); } else { context.Return(Const(op.Immediate)); } }
public static void EmitCall(ArmEmitterContext context, ulong immediate) { bool isRecursive = immediate == context.EntryAddress; if (isRecursive) { context.Branch(context.GetLabel(immediate)); } else { EmitTableBranch(context, Const(immediate), isJump: false); } }
public static void B(ArmEmitterContext context) { OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; if (context.CurrBlock.Branch != null) { context.Branch(context.GetLabel((ulong)op.Immediate)); } else { EmitTailContinue(context, Const(op.Immediate), context.CurrBlock.TailCall); } }
public static void B(ArmEmitterContext context) { IOpCode32BImm op = (IOpCode32BImm)context.CurrOp; if (context.CurrBlock.Branch != null) { context.Branch(context.GetLabel((ulong)op.Immediate)); } else { context.StoreToContext(); context.Return(Const(op.Immediate)); } }
private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero) { OpCodeBImm op = (OpCodeBImm)context.CurrOp; Operand lblTarget = context.GetLabel((ulong)op.Immediate); if (onNotZero) { context.BranchIfTrue(lblTarget, value); } else { context.BranchIfFalse(lblTarget, value); } }
private static void EmitCb(ArmEmitterContext context, bool onNotZero) { OpCodeT16BImmCmp op = (OpCodeT16BImmCmp)context.CurrOp; Operand value = GetIntA32(context, op.Rn); Operand lblTarget = context.GetLabel((ulong)op.Immediate); if (onNotZero) { context.BranchIfTrue(lblTarget, value); } else { context.BranchIfFalse(lblTarget, value); } }
public static void EmitCall(ArmEmitterContext context, ulong immediate) { bool isRecursive = immediate == context.EntryAddress; if (isRecursive) { context.Branch(context.GetLabel(immediate)); } else { Operand address = !context.HasTtc ? Const(immediate) : Const(immediate, new Symbol(SymbolType.DynFunc, context.GetOffset(immediate))); EmitTableBranch(context, address, isJump: false); } }
private static void EmitBranch(ArmEmitterContext context, Operand value, bool onNotZero) { OpCodeBImm op = (OpCodeBImm)context.CurrOp; if (context.CurrBlock.Branch != null) { Operand lblTarget = context.GetLabel((ulong)op.Immediate); if (onNotZero) { context.BranchIfTrue(lblTarget, value); } else { context.BranchIfFalse(lblTarget, value); } if (context.CurrBlock.Next == null) { context.Return(Const(op.Address + 4)); } } else { Operand lblTaken = Label(); if (onNotZero) { context.BranchIfTrue(lblTaken, value); } else { context.BranchIfFalse(lblTaken, value); } context.Return(Const(op.Address + 4)); context.MarkLabel(lblTaken); context.Return(Const(op.Immediate)); } }
private static void EmitBranch(ArmEmitterContext context, Condition cond) { OpCodeBImm op = (OpCodeBImm)context.CurrOp; EmitCondBranch(context, context.GetLabel((ulong)op.Immediate), cond); }
public static void B(ArmEmitterContext context) { OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; context.Branch(context.GetLabel((ulong)op.Immediate)); }
private static void EmitTableBranch(ArmEmitterContext context, Operand guestAddress, bool isJump) { context.StoreToContext(); if (guestAddress.Type == OperandType.I32) { guestAddress = context.ZeroExtend32(OperandType.I64, guestAddress); } // Store the target guest address into the native context. The stubs uses this address to dispatch into the // next translation. Operand nativeContext = context.LoadArgument(OperandType.I64, 0); Operand dispAddressAddr = context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())); context.Store(dispAddressAddr, guestAddress); Operand hostAddress; // If address is mapped onto the function table, we can skip the table walk. Otherwise we fallback // onto the dispatch stub. if (guestAddress.Kind == OperandKind.Constant && context.FunctionTable.IsValid(guestAddress.Value)) { Operand hostAddressAddr = !context.HasPtc ? Const(ref context.FunctionTable.GetValue(guestAddress.Value)) : Const(ref context.FunctionTable.GetValue(guestAddress.Value), new Symbol(SymbolType.FunctionTable, guestAddress.Value)); hostAddress = context.Load(OperandType.I64, hostAddressAddr); } else { hostAddress = !context.HasPtc ? Const((long)context.Stubs.DispatchStub) : Const((long)context.Stubs.DispatchStub, Ptc.DispatchStubSymbol); } if (isJump) { context.Tailcall(hostAddress, nativeContext); } else { OpCode op = context.CurrOp; Operand returnAddress = context.Call(hostAddress, OperandType.I64, nativeContext); context.LoadFromContext(); // Note: The return value of a translated function is always an Int64 with the address execution has // returned to. We expect this address to be immediately after the current instruction, if it isn't we // keep returning until we reach the dispatcher. Operand nextAddr = Const((long)op.Address + op.OpCodeSizeInBytes); // Try to continue within this block. // If the return address isn't to our next instruction, we need to return so the JIT can figure out // what to do. Operand lblContinue = context.GetLabel(nextAddr.Value); context.BranchIf(lblContinue, returnAddress, nextAddr, Comparison.Equal, BasicBlockFrequency.Cold); context.Return(returnAddress); } }
public static void B(ArmEmitterContext context) { IOpCode32BImm op = (IOpCode32BImm)context.CurrOp; context.Branch(context.GetLabel((ulong)op.Immediate)); }