Пример #1
0
        public static void Assemble(string[] lines, IOutput output)
        {
            Beboputer.Bebop.Reset();

            bool errors = false;

            for (int i = 0; i < lines.Length; ++i)
            {
                //FOO:   .EQU    $FF   # this is a comment
                //FOO:   .BYTE   $FF,$FF,$FF   # this is a comment
                //FOO:   LDA     $FF   # this is a comment

                //{LABEL} {DIR|INS} {UINT|OPERAND} {COMMENT}

                try
                {
                    string[] parts = lines[i].Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
                    int      p     = 0;

                    string label   = null;
                    string comment = null;
                    Line   line    = null;

                    if (parts.Length > 0 && parts[0].Length > 0)
                    {
                        //label
                        if (char.IsLetter(parts[p][0]) || parts[p][0] == '_')
                        {
                            if (parts[p][parts[p].Length - 1] == ':')
                            {
                                label = parts[p].Substring(0, parts[p].Length - 1);
                                ++p;
                            }
                        }

                        if (parts[p][0] == '.') //directive
                        {
                            if (parts[p].Length == 1)
                            {
                                throw new InvalidOperationException("can't parse line " + i + " {" + lines[i] + "}");
                            }
                            string dir = parts[p].Substring(1, parts[p].Length - 1);

                            if (Beboputer.Directives.ContainsKey(dir))
                            {
                                ++p;

                                string parm = null;

                                if (p < parts.Length)
                                {
                                    if (parts[p][0] != '#')
                                    {
                                        parm = parts[p];
                                        ++p;
                                    }
                                }

                                Directive directive = (Directive)Activator.CreateInstance(Beboputer.Directives[dir]);

                                if (parm != null)
                                {
                                    directive.Value = UInt.Parse(parm);
                                }

                                line = directive;
                            }
                            else
                            {
                                throw new InvalidOperationException("unknown directive line " + i + " {" + lines[i] + "}");
                            }
                        }
                        else if (Beboputer.Instructions.ContainsKey(parts[p])) //instruction
                        {
                            string ins = parts[p];
                            ++p;

                            string parm = null;

                            if (p < parts.Length)
                            {
                                if (parts[p][0] != '#')
                                {
                                    parm = parts[p];
                                    ++p;
                                }
                            }

                            Instruction instruction = (Instruction)Activator.CreateInstance(Beboputer.Instructions[ins]);

                            if (parm != null)
                            {
                                instruction.Operand = Operand.Parse(parm);
                            }

                            line = instruction;
                        }
                        else if (parts[p][0] == '#') //comment only line
                        {
                            //this is okay
                        }
                        else
                        {
                            throw new InvalidOperationException("unknown instruction line " + i + " {" + lines[i] + "}");
                        }

                        if (p < parts.Length)
                        {
                            if (parts[p][0] == '#')
                            {
                                parts[p] = parts[p].Substring(1, parts[p].Length - 1);
                                comment  = "";

                                for (int j = p; j < (parts.Length); ++j)
                                {
                                    if (comment != "")
                                    {
                                        comment += " ";
                                    }
                                    comment += parts[j];
                                }
                            }
                            else
                            {
                                throw new InvalidOperationException("unknown syntax line " + i + " {" + lines[i] + "}");
                            }
                        }
                    }

                    if (line == null)
                    {
                        if (comment != null)
                        {
                            line = new Comment();
                        }
                        else
                        {
                            if (lines[i].Trim().Length != 0)
                            {
                                throw new InvalidOperationException("can't parse line " + i + " {" + lines[i] + "}");
                            }
                            line = new Line();
                        }
                    }

                    line.Text = lines[i];

                    if (line is Statement)
                    {
                        ((Statement)line).Label   = label;
                        ((Statement)line).Comment = comment;

                        if (label != null)
                        {
                            if (Beboputer.Bebop.Labels.ContainsKey(label))
                            {
                                throw new InvalidOperationException("label {" + label + "} already exists line " + i + " {" + lines[i] + "}");
                            }
                            Beboputer.Bebop.Labels.Add(label, (Statement)line);
                        }
                    }
                    else
                    {
                        if (label != null)
                        {
                            throw new InvalidOperationException("label invalid for line " + i + " {" + lines[i] + "}");
                        }
                    }

                    Beboputer.Bebop.Lines.Add(line);

                    output.Out(i + ":\t" + line.ToString());
                }
                catch (Exception ex)
                {
                    errors = true;
                    output.Out("ERROR: " + i + ":\t" + ex.Message);
                }
            }

            //load
            ushort address = 0;

            foreach (Line line in Beboputer.Bebop.Lines)
            {
                if (line is ORG)
                {
                    address = ((U16)((ORG)line).Value).Read();
                }
                else if (line is Instruction)
                {
                    Instruction ins = (Instruction)line;

                    byte opcode;
                    if (Beboputer.Opcodes.ContainsKey(Instruction.GetOpcodeKey(ins.Mnemonic, ins.AddressingMode)))
                    {
                        opcode = Beboputer.Opcodes[Instruction.GetOpcodeKey(ins.Mnemonic, ins.AddressingMode)];
                    }
                    else
                    {
                        throw new InvalidOperationException("no opcode for {" + ins.ToString() + "}");
                    }

                    Beboputer.Bebop.RAM.Write(address, opcode);
                    ++address;

                    if (ins.Operand != null)
                    {
                        if (ins.Operand.Value is Literal)
                        {
                            Literal l = (Literal)ins.Operand.Value;

                            if (l.Value is U8)
                            {
                                Beboputer.Bebop.RAM.Write(address, ((U8)l.Value).Read());
                                ++address;
                            }
                            else if (l.Value is U16)
                            {
                                ushort v = ((U16)l.Value).Read();
                                Beboputer.Bebop.RAM.Write(address, (byte)((v & 0xFF00) >> 8));
                                ++address;
                                Beboputer.Bebop.RAM.Write(address, (byte)(v & 0xFF));
                                ++address;
                            }
                        }
                        else
                        {
                            throw new NotImplementedException("not yet");
                        }
                    }
                }
            }

            //refresh windows
            Beboputer.Bebop.Load();
        }
