Ejemplo n.º 1
0
        protected void Write16(ushort address, ushort value)
        {
            //convert native ushort to big endian format in ram
            var bytes = EndianUtils.FromNative(value);

            _cpu.Ram[address] = bytes[0];               //msb
            _cpu.Ram[(ushort)(address + 1)] = bytes[1]; //lsb;
        }
Ejemplo n.º 2
0
        public static ROF Assemble(FileAstNode file)
        {
            /*
             *  Rules:
             *
             *  .ORG and .END required
             *  file must start with EQUs or ORG
             *  EQUs must be before ORG
             *  EQUs must have labels
             *  file must end with END
             *  reserve statements must come between ORG and END (ORG doesn't mean the start of code, only the image)
             *
             *  address labels are ushort
             *  constant labels (EQU) may be bytes or ushorts
             *
             *
             */

            //cache instructions
            Dictionary <string, Instruction> instructions = new Dictionary <string, Instruction>();

            foreach (var instruction in Instruction.GetInstructions())
            {
                instructions.Add(instruction.Encode(), instruction);
            }

            byte[] image = new byte[0xFFFF + 1];

            Dictionary <string, Label> labels = new Dictionary <string, Label>();

            ushort?start = null;
            ushort?code  = null;
            ushort?end   = null;
            ushort here  = 0;


            foreach (var statement in file.ChildNodes)
            {
                if (end != null)
                {
                    throw new AssembleException("END must be last statement in file", statement.SourceSpan);
                }

                LabelAstNode label = statement[typeof(LabelAstNode)] as LabelAstNode;

                if (statement is DirectiveAstNode)
                {
                    IDirective directive = statement[typeof(IDirective)] as IDirective;

                    if (directive is DeclarationAstNode)
                    {
                        if (start != null)
                        {
                            throw new AssembleException("EQU must be before ORG", statement.SourceSpan);
                        }

                        if (label == null)
                        {
                            throw new AssembleException("EQU must have a label", statement.SourceSpan);
                        }

                        IntegerAstNode integer = directive[typeof(IntegerAstNode)] as IntegerAstNode;

                        labels.Add(label.Value, new Label(LabelType.Constant, integer.Value));
                    }
                    else
                    {
                        if (directive is OriginAstNode)
                        {
                            start = GetIntegerRef16(statement, (OriginAstNode)directive, labels);
                        }
                        else
                        {
                            if (start == null)
                            {
                                throw new AssembleException("ORG must be defined first", statement.SourceSpan);
                            }

                            if (directive is ReservationAstNodeBase)
                            {
                                if (label != null)
                                {
                                    labels.Add(label.Value, new Label(LabelType.Address, here + start.Value));
                                }

                                int byteSize = ((ReservationAstNodeBase)directive).Value;

                                if (directive is ReservationInitAstNode)
                                {
                                    var integers = ((AstNodeBase)directive).Find(typeof(IntegerAstNode));

                                    if (integers.Length == 0)
                                    {
                                        here += (ushort)byteSize;
                                    }
                                    else
                                    {
                                        foreach (var integer in integers)
                                        {
                                            var i = (IntegerAstNode)integer;

                                            if (byteSize == 1)
                                            {
                                                if (i.Value is ushort)
                                                {
                                                    throw new AssembleException("can't use 16 bit constants in .byte reservation", statement.SourceSpan);
                                                }

                                                image[here] = (byte)i.Value;
                                            }
                                            else if (byteSize == 2)
                                            {
                                                if (i.Value is uint)
                                                {
                                                    throw new AssembleException("can't use 32 bit constants in .2byte reservation", statement.SourceSpan);
                                                }

                                                var bytes = EndianUtils.FromNative(Convert.ToUInt16(i.Value));

                                                image[here]     = bytes[0]; //msb;
                                                image[here + 1] = bytes[1]; //lsb;
                                            }
                                            else if (byteSize == 4)
                                            {
                                                var bytes = EndianUtils.FromNative(Convert.ToUInt32(i.Value));

                                                image[here]     = bytes[0]; //msb;
                                                image[here + 1] = bytes[1];
                                                image[here + 2] = bytes[2];
                                                image[here + 3] = bytes[3]; //lsb;
                                            }
                                            else
                                            {
                                                throw new NotImplementedException("bad byte size");
                                            }

                                            here += (ushort)byteSize;
                                        }
                                    }
                                }
                                else if (directive is ReservationStarAstNode)
                                {
                                    uint bytes = GetIntegerRef32(statement, (AstNode)directive, labels);
                                    //TODO what if this overflows?
                                    here += (ushort)(bytes * byteSize);
                                }
                                else
                                {
                                    throw new InvalidOperationException("bad reservation directive");
                                }
                            }
                            else if (directive is EndAstNode)
                            {
                                end = (ushort?)(start + here - 1);
                            }
                        }
                    }
                }
                else if (statement is InstructionAstNode)
                {
                    if (label != null)
                    {
                        labels.Add(label.Value, new Label(LabelType.Address, here + start));
                    }

                    if (code == null)
                    {
                        code = (ushort)(here + start);
                    }

                    MnemonicAstNode mnemonic           = statement[typeof(MnemonicAstNode)] as MnemonicAstNode;
                    IOperand        operand            = statement[typeof(IOperand)] as IOperand;
                    string          encodedInstruction = EncodeInstruction(mnemonic.Value, operand);
                    Instruction     instruction        = instructions[encodedInstruction];

                    image[here] = instruction.OpCode;

                    if (instruction.Width == 2)
                    {
                        image[here + 1] = GetIntegerRef8(statement, (AstNodeBase)operand, labels);
                    }
                    else if (instruction.Width == 3)
                    {
                        ushort value = GetIntegerRef16(statement, (AstNodeBase)operand, labels);
                        var    bytes = EndianUtils.FromNative(value);
                        image[here + 1] = bytes[0]; //msb;
                        image[here + 2] = bytes[1]; //lsb;
                    }

                    here += instruction.Width;
                }
                else
                {
                    throw new AssembleException("Line must be a statement.", statement.SourceSpan);
                }
            }

            if (end == null)
            {
                throw new InvalidOperationException("file must have END");
            }

            return(new ROF {
                Start = start.Value, Code = code, End = end.Value, Image = image.ToArray()
            });
        }