/// <summary> /// Checks if the third argument is valid. /// </summary> /// <remarks> /// The third argument represents the branch destination address, and uses direct /// or indirect addressing. However, it is not translated in the same manner that /// applies to the 3-bit addressing in other instructions. /// /// If the direct addressing is used, the value of the symbol is considered the /// branch destination and is stored in a separate word as a constant. The value /// must be a valid 16-bit address [0..65535]. /// /// If the indirect addressing is used, the value must be a 3-bit address [0..7] /// </remarks> /// <returns>A value indicating if Argument3 is valid</returns> protected bool CheckArgument3() { int value; if (!Argument3.LookUpValue(Assembler, out value)) { return(false); } if (Argument3.Type == ArgumentType.Direct) { if (value < ushort.MinValue || value > ushort.MaxValue) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument3.Text, ushort.MinValue, ushort.MaxValue); Error.Line = Line; Error.Column = Argument3.Column; return(false); } } else { if (value < 0 || value > 7) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument3.Text, 0, 7); Error.Line = Line; Error.Column = Argument3.Column; return(false); } } return(true); }
/// <summary> /// Checks if the third argument is valid. /// </summary> /// <remarks> /// The third argument can be either a constant, or a direct or indirect 3-bit addressing. /// /// If the argument is a constant, it's value can be between [-32768..32767] /// /// If the argument is a 3-bit address, the value can be between [0..7] only if /// the second argument is NOT a constant. Otherwise, it is between [1..7]. /// This is due to fact that the constant argument is encoded as 0 and it /// would be imposible to differentiate it from the 0 address. /// (The constant is stored in the second word of the instruction and only one /// argument can be a constant.) /// </remarks> /// <returns>A value indicating if Argument3 is valid</returns> protected bool CheckArgument3() { int value; if (!Argument3.LookUpValue(Assembler, out value)) { return(false); } if (Argument3.Type == ArgumentType.Direct || Argument3.Type == ArgumentType.Indirect) { // Techically, an indirect addressing of the zero address would not be a problem, because the encoded // argument would be 1000b, not 0000b like a constant, but pCAS (the original assembler) does not allow this. // For compatibility, neither does Messy Lab. int min = Argument2.Type == ArgumentType.Constant || Argument2.Type == ArgumentType.SymbolConstant ? 1 : 0; if (value < min || value > 7) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument3.Text, min, 7); Error.Line = Line; Error.Column = Argument3.Column; return(false); } } else { if (value < short.MinValue || value > short.MaxValue) { Error = new Error(); Error.ID = 2; Error.Description = string.Format(Messages.E0002, Argument3.Text); Error.Line = Line; Error.Column = Argument3.Column; return(false); } } return(true); }
/// <summary> /// Translates the third argument to the machine code. /// The resulting value contains the argument encoding in the right /// position within the word, and zeroes in locations intended for the /// OPCode (mnemonic) or other arguments. /// </summary> /// <param name="constantSet">used to indicate that the argument is a consant, otherwise unchanged</param> /// <param name="constant">used to store the constant, if any, otherwise unchanged</param> /// <returns>A value containing the translation of the Argument3</returns> protected ushort TranslateArgument3(ref bool constantSet, ref ushort constant) { int ivalue; Argument3.LookUpValue(Assembler, out ivalue); ushort value = (ushort)ivalue; if (Argument3.Type == ArgumentType.Direct) { // If the direct addressing is used, the argument translates as 1000b // and the actual value is stored in a second word. constant = value; constantSet = true; // No shifting is required because the third argument uses the 4 lowest bits return(0x8); } else // Indirect { // Unlike for other instructions, indirect addressing is not marked by setting the // 4th lowest bit. return(value); } }
/// <summary> /// Translates the third argument to the machine code. If there is no /// third argument, its argument field is used as an extension to the /// OPCode to indicate if the second argument is a constant. /// /// The resulting value contains the argument encoding in the right /// position within the word, and zeroes in locations intended for the /// OPCode (mnemonic) or other arguments. /// </summary> /// <param name="constantSet">used to indicate that the argument is a consant, otherwise unchanged</param> /// <param name="constant">used to store the constant, if any, otherwise unchanged</param> /// <returns>A value containing the translation of the argument</returns> protected ushort TranslateArgument3(ref bool constantSet, ref ushort constant) { if (Argument3.Type == ArgumentType.None) { // If there is no third argument, its field is used to indicate // the type of the second one (1000b if it is a constant, or 0000b // if it is a 3-bit address). if (constantSet) { return(8); } else { return(0); } } else { int value; Argument3.LookUpValue(Assembler, out value); if (Argument3.Type == ArgumentType.Direct) { // The address is already in the lowest 3 bits. return((ushort)value); } else // A constant { constantSet = true; constant = (ushort)value; // A constant as the third argument is indicated by 1111b value // in its argument field. return(0xF); } } }