/// <summary>
        /// Generates the byte representation of an instruction from a line of assembly code.
        /// </summary>
        /// <param name="asmLine">The line to parse.</param>
        /// <param name="objFile">The object file that will be written to.</param>
        /// <param name="currAlignment">The current specified alignment of the file.</param>
        public void GenerateCodeForSegment(string fileName, LineData asmLine, BasicObjectFile objFile, int currAlignment)
        {
            string[] tokens               = asmLine.Text.Split(' ', '\t');
            string[] fixedTokens          = ParserCommon.GetTrimmedTokenArray(tokens).ToArray();
            bool     foundDataDeclaration = false;
            int      dataDeclarationIdx   = 0;

            for (int i = 0; i < fixedTokens.Length && !foundDataDeclaration; ++i)
            {
                if (ParserCommon.IsDataDeclaration(fixedTokens[i]))
                {
                    foundDataDeclaration = true;
                    dataDeclarationIdx   = i;
                }
            }

            // we found a data declaration; make sure that there's at least one value following it.
            if (foundDataDeclaration)
            {
                if (dataDeclarationIdx + 1 < fixedTokens.Length)
                {
                    // if it is a trivial type, use our precomputed map to get the size.
                    if (ParserCommon.IsTrivialDataType(fixedTokens[dataDeclarationIdx]))
                    {
                        // determine before writing the next data element if we need to add padding.
                        int paddingSize = ParserCommon.GetNumPaddingBytes(m_NumBytesLaidOut, currAlignment);
                        int dataSize    = ParserCommon.DetermineTrivialDataSize(fixedTokens[dataDeclarationIdx]);
                        int numElements = ParserCommon.GetArraySize(asmLine.Text, fixedTokens[dataDeclarationIdx]);

                        if (dataSize > paddingSize)
                        {
                            // add as much padding as we need to reach the next alignment boundary.
                            for (int i = 0; i < paddingSize; ++i)
                            {
                                objFile.AddDataElement((byte)0);
                                m_NumBytesLaidOut += 1;
                            }
                        }

                        int totalReservedSize = dataSize * numElements;

                        m_NumBytesLaidOut += totalReservedSize;

                        AddTrivialDataElementsToFile(objFile, dataSize, asmLine.Text, fixedTokens[dataDeclarationIdx]);
                    }

                    // see if we can figure out the string length
                    else if (ParserCommon.IsStringDeclaration(fixedTokens[dataDeclarationIdx]))
                    {
                        int paddingSize = ParserCommon.GetNumPaddingBytes(m_NumBytesLaidOut, currAlignment);

                        // if this is a string declaration, then get the original string data
                        string dataStr  = ParserCommon.GetStringData(asmLine.Text);
                        int    dataSize = ParserCommon.DetermineNonTrivialDataLength(fixedTokens[dataDeclarationIdx], dataStr);

                        if (dataSize > paddingSize)
                        {
                            // add as much padding as we need to reach the next alignment boundary.
                            for (int i = 0; i < paddingSize; ++i)
                            {
                                objFile.AddDataElement((byte)0);
                                m_NumBytesLaidOut += 1;
                            }
                        }

                        // add the string data to the object file.
                        AddNonTrivialDataElementToObjectFile(objFile, fixedTokens[dataDeclarationIdx], dataStr);
                        m_NumBytesLaidOut += dataSize;
                    }

                    // otherwise, this must be a .space declaration. just get the size following it.
                    else
                    {
                        int dataSize    = ParserCommon.DetermineNonTrivialDataLength(fixedTokens[dataDeclarationIdx], fixedTokens[dataDeclarationIdx + 1]);
                        int paddingSize = ParserCommon.GetNumPaddingBytes(dataSize, currAlignment);

                        // fill the space and padding with zeroes.
                        for (int i = 0; i < dataSize + paddingSize; ++i)
                        {
                            objFile.AddDataElement((byte)0);
                        }

                        // we expect one token after this word.
                        // otherwise, it may be garbage that we should detect.
                        if (fixedTokens.Length > dataDeclarationIdx + 2)
                        {
                            throw new AssemblyException(asmLine.LineNum, "Unknown token \"" + fixedTokens[dataDeclarationIdx + 2] + "\" found.");
                        }
                    }
                }
                else
                {
                    throw new AssemblyException(asmLine.LineNum, "Expected data value after token " + fixedTokens[dataDeclarationIdx]);
                }
            }

            // check to see if this is just a label.
            // otherwise, it is probably garbage that we should throw.
            else if (!ParserCommon.ContainsLabel(asmLine.Text))
            {
                throw new AssemblyException(asmLine.LineNum, "Unable to ascertain data type from line " + asmLine.Text);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Parses an unlabeled line to calculate the appropriate address of the next element (if any).
        /// </summary>
        /// <param name="originalLine">The line data being parsed.</param>
        /// <param name="tokens">The string array of space-separated tokens.</param>
        /// <param name="alignment">The current alignment</param>
        /// <returns>A boolean determining if anything of use was parsed. If this is false,
        /// the line should be examined to make sure a symbol was at least parsed. Otherwise,
        /// this could indicate that garbage was on the line.</returns>
        private bool ParseUnlabeledLine(LineData originalLine, string[] tokens, int alignment)
        {
            bool foundDataDeclaration = false;
            int  dataDeclarationIdx   = 0;

            // scan it for a data size (e.g. .asciiz, .word, etc)
            for (int i = 0; i < tokens.Length && !foundDataDeclaration; ++i)
            {
                if (ParserCommon.IsDataDeclaration(tokens[i]))
                {
                    foundDataDeclaration = true;
                    dataDeclarationIdx   = i;
                }
            }

            // we found a data declaration; make sure that there's at least one value following it.
            if (foundDataDeclaration)
            {
                int dataSize = 0;
                if (dataDeclarationIdx + 1 < tokens.Length)
                {
                    // if it is a trivial type, use our precomputed map to get the size.
                    if (ParserCommon.IsTrivialDataType(tokens[dataDeclarationIdx]))
                    {
                        int paddingSize = ParserCommon.GetNumPaddingBytes(m_TotalBytesLaidOut, alignment);
                        dataSize = ParserCommon.DetermineTrivialDataSize(tokens[dataDeclarationIdx]);
                        int numElementsToStore = ParserCommon.GetArraySize(originalLine.Text, tokens[dataDeclarationIdx]);

                        if (dataSize > paddingSize)
                        {
                            // add as much padding as we need to reach the next alignment boundary.
                            for (int i = 0; i < paddingSize; ++i)
                            {
                                ++m_CurrDataAddress;
                                ++m_TotalBytesLaidOut;
                            }
                        }

                        int reservedSize = numElementsToStore * dataSize;

                        // need to fixup the address here, since we have committed to placing padding
                        // here.
                        if (m_UnresolvedSym != null)
                        {
                            m_UnresolvedSym.Address = m_CurrDataAddress;
                        }
                        m_CurrDataAddress   += reservedSize;
                        m_TotalBytesLaidOut += reservedSize;
                    }

                    // otherwise, we'd expect there to be another token after the data type.
                    // see if we can figure out the string length
                    else if (ParserCommon.IsStringDeclaration(tokens[dataDeclarationIdx]))
                    {
                        // if this is a string declaration, then get the original string data
                        string dataStr = ParserCommon.GetStringData(originalLine.Text);

                        dataSize = ParserCommon.DetermineNonTrivialDataLength(tokens[dataDeclarationIdx], dataStr);

                        int paddingSize = ParserCommon.GetNumPaddingBytes(m_TotalBytesLaidOut, alignment);

                        if (dataSize > paddingSize)
                        {
                            // add as much padding as we need to reach the next alignment boundary.
                            for (int i = 0; i < paddingSize; ++i)
                            {
                                ++m_CurrDataAddress;
                                ++m_TotalBytesLaidOut;
                            }
                        }

                        // need to fixup the address here, since we have committed to placing padding
                        // here.
                        if (m_UnresolvedSym != null)
                        {
                            m_UnresolvedSym.Address = m_CurrDataAddress;
                        }

                        m_CurrDataAddress   += dataSize;
                        m_TotalBytesLaidOut += dataSize;
                    }

                    // otherwise, this must be a .space declaration. just get the size following it.
                    else
                    {
                        int paddingSize = ParserCommon.GetNumPaddingBytes(m_TotalBytesLaidOut, alignment);
                        dataSize = ParserCommon.DetermineNonTrivialDataLength(tokens[dataDeclarationIdx], tokens[dataDeclarationIdx + 1]);
                        if (dataSize > paddingSize)
                        {
                            // add as much padding as we need to reach the next alignment boundary.
                            for (int i = 0; i < paddingSize; ++i)
                            {
                                ++m_CurrDataAddress;
                                ++m_TotalBytesLaidOut;
                            }
                        }

                        // need to fixup the address here, since we have committed to placing padding
                        // here.
                        // need to really clean this logic up.
                        if (m_UnresolvedSym != null)
                        {
                            m_UnresolvedSym.Address = m_CurrDataAddress;
                        }

                        m_CurrDataAddress   += dataSize;
                        m_TotalBytesLaidOut += dataSize;
                    }
                }
                else
                {
                    throw new AssemblyException(originalLine.LineNum, "Expected data value after token " + tokens[dataDeclarationIdx]);
                }

                if (m_UnresolvedSym != null)
                {
                    m_UnresolvedSym.Size = dataSize;
                    m_UnresolvedSym      = null;
                }
            }

            return(foundDataDeclaration);
        }