internal void UpdateTotal(ExecState newExecState) { CyclesConsumed += newExecState.CyclesConsumed; InstructionsExecutionCount += newExecState.InstructionsExecutionCount; UnknownOpCodeCount += newExecState.UnknownOpCodeCount; LastOpCodeWasHandled = newExecState.LastOpCodeWasHandled; LastOpCode = newExecState.LastOpCode; PCBeforeLastOpCodeExecuted = newExecState.PCBeforeLastOpCodeExecuted; }
public CPU(ExecState execState) { ProcessorStatus = new ProcessorStatus(); ExecState = execState; // TODO: Inject instruction list? InstructionList = InstructionList.GetAllInstructions(); // TODO: Inject InstructionExecutor? _instructionExecutor = new InstructionExecutor(); }
public static ExecState ExecStateAfterInstruction(ulong cyclesConsumed, bool unknownInstruction, byte?lastOpCode, ushort?lastPC) { var execState = new ExecState(); execState.InstructionsExecutionCount = 1; execState.CyclesConsumed = cyclesConsumed; execState.InstructionsExecutionCount += unknownInstruction?(ulong)1:(ulong)0; execState.PCBeforeLastOpCodeExecuted = lastPC; execState.LastOpCode = lastOpCode; return(execState); }
public ExecState Execute( Memory mem, ExecOptions execOptions) { // Collect stats for this invocation of Execute(). // Whereas the property Cpu.ExecState contains the aggregate stats for all invocations of Execute(). var thisExecState = new ExecState(); // Get current cycle count bool doNextInstruction = true; while (doNextInstruction) { // Fire event before instruction executes OnInstructionToBeExecuted(new CPUInstructionToBeExecutedEventArgs(this, mem)); // Execute instruction ushort PCBeforeInstructionExecuted = PC; var instructionExecutionResult = _instructionExecutor.Execute(this, mem); // Collect stats for this instruction. // Whereas the property thisExecState contains the aggregate stats for this invocation of Execute(). // and the property Cpu.ExecState contains the aggregate stats for all invocations of Execute(). var instructionExecState = ExecState.ExecStateAfterInstruction( cyclesConsumed: instructionExecutionResult.CyclesConsumed, unknownInstruction: instructionExecutionResult.UnknownInstruction, lastOpCode: instructionExecutionResult.OpCodeByte, lastPC: PCBeforeInstructionExecuted ); // Update/Aggregate total Cpu.ExecState stats ExecState.UpdateTotal(instructionExecState); // Update/Aggregate this invocation of Execute() ExecState stats thisExecState.UpdateTotal(instructionExecState); // Fire "unknown opcode" or "instruction executed" event if (instructionExecutionResult.UnknownInstruction) { OnUnknownOpCodeDetected(new CPUUnknownOpCodeDetectedEventArgs(this, mem, instructionExecutionResult.OpCodeByte)); Debug.WriteLine($"Unknown opcode: {instructionExecutionResult.OpCodeByte.ToHex()}"); // Check if we're configured to throw exception when unknown exception occurs if (execOptions.UnknownInstructionThrowsException) { throw new DotNet6502Exception($"Unknown opcode: {instructionExecutionResult.OpCodeByte.ToHex()}"); } } else { OnInstructionExecuted(new CPUInstructionExecutedEventArgs(this, mem)); } // Check if we should continue executing instructions if (execOptions.CyclesRequested.HasValue && thisExecState.CyclesConsumed >= execOptions.CyclesRequested.Value) { doNextInstruction = false; } if (execOptions.MaxNumberOfInstructions.HasValue && thisExecState.InstructionsExecutionCount >= execOptions.MaxNumberOfInstructions.Value) { doNextInstruction = false; } if (!instructionExecutionResult.UnknownInstruction && execOptions.ExecuteUntilInstruction.HasValue && instructionExecutionResult.OpCodeByte == execOptions.ExecuteUntilInstruction.Value.ToByte()) { doNextInstruction = false; } if (execOptions.ExecuteUntilInstructions.Count > 0 && execOptions.ExecuteUntilInstructions.Contains(instructionExecutionResult.OpCodeByte)) { doNextInstruction = false; } if (execOptions.ExecuteUntilPC.HasValue && PC == execOptions.ExecuteUntilPC.Value) { doNextInstruction = false; } if (execOptions.ExecuteUntilExecutedInstructionAtPC.HasValue && PCBeforeInstructionExecuted == execOptions.ExecuteUntilExecutedInstructionAtPC.Value) { doNextInstruction = false; } } // Return stats for this invocation of Execute(); return(thisExecState); }