/// <summary> /// Performs a single processor step. /// </summary> private int Step() { reader.Address = machine.PC; currentInstruction = reader.NextInstruction(); var oldPC = machine.PC; OnStepping(oldPC); var newPC = machine.Step(); // If the instruction just executed was a call, we should add the address to the // routine table. The address is packed inside the first operand value. Note that // we need to do this prior to calling firing the ProcessorStepped event to ensure // that the disassembly view gets updated with the new routine before attempting // to set the new IP. if (currentInstruction.Opcode.IsCall) { var callOpValue = machine.GetOperandValue(0); var callAddress = storyService.Story.UnpackRoutineAddress(callOpValue); if (callAddress != 0) { routineService.Add(callAddress); } } OnStepped(oldPC, newPC); hasStepped = true; return(newPC); }
public override void Run() { MarkProfile("Reading story"); var story = ReadStory(StoryFilePath); var processor = new InterpretedZMachine(story); var done = false; Action doneAction = () => { done = true; }; var mockScreen = new MockScreen(ScriptFilePath, doneAction); processor.SetRandomSeed(42); processor.RegisterScreen(mockScreen); processor.Quit += (s, e) => { done = true; }; MarkProfile("Stepping..."); var sw = Stopwatch.StartNew(); try { while (!done) { processor.Step(); } } catch (Exception ex) { MarkProfile(string.Format("{0}: {1}", ex.GetType().FullName, ex.Message)); } sw.Stop(); MarkProfile("Done stepping"); Console.WriteLine(); Console.WriteLine("{0:#,#} instructions", processor.InstructionCount); Console.WriteLine("{0:#,#} calls", processor.CallCount); Console.WriteLine(); Console.WriteLine("{0:#,0.##########} seconds", (double)sw.ElapsedTicks / (double)Stopwatch.Frequency); Console.WriteLine("{0:#,0.##########} seconds per instruction", ((double)sw.ElapsedTicks / (double)Stopwatch.Frequency) / (double)processor.InstructionCount); }