Example #1
0
        /// <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);
        }
Example #2
0
        /// <summary>
        /// Formats the instruction as string.
        /// <example>
        /// ADD (x), x, 2
        /// </example>
        /// </summary>
        /// <returns>A string representing the instruction</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(Mnemonic);
            sb.Append(' ');
            sb.Append(Argument1.ToString());
            if (Argument2.Type != ArgumentType.None)
            {
                sb.Append(", ");
                sb.Append(Argument2.ToString());
            }
            if (Argument3.Type != ArgumentType.None)
            {
                sb.Append(", ");
                sb.Append(Argument3.ToString());
            }
            return(sb.ToString());
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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);
            }
        }
Example #5
0
        /// <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);
                }
            }
        }