예제 #1
0
        public static VMRoutine Assemble(VM vm, BHAV bhav)
        {
            var context = vm.Context;

            var routine = new VMRoutine();
            routine.Locals = bhav.Locals;
            routine.Arguments = bhav.Args;
            routine.Type = bhav.Type;
            routine.VM = vm;
            routine.Rti = new VMFunctionRTI {
                Name = bhav.ChunkLabel
            };

            VMInstruction[] instructions = new VMInstruction[bhav.Instructions.Length];
            for (var i = 0; i < bhav.Instructions.Length; i++)
            {
                var bhavInstruction = bhav.Instructions[i];
                var instruction = new VMInstruction();

                instruction.Index = (byte)i;
                instruction.Opcode = bhavInstruction.Opcode;
                instruction.Operand = bhavInstruction.Operand;
                instruction.FalsePointer = bhavInstruction.FalsePointer;
                instruction.TruePointer = bhavInstruction.TruePointer;
                instruction.Function = routine;

                /** Routine call **/
                if (instruction.Opcode >= 256)
                {
                    var operand = new VMSubRoutineOperand();
                    operand.Read(bhavInstruction.Operand);
                    instruction.Operand = operand;
                }
                else
                {
                    var primitive = context.GetPrimitive(instruction.Opcode);
                    if (primitive != null)
                    {
                        if (primitive.OperandModel != null)
                        {
                            VMPrimitiveOperand operand = (VMPrimitiveOperand)Activator.CreateInstance(primitive.OperandModel);
                            operand.Read(bhavInstruction.Operand);
                            instruction.Operand = operand;
                        }
                    }
                }
                instructions[i] = instruction;

            }
            routine.Instructions = instructions;
            return routine;
        }
예제 #2
0
        private void ExecuteSubRoutine(VMStackFrame frame, BHAV bhav, GameIffResource codeOwner, VMSubRoutineOperand args)
        {
            if (bhav == null){
                Pop(VMPrimitiveExitCode.ERROR);
                return;
            }
            System.Diagnostics.Debug.WriteLine("Invoke: " + bhav.ChunkLabel);
            System.Diagnostics.Debug.WriteLine("");

            var routine = frame.VM.Assemble(bhav);
            var childFrame = new VMStackFrame
            {
                Routine = routine,
                Caller = frame.Caller,
                Callee = frame.Callee,
                CodeOwner = codeOwner,
                StackObject = frame.StackObject
            };
            childFrame.Args = new short[routine.Arguments];
            for (var i = 0; i < childFrame.Args.Length; i++){
                var argValue = args.Arguments[i];
                if (argValue == -1)
                {
                    /** TODO: Is this the right rule? Maybe a flag decides when to copy from temp? **/
                    argValue = TempRegisters[i];
                }
                childFrame.Args[i] = argValue;
            }
            Push(childFrame);
        }