Пример #1
0
 public Assembler(ref byte[] bytes, AssemblerConfig config)
 {
     this.Config = config;
     this.Bytes  = bytes;
 }
Пример #2
0
 public Assembler(AssemblerConfig config)
 {
     this.Config = config;
 }
Пример #3
0
        /// <summary>
        /// Determines addressing method of a line
        /// </summary>
        /// <param name="assembler"></param>
        public void DetermineAddressingMethod(AssemblerConfig config)
        {
            if (this.OpCode == null)
            {
                throw new InvalidOperationException("Attempt to determine addressing method of non-statement");
            }

            if (this.RValue == null)
            {
                this.AddressingMethod = Assembly.AddressingMethod.implied;
                return;
            }

            //will include branches, jmp, implied, accumulator (shown as implied
            if (Assembly.OpcodeTable[OpCode.Value].Keys.Count == 1)
            {
                AddressingMethod = Assembly.OpcodeTable[OpCode.Value].Keys.First();
                return;
            }

            //branches and jumps were already detected before this point
            this.RValue.ParseValue(this.OpCode.Value);

            var result = this.RValue.ComputedValue;

            var choices =
                RValue.LineEndingToOptions[this.RValue.ValueRight].Where(
                    choice => Assembly.OpcodeTable[this.OpCode.Value].Keys.Contains(choice)
                    ).ToList();

            if (choices.Count == 0)
            {
                throw new SyntaxErrorException("Illegal addressing method for opcode");
            }

            if (choices.Count == 1)
            {
                this.AddressingMethod = choices.First();
                return;
            }

            if (result.Literal)
            {
                this.AddressingMethod = Assembly.AddressingMethod.immediate;
                return;
            }

            choices.Remove(Assembly.AddressingMethod.immediate);

            if (choices.Count == 0)
            {
                throw new SyntaxErrorException("Illegal addressing method for opcode");
            }

            if (choices.Count == 1)
            {
                this.AddressingMethod = choices.First();
                return;
            }

            Assembly.AddressingMethod lo = choices.Where(choice => Assembly.AddressingMethodLength[choice] == 1).First();
            Assembly.AddressingMethod hi = choices.Where(choice => Assembly.AddressingMethodLength[choice] == 2).First();

            switch (config.OperandLength)
            {
            case AssemblerConfig.OperandLengthOption.Longest:
                this.AddressingMethod = hi;
                return;

            case AssemblerConfig.OperandLengthOption.Smallest:
                if (result.Result > byte.MaxValue)
                {
                    this.AddressingMethod = hi;
                    return;
                }

                this.AddressingMethod = lo;
                return;

            case AssemblerConfig.OperandLengthOption.AsWritten:
                //Only works in binary and hex because they're the ones where one extra digit is the point where it goes from one byte to two
                if (result.Base == 2 || result.Base == 16)
                {
                    //maximum characters before there are more characters than necessary to represent 256
                    int bumpLimit = result.Base == 2 ? 8 : 2;

                    if (result.ValueString.Length > bumpLimit)
                    {
                        this.AddressingMethod = hi;
                        return;
                    }

                    this.AddressingMethod = lo;
                    return;
                }

                if (result.Result > byte.MaxValue)
                {
                    this.AddressingMethod = hi;
                    return;
                }
                this.AddressingMethod = lo;
                return;
            }

            throw new SyntaxErrorException("Unable to determine addressing method");
        }