Пример #1
0
        private void EmitDirectCall(Operand addressOp, ReadOnlyArray <Operand> args)
        {
            if (machine.Profiling)
            {
                il.Arguments.LoadMachine();
                if (addressOp.Value == 0)
                {
                    il.Load(0);
                }
                else
                {
                    il.Load(machine.UnpackRoutineAddress(addressOp.Value));
                }

                il.Load(false);
                il.Call(Reflection <CompiledZMachine> .GetMethod("Profiler_Call", Types.Array <int, bool>(), @public: false));
            }

            if (addressOp.Value == 0)
            {
                il.Load(0);
                EmitReturn();
            }
            else
            {
                var address     = machine.UnpackRoutineAddress(addressOp.Value);
                var routineCall = machine.GetRoutineCall(address);
                var index       = calls.Count;
                calls.Add(routineCall);

                // load routine call
                il.Arguments.LoadCalls();
                il.Load(index);
                il.Emit(OpCodes.Ldelem_Ref);

                foreach (var arg in args)
                {
                    EmitLoadOperand(arg);
                }

                // The memory, stack and stack pointer are the last arguments passed in
                // case any operands manipulate them.
                il.Arguments.LoadMemory();
                il.Arguments.LoadStack();
                il.Arguments.LoadSP();

                il.Call(ZRoutineCall.GetInvokeMethod(args.Length));
            }
        }
Пример #2
0
        internal ZRoutineCall GetRoutineCall(int address)
        {
            ZRoutineCall routineCall;

            if (!addressToRoutineCallMap.TryGetValue(address, out routineCall))
            {
                cacheMiss++;
                var routine = GetRoutineByAddress(address);
                routineCall = new ZRoutineCall(routine, machine: this);
                addressToRoutineCallMap.Add(address, routineCall);
            }

            if (this.precompile && !compiling)
            {
                compiling = true;
                routineCall.Compile();
                compiling = false;
            }

            return(routineCall);
        }
Пример #3
0
        private void EmitCalculatedCall(Operand addressOp, ReadOnlyArray <Operand> args, bool reuse)
        {
            using (var address = il.NewLocal <int>())
            {
                if (!reuse)
                {
                    EmitLoadVariable((byte)addressOp.Value);
                }

                address.Store();

                // is this address 0?
                var nonZeroCall = il.NewLabel();
                var done        = il.NewLabel();
                address.Load();
                nonZeroCall.BranchIf(Condition.True);

                if (machine.Profiling)
                {
                    il.Arguments.LoadMachine();
                    il.Load(0);
                    il.Load(true);

                    var profilerCall = Reflection <CompiledZMachine> .GetMethod("Profiler_Call", Types.Array <int, bool>(), @public : false);

                    il.Call(profilerCall);
                }

                // discard any SP operands...
                int spOperands = 0;
                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i].IsStackVariable)
                    {
                        spOperands++;
                    }
                }

                if (spOperands > 0)
                {
                    il.Arguments.LoadSP();
                    il.Math.Subtract(spOperands);
                    il.Arguments.StoreSP();
                }

                il.Load(0);

                done.Branch();

                nonZeroCall.Mark();

                if (machine.Profiling)
                {
                    il.Arguments.LoadMachine();
                    address.Load();
                    UnpackRoutineAddress();
                    il.Load(true);

                    il.Call(Reflection <CompiledZMachine> .GetMethod("Profiler_Call", Types.Array <int, bool>(), @public: false));
                }

                il.Arguments.LoadMachine();
                address.Load();
                UnpackRoutineAddress();

                il.Call(Reflection <CompiledZMachine> .GetMethod("GetRoutineCall", Types.Array <int>(), @public: false));

                foreach (var arg in args)
                {
                    EmitLoadOperand(arg);
                }

                // The stack and stack pointer are the last arguments passed in
                // case any operands manipulate them.
                il.Arguments.LoadMemory();
                il.Arguments.LoadStack();
                il.Arguments.LoadSP();

                il.Call(ZRoutineCall.GetInvokeMethod(args.Length));

                done.Mark();
            }
        }