Пример #1
0
        private static void EmitBranch(ILEmitterCtx context, OpCode ilOp)
        {
            OpCodeBImm64 op = (OpCodeBImm64)context.CurrOp;

            if (context.CurrBlock.Branch != null)
            {
                context.Emit(ilOp, context.GetLabel(op.Imm));

                if (context.CurrBlock.Next == null)
                {
                    context.EmitStoreState();
                    context.EmitLdc_I8(op.Position + 4);

                    context.Emit(OpCodes.Ret);
                }
            }
            else
            {
                context.EmitStoreState();

                ILLabel lblTaken = new ILLabel();

                context.Emit(ilOp, lblTaken);

                context.EmitLdc_I8(op.Position + 4);

                context.Emit(OpCodes.Ret);

                context.MarkLabel(lblTaken);

                context.EmitLdc_I8(op.Imm);

                context.Emit(OpCodes.Ret);
            }
        }
Пример #2
0
        public static void Ret(ILEmitterCtx context)
        {
            context.EmitStoreState();
            context.EmitLdint(RegisterAlias.Lr);

            context.Emit(OpCodes.Ret);
        }
Пример #3
0
        private static void Blx(ILEmitterCtx context, bool x)
        {
            IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;

            uint pc = op.GetPc();

            bool isThumb = IsThumb(context.CurrOp);

            if (!isThumb)
            {
                context.EmitLdc_I(op.GetPc() - 4);
            }
            else
            {
                context.EmitLdc_I(op.GetPc() | 1);
            }

            context.EmitStint(GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr));
            context.EmitStoreState();

            //If x is true, then this is a branch with link and exchange.
            //In this case we need to swap the mode between Arm <-> Thumb.
            if (x)
            {
                context.EmitLdc_I4(isThumb ? 0 : 1);

                context.EmitStflg((int)PState.TBit);
            }

            InstEmitFlowHelper.EmitCall(context, op.Imm);
        }
Пример #4
0
        public static void Ret(ILEmitterCtx context)
        {
            context.EmitStoreState();
            context.EmitLdint(CpuThreadState.LrIndex);

            context.Emit(OpCodes.Ret);
        }
Пример #5
0
        public static void Br(ILEmitterCtx context)
        {
            OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;

            context.EmitStoreState();
            context.EmitLdintzr(op.Rn);

            context.Emit(OpCodes.Ret);
        }
Пример #6
0
        public static void Bl(ILEmitterCtx context)
        {
            OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp;

            context.EmitLdc_I(op.Position + 4);
            context.EmitStint(RegisterAlias.Lr);
            context.EmitStoreState();

            InstEmitFlowHelper.EmitCall(context, op.Imm);
        }
Пример #7
0
        public static void EmitCall(ILEmitterCtx context, long imm)
        {
            if (context.Tier == TranslationTier.Tier0)
            {
                context.EmitStoreState();

                context.TranslateAhead(imm);

                context.EmitLdc_I8(imm);

                context.Emit(OpCodes.Ret);

                return;
            }

            if (!context.TryOptEmitSubroutineCall())
            {
                context.HasSlowCall = true;

                context.EmitStoreState();

                context.TranslateAhead(imm);

                context.EmitLdarg(TranslatedSub.StateArgIdx);

                context.EmitFieldLoad(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);
        }
Пример #8
0
        public static void Bx(ILEmitterCtx context)
        {
            IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;

            context.EmitStoreState();

            EmitLoadFromRegister(context, op.Rm);

            EmitBxWritePc(context);
        }
Пример #9
0
        public static void Blr(ILEmitterCtx context)
        {
            OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;

            context.EmitLdintzr(op.Rn);
            context.EmitLdc_I(op.Position + 4);
            context.EmitStint(RegisterAlias.Lr);
            context.EmitStoreState();

            context.Emit(OpCodes.Ret);
        }
Пример #10
0
        public static void Br(ILEmitterCtx context)
        {
            OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;

            context.HasIndirectJump = true;

            context.EmitStoreState();
            context.EmitLdintzr(op.Rn);

            EmitVirtualJump(context);
        }
Пример #11
0
        public static void Blr(ILEmitterCtx context)
        {
            OpCodeBReg64 op = (OpCodeBReg64)context.CurrOp;

            context.EmitLdintzr(op.Rn);
            context.EmitLdc_I(op.Position + 4);
            context.EmitStint(CpuThreadState.LrIndex);
            context.EmitStoreState();

            context.Emit(OpCodes.Ret);
        }
Пример #12
0
        public static void EmitStoreToRegister(ILEmitterCtx context, int register)
        {
            if (register == RegisterAlias.Aarch32Pc)
            {
                context.EmitStoreState();

                EmitBxWritePc(context);
            }
            else
            {
                context.EmitStint(GetRegisterAlias(context.Mode, register));
            }
        }
Пример #13
0
        public static void B(ILEmitterCtx context)
        {
            OpCodeBImmAl64 op = (OpCodeBImmAl64)context.CurrOp;

            if (context.CurrBlock.Branch != null)
            {
                context.Emit(OpCodes.Br, context.GetLabel(op.Imm));
            }
            else
            {
                context.EmitStoreState();
                context.EmitLdc_I8(op.Imm);

                context.Emit(OpCodes.Ret);
            }
        }
Пример #14
0
        private static void EmitAluWritePc(ILEmitterCtx context)
        {
            context.EmitStoreState();

            if (IsThumb(context.CurrOp))
            {
                context.EmitLdc_I4(~1);

                context.Emit(OpCodes.And);
                context.Emit(OpCodes.Conv_U8);
                context.Emit(OpCodes.Ret);
            }
            else
            {
                EmitBxWritePc(context);
            }
        }
Пример #15
0
        private static void EmitExceptionCall(ILEmitterCtx context, string mthdName)
        {
            OpCodeException64 op = (OpCodeException64)context.CurrOp;

            context.EmitStoreState();

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitLdc_I8(op.Position);
            context.EmitLdc_I4(op.Id);

            context.EmitPrivateCall(typeof(CpuThreadState), mthdName);

            //Check if the thread should still be running, if it isn't then we return 0
            //to force a return to the dispatcher and then exit the thread.
            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitCallPropGet(typeof(CpuThreadState), nameof(CpuThreadState.Running));

            ILLabel lblEnd = new ILLabel();

            context.Emit(OpCodes.Brtrue_S, lblEnd);

            context.EmitLdc_I8(0);

            context.Emit(OpCodes.Ret);

            context.MarkLabel(lblEnd);

            if (context.CurrBlock.Next != null)
            {
                context.EmitLoadState(context.CurrBlock.Next);
            }
            else
            {
                context.EmitLdc_I8(op.Position + 4);

                context.Emit(OpCodes.Ret);
            }
        }
Пример #16
0
        public static void Und(ILEmitterCtx context)
        {
            OpCode64 op = context.CurrOp;

            context.EmitStoreState();

            context.EmitLdarg(TranslatedSub.StateArgIdx);

            context.EmitLdc_I8(op.Position);
            context.EmitLdc_I4(op.RawOpCode);

            context.EmitPrivateCall(typeof(CpuThreadState), nameof(CpuThreadState.OnUndefined));

            if (context.CurrBlock.Next != null)
            {
                context.EmitLoadState(context.CurrBlock.Next);
            }
            else
            {
                context.EmitLdc_I8(op.Position + 4);

                context.Emit(OpCodes.Ret);
            }
        }
Пример #17
0
        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);
            }
        }