Пример #1
0
 public Literal(UInt value) : base(value != null?value.Size:0)
 {
     if (value == null)
     {
         throw new InvalidOperationException("literals cannot have null values");
     }
     Value = value;
 }
Пример #2
0
 public Constant(string name, UInt value) : base(name, value != null?value.Size:0)
 {
     if (value == null)
     {
         throw new InvalidOperationException("constants cannot have null values");
     }
     Value = value;
 }
Пример #3
0
 public Constant(string name, UInt value):base(name, value!=null?value.Size:0)
 {
    if (value==null) throw new InvalidOperationException("constants cannot have null values");
    Value = value;
 }
Пример #4
0
 public Literal(UInt value):base(value!=null?value.Size:0)
 {
    if (value == null) throw new InvalidOperationException("literals cannot have null values");
    Value = value;
 }
Пример #5
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());
            }
        }
Пример #6
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();
        }