Example #1
0
File: Mix.cs Project: arlm/MixEmul
        public void Tick()
        {
            if (Mode != RunMode.Module)
            {
                if (mInterruptQueue.Count > 0 && mCurrentInstructionTicksLeft == 0 && Mode != RunMode.Control && (Status == RunStatus.Running || Status == RunStatus.Stepping || Status == RunStatus.Idle))
                {
                    if (mInterruptExecuted)
                    {
                        mInterruptExecuted = false;
                    }
                    else
                    {
                        InterruptHandler.HandleInterrupt(this, mInterruptQueue.Dequeue());
                    }
                }

                IncreaseTickCounter();

                if (Status == RunStatus.Halted)
                {
                    if (!mDevices.IsAnyBusy)
                    {
                        Status = RunStatus.Idle;
                    }
                    return;
                }
            }

            IMemoryFullWord instructionWord = Memory[ProgramCounter];
            var             instruction     = InstructionSet.Instance.GetInstruction(instructionWord[MixInstruction.OpcodeByte], new FieldSpec(instructionWord[MixInstruction.FieldSpecByte]));

            if (instruction == null)
            {
                ReportInvalidInstruction("Opcode (and field) do not encode an instruction");
                if (Mode == RunMode.Module)
                {
                    ResetMode();
                }

                return;
            }

            var instance = instruction.CreateInstance(instructionWord);
            var errors   = instance.Validate();

            if (errors != null)
            {
                ReportInvalidInstruction(errors);
                if (Mode == RunMode.Module)
                {
                    ResetMode();
                }

                return;
            }

            if (mCurrentInstructionAddress != ProgramCounter || mCurrentInstructionMnemonic != instruction.Mnemonic || (mCurrentInstructionTicksLeft <= 0 && Mode != RunMode.Module))
            {
                mCurrentInstructionAddress   = ProgramCounter;
                mCurrentInstructionTicksLeft = instruction.TickCount;
                mCurrentInstructionMnemonic  = instruction.Mnemonic;
                if (Mode == RunMode.Module)
                {
                    ResetMode();
                }
            }

            if (Mode != RunMode.Module && mCurrentInstructionTicksLeft > 0)
            {
                mCurrentInstructionTicksLeft--;

                if (ExecutionSettings.ProfilingEnabled)
                {
                    instructionWord.IncreaseProfilingTickCount(1);
                }
            }

            int programCounter;

            if (Mode == RunMode.Module || mCurrentInstructionTicksLeft == 0)
            {
                var increasePC = instance.Execute(this);

                programCounter = ProgramCounter;

                if (increasePC)
                {
                    programCounter++;
                }

                if (ExecutionSettings.ProfilingEnabled && (Mode != RunMode.Module || increasePC))
                {
                    instructionWord.IncreaseProfilingExecutionCount();
                }
            }
            else
            {
                programCounter = ProgramCounter;
            }

            if (programCounter > mMemory.MaxWordIndex)
            {
                ProgramCounter = mMemory.MaxWordIndex;
                ReportRuntimeError("Program counter overflow");
            }
            else
            {
                ProgramCounter = programCounter;
                if (Status == RunStatus.Running && IsBreakpointSet(programCounter))
                {
                    ReportBreakpointReached();
                }
            }
        }
Example #2
0
        public bool Tick()
        {
            bool overflowDetected = false;

            if (ProgramCounter == mExitAddress.Value)
            {
                Status = RunStatus.Idle;
                return(false);
            }

            if (mUnexpectedOverflowAddress != null && ProgramCounter == mUnexpectedOverflowAddress.Value)
            {
                ReportRuntimeError(string.Format("Overflow set at instruction start"));
                return(true);
            }

            if (mExponentOverflowAddress != null && ProgramCounter == mExponentOverflowAddress.Value)
            {
                AddLogLine(new LogLine(moduleName, Severity.Info, "Overflow", "Exponent overflow detected"));
                overflowDetected = true;
            }
            else if (mExponentUnderflowAddress != null && ProgramCounter == mExponentUnderflowAddress.Value)
            {
                AddLogLine(new LogLine(moduleName, Severity.Info, "Underflow", "Exponent underflow detected"));
                overflowDetected = true;
            }
            else if (mFixOverflowAddress != null && ProgramCounter == mFixOverflowAddress.Value)
            {
                AddLogLine(new LogLine(moduleName, Severity.Info, "Overflow", "Float to fix overflow detected"));
                overflowDetected = true;
            }
            else if (mDivisionByZeroAddress != null && ProgramCounter == mDivisionByZeroAddress.Value)
            {
                AddLogLine(new LogLine(moduleName, Severity.Info, "Overflow", "Division by zero detected"));
                overflowDetected = true;
            }

            Status = RunStatus.Running;

            IMemoryFullWord instructionWord = Memory[ProgramCounter];
            var             instruction     = InstructionSet.Instance.GetInstruction(instructionWord[MixInstruction.OpcodeByte], new FieldSpec(instructionWord[MixInstruction.FieldSpecByte]));

            if (instruction == null)
            {
                ReportInvalidInstruction("Opcode (and field) do not encode an instruction");
                return(false);
            }

            var instance = instruction.CreateInstance(instructionWord);
            var errors   = instance.Validate();

            if (errors != null)
            {
                ReportInvalidInstruction(errors);
                return(false);
            }

            var increasePC = instance.Execute(this);

            if (ExecutionSettings.ProfilingEnabled)
            {
                instructionWord.IncreaseProfilingTickCount(instruction.TickCount);
                instructionWord.IncreaseProfilingExecutionCount();
            }

            int programCounter = ProgramCounter;

            if (increasePC)
            {
                programCounter++;
            }

            if (programCounter > mMemory.MaxWordIndex)
            {
                ProgramCounter = mMemory.MaxWordIndex;
                ReportRuntimeError("Program counter overflow");
            }
            else
            {
                ProgramCounter = programCounter;
                if (Status == RunStatus.Running && IsBreakpointSet(programCounter))
                {
                    ReportBreakpointReached();
                }
            }

            return(overflowDetected);
        }