/// <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> /// Calculates the next micro instruction pointer (MIP). /// This is calculated from the processor state and the current micro program memory entry. /// </summary> /// <param name="session"></param> /// <param name="mpmEntry">Current micro program memory entry</param> /// <returns>New micro instruction pointer</returns> private uint NextMip(IProcessor processor, IMicroInstruction mpmEntry) { var mip = processor.Registers[Registers.MIP].Value; var status = new StatusRegister(processor.Registers[Registers.Status]); switch (mpmEntry.NextAddress) { case NextAddress.Next: return mip + (uint)(SuccessfulJump(status, mpmEntry.JumpCriterion) ? mpmEntry.Value : 1); case NextAddress.Decode: var instruction = processor.Registers[Registers.IR].Value; return (uint)mpm.Instructions[(byte)instruction].MpmAddress; case NextAddress.Fetch: var interrupt = processor.Registers[Registers.Interrupt]; return (status.Interrupt && interrupt.Value == 1) ? InterruptAddress : FetchAddress; default: throw new NotImplementedException(); } }
/// <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; } }
/// <summary> /// Checks if the processor reched a state in which it should be halted. /// </summary> /// <param name="mpmEntry"></param> /// <param name="processor"></param> /// <returns></returns> private bool IsHalt(IMicroInstruction mpmEntry, IProcessor processor) => mpmEntry.NextAddress == NextAddress.Decode && processor.Registers[Registers.IR].Value == 0;