/// <summary> /// Method for performing the OUT instruction /// </summary> public static bool Output(ModuleBase module, MixInstruction.Instance instance) { if (module.Devices == null) { module.ReportRuntimeError("Module does not provide devices"); return(false); } var mValue = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (mValue == int.MinValue) { return(false); } int deviceIndex = instance.FieldSpec.MixByteValue.ByteValue; MixDevice device = module.Devices[deviceIndex]; if (!device.SupportsOutput) { module.ReportRuntimeError("Device " + deviceIndex + " doesn't support output"); return(false); } if (device.Busy) { return(false); } var field = WordField.LoadFromRegister(new FieldSpec(4, 5), module.Registers.RX); device.StartOutput(module.Memory, mValue, (int)field.LongValue, module is Mix && ((Mix)module).Mode == ModuleBase.RunMode.Control ? new InterruptQueueCallback(((Mix)module).QueueInterrupt) : null); return(true); }
/// <summary> /// Method for performing STx instructions /// </summary> public static bool StoreRegister(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress != int.MinValue) { Register sourceRegister; if (instance.MixInstruction.Opcode == storeJOpcode) { sourceRegister = module.Registers.RJ; } else { sourceRegister = module.Registers[instance.MixInstruction.Opcode - storeOpcodeBase]; } WordField.LoadFromRegister(instance.FieldSpec, sourceRegister).ApplyToFullWord(module.Memory[indexedAddress]); } return(true); }
/// <summary> /// Method for performing the IOC instruction /// </summary> public static bool IOControl(ModuleBase module, MixInstruction.Instance instance) { if (module.Devices == null) { module.ReportRuntimeError("Module does not provide devices"); return(false); } var indexedAddress = module.Registers.GetIndexedAddress(instance.AddressValue, instance.Index); int deviceIndex = instance.FieldSpec.MixByteValue.ByteValue; MixDevice device = module.Devices[deviceIndex]; if (device.Busy) { return(false); } var field = WordField.LoadFromRegister(new FieldSpec(4, 5), module.Registers.RX); device.StartIoc(indexedAddress, (int)field.LongValue, module is Mix && ((Mix)module).Mode == ModuleBase.RunMode.Control ? new InterruptQueueCallback(((Mix)module).QueueInterrupt) : null); return(true); }
public static IValue ParseValue(string text, int sectionCharIndex, ParsingStatus status) { // split the text to parse in its W-value components var textParts = text.Split(new char[] { ',' }); int currentIndex = 0; var register = new FullWordRegister(); var word = new FullWord(0); // parse and apply each component to the word that contains the result foreach (string part in textParts) { // parse the address part... var braceIndex = part.IndexOf('('); var address = ExpressionValue.ParseValue((braceIndex == -1) ? part : part.Substring(0, braceIndex), sectionCharIndex + currentIndex, status); if (address == null) { return(null); } // ... and check if it is valid var addressSign = address.GetSign(status.LocationCounter); var addressMagnitude = address.GetMagnitude(status.LocationCounter); if (addressMagnitude > register.MaxMagnitude) { status.ReportParsingError(sectionCharIndex + currentIndex, (braceIndex == -1) ? part.Length : braceIndex, "W-value field value invalid"); return(null); } register.MagnitudeLongValue = addressMagnitude; register.Sign = addressSign; int fieldValue = FullWord.ByteCount; // if a fieldspec part is present... if (braceIndex >= 0) { // ... parse its value... var field = FPartValue.ParseValue(part.Substring(braceIndex), (sectionCharIndex + currentIndex) + braceIndex, status); if (field == null) { return(null); } // ... and check if it is valid if (field.GetValue(status.LocationCounter) != FPartValue.Default) { fieldValue = (int)field.GetValue(status.LocationCounter); } } // use the fieldspec value to create and check an actual fieldspec var fieldSpec = new FieldSpec(fieldValue); if (!fieldSpec.IsValid) { status.ReportParsingError((sectionCharIndex + currentIndex) + braceIndex, part.Length - braceIndex, "field must be a fieldspec"); return(null); } // apply the component to the word that will contain the end result WordField.LoadFromRegister(fieldSpec, register).ApplyToFullWord(word); currentIndex += part.Length + 1; } return(new NumberValue(word.Sign, word.MagnitudeLongValue)); }