/// <summary> /// Translates the second 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) and the other argument. /// </summary> /// <remarks> /// Because there is no third argument for I/O instructions, the second /// argument uses additional four bits. /// /// If the argument is a constant, it is stored in the lowest 7 bits, /// while the 8th has the value 0 to indicate a constant. /// /// If 3-bit addressing is used, the 5th to 8th bits have value 1000b, /// while the address is stored in the 3 lowest bits. The 4th lowest /// bit indicates if direct (0) or indirect (1) addressing is used. /// </remarks> /// <returns>A value containing the translation of the argument</returns> protected ushort TranslateArgument2() { if (Argument2.Type == ArgumentType.None) { return(1); // This argument is optional. } int value; Argument2.LookUpValue(Assembler, out value); if (Argument2.Type == ArgumentType.Constant || Argument2.Type == ArgumentType.SymbolConstant) { ushort constant = (ushort)value; // No shifting is required, and the constant range [0..127] garanties that // only the first 7 low bits can be set. return(constant); } else { // Write address to the lowest 3 bits ushort result = (ushort)value; if (Argument2.Type == ArgumentType.Indirect) { // Indirect addressing is indicated by setting the 4th lowest bit. result |= 0x8; } // The 3-bit address and the (in)direct addresing indicator are already in place. // It is only necessary to write the 1000b marker to the second argument position. result |= 0x8 << 4; return(result); } }
/// <summary> /// Checks if the second argument is valid. /// </summary> /// <remarks> /// The second 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] /// </remarks> /// <returns>A value indicating if Argument2 is valid</returns> protected bool CheckArgument2() { int value; if (!Argument2.LookUpValue(Assembler, out value)) { return(false); } if (Argument2.Type == ArgumentType.Direct || Argument2.Type == ArgumentType.Indirect) { if (value < 0 || value > 7) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument2.Text, 0, 7); Error.Line = Line; Error.Column = Argument2.Column; return(false); } } else { if (value < short.MinValue || value > short.MaxValue) { Error = new Error(); Error.ID = 2; Error.Description = string.Format(Messages.E0002, Argument2.Text); Error.Line = Line; Error.Column = Argument2.Column; return(false); } } return(true); }
/// <summary> /// Translates the second 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 argument</returns> protected ushort TranslateArgument2(ref bool constantSet, ref ushort constant) { int value; Argument2.LookUpValue(Assembler, out value); if (Argument2.Type == ArgumentType.Constant || Argument2.Type == ArgumentType.SymbolConstant) { constant = (ushort)value; constantSet = true; // The argument field content is not defined if it is a constant. return(0); } else { // Write address to the lowest 3 bits ushort result = (ushort)value; if (Argument2.Type == ArgumentType.Indirect) { // Indirect addressing is indicated by setting the 4th lowest bit. result |= 0x8; } // Move the argument to the right position : 00000000aaaa0000 result <<= 4; return(result); } }
/// <summary> /// Checks if the second argument is valid. /// </summary> /// <remarks> /// The second argument can be either a constant, or a direct or indirect 3-bit addressing. /// /// If the argument is a constant, its value must be between [0..127] because there are /// 7 bits reserved for storing the constant. /// These instructions have a maximum of two arguments, so the second argument is stored in eight /// instead of the usual four bits. /// /// If the argument is a 3-bit address, the value must be between [0..7] /// </remarks> /// <returns>A value indicating if Argument2 is valid</returns> protected bool CheckArgument2() { // If there is no second argumnt, then there is no argument here. See what I did there? :P if (Argument2.Type == ArgumentType.None) { return(true); } int value; if (!Argument2.LookUpValue(Assembler, out value)) { return(false); } if (Argument2.Type == ArgumentType.Direct || Argument2.Type == ArgumentType.Indirect) { if (value < 0 || value > 7) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument2.Text, 0, 7); Error.Line = Line; Error.Column = Argument2.Column; return(false); } } else { if (value < 0 || value > 127) { Error = new Error(); Error.ID = 5; Error.Description = Messages.E0005; Error.Line = Line; Error.Column = Argument2.Column; return(false); } } return(true); }
/// <summary> /// Checks if the second argument is valid. /// </summary> /// <remarks> /// The second 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 third 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 Argument2 is valid</returns> protected bool CheckArgument2() { int value; if (!Argument2.LookUpValue(Assembler, out value)) { return(false); } if (Argument2.Type == ArgumentType.Direct || Argument2.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 = Argument3.Type == ArgumentType.Constant || Argument3.Type == ArgumentType.SymbolConstant ? 1 : 0; if (value < min || value > 7) { Error = new Error(); Error.ID = 3; Error.Description = string.Format(Messages.E0003, Argument2.Text, min, 7); Error.Line = Line; Error.Column = Argument2.Column; return(false); } } else { if (value < short.MinValue || value > short.MaxValue) { Error = new Error(); Error.ID = 2; Error.Description = string.Format(Messages.E0002, Argument2.Text); Error.Line = Line; Error.Column = Argument2.Column; return(false); } } return(true); }