private void ExecuteMicroStep(IProcessor processor, IProcessorSession session) { var mpmEntry = mpm.MicroInstructions[(int)processor.Registers[Registers.MIP].Value]; //Halt processor, if halt instruction was reached if (IsHalt(mpmEntry, processor)) { session.SetHalted(true); } if (processor.IsHalted) { return; } //Transfer data from source to target session.SetRegister(Registers.MIP, NextMip(processor, mpmEntry)); var dataBus = mpmEntry.EnableValue ? (uint)mpmEntry.Value : GetDataBusValue(session, mpmEntry); WriteDataBusToRegister(session, mpmEntry, dataBus); //Reset interrupt flag if (mpmEntry.ClearInterrupt) { session.SetRegister(Registers.Interrupt, 0); } //Execute ALU command if one is contained in the mpm entry if (mpmEntry.AluCommand != AluCmd.NOP) { var status = new StatusRegister(processor.Registers[Registers.Status]); var result = processor.Alu.Execute(mpmEntry.AluCommand, (byte)processor.Registers[Registers.X].Value, (byte)processor.Registers[Registers.Y].Value, ref status); session.SetRegister(Registers.RES, result); if (mpmEntry.AffectFlags) { session.SetRegister(status.Register); } } }
/// <summary> /// Writes the given databus value to the register determined by the micro program memory entry. /// </summary> /// <param name="session"></param> /// <param name="mpmEntry">Current micro program memory entry</param> /// <param name="dataBus">DataBus value</param> private void WriteDataBusToRegister(IProcessorSession session, IMicroInstruction mpmEntry, uint dataBus) { Registers target; switch (mpmEntry.Destination) { case Destination.Empty: return; case Destination.SELReferenced: target = GetSELReferenced(session.Processor); break; case Destination.MDR: if (mpmEntry.ReadWrite == ReadWrite.Write) { var memoryAddress = (byte)session.Processor.Registers[Registers.MAR].Value; if (mpmEntry.DataInput == DataInput.IO) { var devices = session.DeviceManager.Devices; if (devices.ContainsKey(memoryAddress)) { devices[memoryAddress].Input((byte)dataBus); } } else { session.RamSession.Set(memoryAddress, (byte)dataBus); } } target = Registers.MDR; break; default: target = (Registers)mpmEntry.Destination; break; } session.SetRegister(target, dataBus); }
/// <summary> /// Resets all registers of the processor in the given session. /// </summary> /// <param name="session"></param> private void ResetRegisters(IProcessorSession session) { foreach (var type in RegistersExtensions.GetValues()) { session.SetRegister(type, type == Registers.SP ? session.Processor.InitialStackPointer : 0); } }
/// <summary> /// Returns the value, which is currently active on the databus. /// </summary> /// <param name="processor"></param> /// <param name="mpmEntry">Current micro program memory entry</param> /// <returns>DataBus value</returns> private uint GetDataBusValue(IProcessorSession session, IMicroInstruction mpmEntry) { var processor = session.Processor; switch (mpmEntry.Source) { case Source.Empty: return 0; case Source.Data: var memoryAddress = (byte)processor.Registers[Registers.MAR].Value; if (mpmEntry.DataInput == DataInput.IO) { var devices = session.DeviceManager.Devices; if (devices.ContainsKey(memoryAddress)) { return devices[memoryAddress].Output(); } else { return 0; } } else { return processor.Ram.Data[memoryAddress]; } case Source.SELReferenced: return processor.Registers[GetSELReferenced(processor)].Value; default: return processor.Registers[(Registers)mpmEntry.Source].Value; } }