Пример #2
0
      public static Operand Parse(string text)
      {
         //v=LABEL | ($ff | 255 | %10101010) | ($ffff | 64000 | %1010101010101010

         //v
         //[v]
         //[[v]]
         //[v,X]
         //[[v,X]]
         //[[v],X]

         AddressingModes addressingMode = AddressingModes.Implied;

         string parsed = text;

         if (parsed != null)
         {
            bool isAddress = false;
            bool isIndirect = false;
            bool isIndexed = false;
            bool isPreIndexed = false;
            bool isPostIndexed = false;


            if (parsed[0] == '[')
            {
               if (parsed[parsed.Length - 1] != ']') throw new InvalidOperationException("can't parse {" + text + "}");

               isAddress = true;
               parsed = parsed.Substring(1, parsed.Length - 2);

               if (parsed[0] == '[')
               {

                  isIndirect = true;

                  if (parsed.Substring(parsed.Length - 3, 3) == ",X]")
                  {
                     isPreIndexed = true;
                     parsed = parsed.Substring(1, parsed.Length - 4);
                  }
                  else if (parsed.Substring(parsed.Length - 3, 3) == "],X")
                  {
                     isPostIndexed = true;
                     parsed = parsed.Substring(1, parsed.Length - 4);
                  }
                  else if (parsed[parsed.Length - 1] == ']')
                  {
                     parsed = parsed.Substring(1, parsed.Length - 2);
                  }
                  else
                  {
                     throw new InvalidOperationException("can't parse {" + text + "}");
                  }


               }

               if (parsed.Substring(parsed.Length - 2, 2) == ",X")
               {
                  isIndexed = true;
                  parsed = parsed.Substring(0, parsed.Length - 2);
               }

            }

            if (parsed.Length == 0) throw new InvalidOperationException("can't parse {" + text + "}");

            //parse label or literal
            UInt ui = null;
            string name = null;

            if (char.IsLetter(parsed[0])||parsed[0]=='_') 
            {
               if (!parsed.All(c => char.IsLetterOrDigit(c) || c=='_')) throw new InvalidOperationException("can't parse {" + text + "}");
               name = parsed;
            }
            else
            {
               ui = UInt.Parse(parsed);

               if (isAddress && ui is U8)
               {
                  ui = new U16(((U8)ui).Read());
               }

            }


            if (isAddress)
            {
               //address literal or pointer (label)
               if (isIndirect)
               {
                  if (isPreIndexed) addressingMode = AddressingModes.IndirectPreIndexed;
                  else if (isPostIndexed) addressingMode = AddressingModes.IndirectPostIndexed;
                  else addressingMode = AddressingModes.Indirect;
               }
               else 
               {
                  if (isIndexed)
                  {
                     addressingMode = AddressingModes.Indexed;
                  }
                  else
                  {
                     addressingMode = AddressingModes.Absolute;
                  }
               }

               Value value = null;

               if (ui!=null)
               {
                  value = new Literal(ui);
               }
               else
               {
                  value=new Pointer(name);
               }

               return new Operand(value, addressingMode);

            }
            else
            {
               //immediate literal or constant (label)
               if (ui!=null)
               {
                  if (ui is U8)
                  {
                     addressingMode = AddressingModes.Immediate;
                  }
                  else if (ui is U16)
                  {
                     addressingMode = AddressingModes.BigImmediate;
                  }
                  else
                  {
                     throw new NotSupportedException("only U8 and U16 supported");
                  }

                  return new Operand(new Literal(ui), addressingMode);
               }
               else
               {
                  //how to tell if a constant label is 8 or 16?
                  //TODO: look up .EQU in symbol table
                  return new Operand(new Constant(name,null), addressingMode);
               }
            }

         }
         else
         {
            //implied
            return new Operand();

         }

      }