public static void EmitCall(ILEmitterCtx context, long imm) { if (context.TryOptEmitSubroutineCall()) { //Note: the return value of the called method will be placed //at the Stack, the return value is always a Int64 with the //return address of the function. We check if the address is //correct, if it isn't we keep returning until we reach the dispatcher. context.Emit(OpCodes.Dup); context.EmitLdc_I8(context.CurrOp.Position + 4); ILLabel lblContinue = new ILLabel(); context.Emit(OpCodes.Beq_S, lblContinue); context.Emit(OpCodes.Ret); context.MarkLabel(lblContinue); context.Emit(OpCodes.Pop); context.EmitLoadState(); } else { context.EmitLdc_I8(imm); context.Emit(OpCodes.Ret); } }
public static void EmitCall(ILEmitterCtx context, long imm) { if (context.Tier == TranslationTier.Tier0) { context.EmitStoreContext(); context.TranslateAhead(imm); context.EmitLdc_I8(imm); context.Emit(OpCodes.Ret); return; } if (!context.TryOptEmitSubroutineCall()) { context.HasSlowCall = true; context.EmitStoreContext(); context.TranslateAhead(imm); context.EmitLdarg(TranslatedSub.StateArgIdx); context.EmitLdfld(typeof(CpuThreadState).GetField(nameof(CpuThreadState.CurrentTranslator), BindingFlags.Instance | BindingFlags.NonPublic)); context.EmitLdarg(TranslatedSub.StateArgIdx); context.EmitLdc_I8(imm); context.EmitLdc_I4((int)CallType.Call); context.EmitPrivateCall(typeof(Translator), nameof(Translator.GetOrTranslateSubroutine)); context.EmitLdarg(TranslatedSub.StateArgIdx); context.EmitLdarg(TranslatedSub.MemoryArgIdx); context.EmitCall(typeof(TranslatedSub), nameof(TranslatedSub.Execute)); } EmitContinueOrReturnCheck(context); }
public static void Bl(ILEmitterCtx context) { OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp; context.EmitLdc_I(op.Position + 4); context.EmitStint(CpuThreadState.LrIndex); context.EmitStoreState(); if (context.TryOptEmitSubroutineCall()) { //Note: the return value of the called method will be placed //at the Stack, the return value is always a Int64 with the //return address of the function. We check if the address is //correct, if it isn't we keep returning until we reach the dispatcher. context.Emit(OpCodes.Dup); context.EmitLdc_I8(op.Position + 4); ILLabel lblContinue = new ILLabel(); context.Emit(OpCodes.Beq_S, lblContinue); context.Emit(OpCodes.Ret); context.MarkLabel(lblContinue); context.Emit(OpCodes.Pop); context.EmitLoadState(context.CurrBlock.Next); } else { context.EmitLdc_I8(op.Imm); context.Emit(OpCodes.Ret); } }