/// <summary> /// Method for performing MUL instruction /// </summary> public static bool Multiply(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress == int.MinValue) { return(false); } Register rA = module.Registers.RA; Register rX = module.Registers.RX; long rAValue = rA.LongValue; long memoryWordValue = WordField.LoadFromFullWord(instance.FieldSpec, module.Memory[indexedAddress]).LongValue; var result = decimal.Multiply(rAValue, memoryWordValue); rA.Sign = rX.Sign = result.GetSign(); result = result.GetMagnitude(); var rXResultValue = (long)(result % ((long)1 << rX.BitCount)); var rAResultValue = (long)decimal.Truncate(result / ((long)1 << rX.BitCount)); rA.MagnitudeLongValue = rAResultValue; rX.MagnitudeLongValue = rXResultValue; return(true); }
/// <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 the STZ instruction /// </summary> public static bool StoreZero(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress != int.MinValue) { var word = new FullWord(); WordField.LoadFromFullWord(instance.FieldSpec, word).ApplyToFullWord(module.Memory[indexedAddress]); } return(true); }
/// <summary> /// Method for performing CMPx instructions /// </summary> public static bool Compare(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress == int.MinValue) { return(false); } int registerIndex = instance.MixInstruction.Opcode - opcodeBase; Register register = module.Registers[registerIndex]; module.Registers.CompareIndicator = WordField.LoadFromFullWord(instance.FieldSpec, register.FullWordValue).CompareTo(module.Memory[indexedAddress]).ToCompValue(); return(true); }
/// <summary> /// Method for performing DIV instruction /// </summary> public static bool Divide(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress == int.MinValue) { return(false); } long memoryWordValue = WordField.LoadFromFullWord(instance.FieldSpec, module.Memory[indexedAddress]).LongValue; if (memoryWordValue == 0L) { module.ReportOverflow(); return(true); } Register rA = module.Registers.RA; Register rX = module.Registers.RX; long rAValue = rA.LongValue; long rXValue = rX.LongValue; decimal rAXValue = (decimal)rAValue * ((long)1 << rX.BitCount) + rXValue; decimal divider = rAXValue / memoryWordValue; rX.Sign = rA.Sign; rA.Sign = divider.GetSign(); divider = divider.GetMagnitude(); if (divider > rA.MaxMagnitude) { module.ReportOverflow(); return(true); } decimal remainder = rAXValue % memoryWordValue; rA.MagnitudeLongValue = (long)divider; rX.MagnitudeLongValue = (long)remainder; return(true); }
static bool DoLoad(ModuleBase module, MixInstruction.Instance instance, int registerIndex, bool negateSign) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress == int.MinValue) { return(false); } var memoryField = WordField.LoadFromFullWord(instance.FieldSpec, module.Memory[indexedAddress]); if (negateSign) { memoryField.InvertSign(); } memoryField.ApplyToRegister(module.Registers[registerIndex]); 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); }
/// <summary> /// Method for performing ADD and SUB instructions /// </summary> public static bool AddSubstract(ModuleBase module, MixInstruction.Instance instance) { var indexedAddress = InstructionHelpers.GetValidIndexedAddress(module, instance.AddressValue, instance.Index); if (indexedAddress == int.MinValue) { return(false); } Register rA = module.Registers.RA; long rALongValue = rA.LongValue; long memoryWordValue = WordField.LoadFromFullWord(instance.FieldSpec, module.Memory[indexedAddress]).LongValue; if (instance.MixInstruction.Opcode == substractOpcode) { memoryWordValue = -memoryWordValue; } long sumValue = rALongValue + memoryWordValue; if (sumValue != 0L) { rA.Sign = sumValue.GetSign(); sumValue = sumValue.GetMagnitude(); } if (sumValue > rA.MaxMagnitude) { module.ReportOverflow(); sumValue &= rA.MaxMagnitude; } rA.MagnitudeLongValue = sumValue; 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)); }