Esempio n. 1
0
        bool OpcodeHandled(AsmState state, Line line)
        {
            var mnemonic = GetMnemonic(line);
            var op       = State.Cpu.FindOpcode(mnemonic);

            if (op != null)
            {
                line.Address = state.Address;
                State.Cpu.ParseOpcodeAndOperand(state, line, op);
                return(true);
            }
            return(false);
        }
Esempio n. 2
0
        bool StructHandled(AsmState state, Line line)
        {
            var structName = line.Opcode.Text;
            var str        = state.Symbols.GetStructs().FirstOrDefault(s => s.Text == structName);

            if (str != null)
            {
                line.Address = state.Address;
                var operands = line.Operand?.Text ?? "";
                line.Length = str.ByteLength;
                if (String.IsNullOrEmpty(operands))
                {
                    Error(line, line.Opcode, "Empty struct operand");
                    return(false);
                }
                // odd special case of zeroed fields
                var cleaned = operands.Replace("<", "").Replace(">", "").Replace("\t", "").Replace(" ", "");
                var zeroOut = cleaned == "0"; // special case - if this, zero out structure
                cleaned = ConvertStringsToNumbers(cleaned);
                var items = cleaned.Split(',');
                if (str.ByteLengths.Count != items.Length && !zeroOut)
                {
                    Error(line, line.Operand, $"Struct def has {str.ByteLengths.Count} fields, operand has {items.Length}");
                    return(false);
                }
                var bytesAlready = line.Data.Count;
                var value        = 0;
                for (var i = 0; i < str.ByteLengths.Count; ++i)
                {
                    if (zeroOut || Evaluator.Evaluate(state, line, items[i], out value))
                    {
                        line.AddValue(value, str.ByteLengths[i]);
                    }
                    else
                    {
                        line.NeedsFixup = true;
                        var len = line.Data.Count;
                        if (len > bytesAlready) // restore state
                        {
                            line.Data.RemoveRange(bytesAlready, len - bytesAlready);
                        }
                        break; // will return to here and try again
                    }
                }
                return(true);
            }
            return(false);
        }
Esempio n. 3
0
        bool PseudoOpHandled(AsmState state, Line line)
        {
            switch (line.Opcode.Text.ToLower())
            {
            case "fcc":     // string data
                line.Address = state.Address;
                var num = ConvertStringsToNumbers(line.Operand.Text);
                WriteData(state, line, num, 1);
                break;

            case "rmb":     // reserve bytes
                line.Address = state.Address;
                var szText = line?.Operand?.Text ?? "";
                if (ParseHex(szText, out var size))
                {
                    line.Data.AddRange(new byte[size]);
                    line.Length   = size;
                    line.Address += size;
                }
                else
                {
                    state.Output.Error($"Cannot parse 'rmb' directive size {szText}");
                }
                break;

            case "fcb":     // byte data
                line.Address = state.Address;
                WriteData(state, line, line.Operand.Text, 1);
                break;

            case "fdb":     // double byte data
                line.Address = state.Address;
                WriteData(state, line, line.Operand.Text, 2);
                break;

            case "end":     // end of assembly
                line.Address = state.Address;
                line.Length  = 0;
                break;

            default:
                return(false);
            }
            return(true);
        }
Esempio n. 4
0
        // write fdb or fcb data
        void WriteData(AsmState state, Line line, string text, int itemLength)
        {
            var items = text.Split(',').Select(t => t.Trim()).ToList();

            line.Length = itemLength * items.Count;
            foreach (var item in items)
            {
                if (Evaluator.Evaluate(state, line, item, out int value))
                {
                    line.AddValue(value, itemLength);
                }
                else
                {
                    line.Data.Clear();
                    line.NeedsFixup = true;
                    break;
                }
            }
        }
Esempio n. 5
0
        bool DirectiveHandled(AsmState state, Line line)
        {
            int value;

            switch (line.Opcode.Text.ToLower())
            {
            case ".setdp":     // set direct page
                line.Address = state.Address;
                line.Length  = 0;
                if (Evaluator.Evaluate(state, line, line.Operand.Text, out value))
                {
                    state.dpRegister = value;     // todo - move to CPU class
                }
                else
                {
                    Error(line, line.Operand, "Cannot evaluate DP");
                }
                break;

            case ".rom":     // add rom definition
                line.Address = state.Address;
                line.Length  = 0;
                var fields = line.Operand.Text.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                             .Select(r => r.Trim().ToLower())
                             .ToList();
                if (fields.Count == 4 &&
                    Int32.TryParse(fields[1], out var size) &&
                    Int32.TryParse(fields[3],
                                   NumberStyles.AllowHexSpecifier | NumberStyles.HexNumber, CultureInfo.InvariantCulture,
                                   out var offset))

                {
                    var filename = fields[0];
                    var sha1     = fields[2];
                    state.RomDefinitions.Add(new AsmState.RomDef(filename, size, offset, sha1));
                }
                else
                {
                    Error(line, line.Operand, "Cannot parse .ROM directive.");
                }
                break;

            case ".cpu":     // set CPU type todo
            case ".meta":    // simple comment
                line.Address = state.Address;
                line.Length  = 0;
                break;

            case "org":
            case ".org":     // set address
                line.Address = state.Address;
                line.Length  = 0;
                if (Evaluator.Evaluate(state, line, line.Operand.Text, out value))
                {
                    state.Address = value;
                }
                else
                {
                    Error(line, line.Operand, "Cannot evaluate address");
                }
                break;

            default:
                return(false);
            }
            return(true);
        }
Esempio n. 6
0
        /// <summary>
        /// Assemble the code.
        /// Return true on no errors, else false
        /// Inspect the State property to see returned items
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="textOut"></param>
        /// <returns></returns>
        public bool Assemble(string filename, TextWriter textOut)
        {
            State        = new AsmState();
            State.Output = new Output(textOut);

            State.Output.Info("");
            State.Output.Info("");
            State.Output.Info($"Assembling file {filename}");

            if (!File.Exists(filename))
            {
                State.Output.Error($"File {filename} does not exist.");
                return(false);
            }

            State.Lines = Tokenizer.GetLines(File.ReadLines(filename), State.Output);

            // determine CPU
            foreach (var line in State.Lines)
            {
                if (line?.Opcode?.Text.ToLower() == ".cpu")
                {
                    State.Cpu = MakeCpu(line?.Operand?.Text, State.Output);
                }
            }
            if (State.Cpu == null)
            {
                State.Output.Info("CPU not detected, assuming 6809. Use '.cpu' directive to set.");
                State.Cpu = new Cpu6809(false);
                State.Cpu.Initialize(State.Output);
            }



            // clean all opcodes
            foreach (var line in State.Lines)
            {
                if (line.Opcode != null)
                {
                    line.Opcode.Text = State.Cpu.FixupMnemonic(line);
                }
            }

            if (State.Lines == null)
            {
                return(false);
            }
            State.Output.Info($"{State.Lines.Count} lines tokenized.");

            // handle #ifdef, #undef, etc
            Preprocess();

            //foreach (var line in lines)
            //    WriteLine(line.ToString());

            // get structs, fill in sizes, validate
            if (!MakeStructs())
            {
                return(false);
            }

            State.Output.Info($"{State.Symbols.GetStructs().Count} structs degrizzled.");

//            foreach (var s in structs)
//                WriteLine($"Struct {s}");

            var labelLines = State.Lines.Where(d => d.Label != null);

            foreach (var labelLine in labelLines)
            {
                State.Symbols.AddSymbol(new Label(labelLine), State.Output);
            }

            State.Output.Info($"{State.Symbols.Count} labels cryoambulated.");

            if (!Assemble())
            {
                return(false);
            }

            return(CreateRom());
        }