OpenCores
URL https://opencores.org/ocsvn/lxp32/lxp32/trunk

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [tools/] [src/] [lxp32asm/] [assembler.cpp] - Diff between revs 6 and 9

Show entire file | Details | Blame | View Log

Rev 6 Rev 9
Line 29... Line 29...
        _line=0;
        _line=0;
        _state=Initial;
        _state=Initial;
        _currentFileName=filename;
        _currentFileName=filename;
        processFileRecursive(filename);
        processFileRecursive(filename);
 
 
 
        if(!_currentLabels.empty())
 
                throw std::runtime_error("Symbol definition must be followed by an instruction or data definition statement");
 
 
 
        if(!_sectionEnabled.empty())
 
                throw std::runtime_error("#endif expected");
 
 
// Examine symbol table
// Examine symbol table
        for(auto const &sym: _obj.symbols()) {
        for(auto const &sym: _obj.symbols()) {
                if(sym.second.type==LinkableObject::Unknown&&!sym.second.refs.empty()) {
                if(sym.second.type==LinkableObject::Unknown&&!sym.second.refs.empty()) {
                        std::ostringstream msg;
                        std::ostringstream msg;
                        msg<<"Undefined symbol \""+sym.first+"\"";
                        msg<<"Undefined symbol \""+sym.first+"\"";
Line 69... Line 75...
        if(_state!=Initial) throw std::runtime_error("Unexpected end of file");
        if(_state!=Initial) throw std::runtime_error("Unexpected end of file");
 
 
        _line=savedLine;
        _line=savedLine;
        _state=savedState;
        _state=savedState;
        _currentFileName=savedFileName;
        _currentFileName=savedFileName;
 
 
        if(!_currentLabels.empty())
 
                throw std::runtime_error("Symbol definition must be followed by an instruction or data definition statement");
 
}
}
 
 
void Assembler::addIncludeSearchDir(const std::string &dir) {
void Assembler::addIncludeSearchDir(const std::string &dir) {
        auto ndir=Utils::normalizeSeparators(dir);
        auto ndir=Utils::normalizeSeparators(dir);
        if(!ndir.empty()&&ndir.back()!='/') ndir.push_back('/');
        if(!ndir.empty()&&ndir.back()!='/') ndir.push_back('/');
Line 205... Line 208...
void Assembler::expand(TokenList &list) {
void Assembler::expand(TokenList &list) {
        TokenList newlist;
        TokenList newlist;
// Perform macro substitution
// Perform macro substitution
        for(auto &token: list) {
        for(auto &token: list) {
                auto it=_macros.find(token);
                auto it=_macros.find(token);
// Note: we don't expand a macro identifier in the #define statement
                bool substitute=false;
// since that would lead to counter-intuitive results
                if(it!=_macros.end()) {
                if(it==_macros.end()||
                        substitute=true;
                        (newlist.size()==1&&newlist[0]=="#define")||
// Don't substitute macros for a second token in certain directives
                        (newlist.size()==3&&newlist[1]==":"&&newlist[2]=="#define"))
                        if(newlist.size()==1) {
                                newlist.push_back(std::move(token));
                                if(newlist[0]=="#define") substitute=false;
                else for(auto const &replace: it->second) newlist.push_back(replace);
                                else if(newlist[0]=="#ifdef") substitute=false;
 
                                else if(newlist[0]=="#ifndef") substitute=false;
 
                        }
 
                        else if(newlist.size()==3&&newlist[1]==":") {
 
                                if(newlist[2]=="#define") substitute=false;
 
                                else if(newlist[2]=="#ifdef") substitute=false;
 
                                else if(newlist[2]=="#ifndef") substitute=false;
 
                        }
 
                }
 
 
 
                if(substitute) {
 
                        for(auto const &replace: it->second) newlist.push_back(replace);
 
                }
 
                else newlist.push_back(std::move(token));
        }
        }
        list=std::move(newlist);
        list=std::move(newlist);
}
}
 
 
void Assembler::elaborate(TokenList &list) {
void Assembler::elaborate(TokenList &list) {
Line 223... Line 239...
 
 
// Process label (if present)
// Process label (if present)
        if(list.size()>=2&&list[1]==":") {
        if(list.size()>=2&&list[1]==":") {
                if(!validateIdentifier(list[0]))
                if(!validateIdentifier(list[0]))
                        throw std::runtime_error("Ill-formed identifier: \""+list[0]+"\"");
                        throw std::runtime_error("Ill-formed identifier: \""+list[0]+"\"");
                _currentLabels.push_back(std::move(list[0]));
                if(isSectionEnabled()) _currentLabels.push_back(std::move(list[0]));
                list.erase(list.begin(),list.begin()+2);
                list.erase(list.begin(),list.begin()+2);
        }
        }
 
 
        if(list.empty()) return;
        if(list.empty()) return;
 
 
 
// If the section is disabled, we look only for #ifdef, #ifndef, #else or #endif
 
        if(!isSectionEnabled()&&list[0]!="#ifdef"&&list[0]!="#ifndef"&&
 
                list[0]!="#else"&&list[0]!="#endif") return;
 
 
// Process statement itself
// Process statement itself
        if(list[0][0]=='#') elaborateDirective(list);
        if(list[0][0]=='#') elaborateDirective(list);
        else {
        else {
                LinkableObject::Word rva;
                LinkableObject::Word rva;
                if(list[0][0]=='.') rva=elaborateDataDefinition(list);
                if(list[0][0]=='.') rva=elaborateDataDefinition(list);
Line 247... Line 267...
 
 
void Assembler::elaborateDirective(TokenList &list) {
void Assembler::elaborateDirective(TokenList &list) {
        assert(!list.empty());
        assert(!list.empty());
 
 
        if(list[0]=="#define") {
        if(list[0]=="#define") {
                if(list.size()<3)
                if(list.size()<2)
                        throw std::runtime_error("Wrong number of tokens in the directive");
                        throw std::runtime_error("Wrong number of tokens in the directive");
                if(_macros.find(list[1])!=_macros.end())
                if(_macros.find(list[1])!=_macros.end())
                        throw std::runtime_error("Macro \""+list[1]+"\" has been already defined");
                        throw std::runtime_error("Macro \""+list[1]+"\" has been already defined");
                if(!validateIdentifier(list[1]))
                if(!validateIdentifier(list[1]))
                        throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                        throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                _macros.emplace(list[1],TokenList(list.begin()+2,list.end()));
                _macros.emplace(list[1],TokenList(list.begin()+2,list.end()));
        }
        }
        else if(list[0]=="#export") {
        else if(list[0]=="#export") {
                if(list.size()!=2) std::runtime_error("Wrong number of tokens in the directive");
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
                if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                _exportedSymbols.push_back(list[1]);
                _exportedSymbols.push_back(list[1]);
        }
        }
        else if(list[0]=="#import") {
        else if(list[0]=="#import") {
                if(list.size()!=2) std::runtime_error("Wrong number of tokens in the directive");
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
                if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                if(!validateIdentifier(list[1])) throw std::runtime_error("Ill-formed identifier: \""+list[1]+"\"");
                _obj.addImportedSymbol(list[1]);
                _obj.addImportedSymbol(list[1]);
        }
        }
        else if(list[0]=="#include") {
        else if(list[0]=="#include") {
                if(list.size()!=2) std::runtime_error("Wrong number of tokens in the directive");
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
                auto filename=Utils::dequoteString(list[1]);
                auto filename=Utils::dequoteString(list[1]);
                if(Utils::isAbsolutePath(filename)) return processFileRecursive(filename);
                if(Utils::isAbsolutePath(filename)) return processFileRecursive(filename);
                else {
                else {
                        auto path=Utils::relativePath(currentFileName(),filename);
                        auto path=Utils::relativePath(currentFileName(),filename);
                        if(Utils::fileExists(path)) return processFileRecursive(path);
                        if(Utils::fileExists(path)) return processFileRecursive(path);
Line 282... Line 302...
                        }
                        }
                }
                }
                throw std::runtime_error("Cannot locate include file \""+filename+"\"");
                throw std::runtime_error("Cannot locate include file \""+filename+"\"");
        }
        }
        else if(list[0]=="#message") {
        else if(list[0]=="#message") {
                if(list.size()!=2) std::runtime_error("Wrong number of tokens in the directive");
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
                auto msg=Utils::dequoteString(list[1]);
                auto msg=Utils::dequoteString(list[1]);
                std::cout<<currentFileName()<<":"<<line()<<": "<<msg<<std::endl;
                std::cout<<currentFileName()<<":"<<line()<<": "<<msg<<std::endl;
        }
        }
 
        else if(list[0]=="#error") {
 
                if(list.size()<2) throw std::runtime_error("#error directive encountered");
 
                auto msg=Utils::dequoteString(list[1]);
 
                throw std::runtime_error(msg);
 
        }
 
        else if(list[0]=="#ifdef") {
 
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
 
                if(_macros.find(list[1])!=_macros.end()) _sectionEnabled.push_back(true);
 
                else _sectionEnabled.push_back(false);
 
        }
 
        else if(list[0]=="#ifndef") {
 
                if(list.size()!=2) throw std::runtime_error("Wrong number of tokens in the directive");
 
                if(_macros.find(list[1])!=_macros.end()) _sectionEnabled.push_back(false);
 
                else _sectionEnabled.push_back(true);
 
        }
 
        else if(list[0]=="#else") {
 
                if(list.size()!=1) throw std::runtime_error("Wrong number of tokens in the directive");
 
                if(_sectionEnabled.empty()) throw std::runtime_error("Unexpected #else");
 
                _sectionEnabled.back()=!_sectionEnabled.back();
 
        }
 
        else if(list[0]=="#endif") {
 
                if(list.size()!=1) throw std::runtime_error("Wrong number of tokens in the directive");
 
                if(_sectionEnabled.empty()) throw std::runtime_error("Unexpected #endif");
 
                _sectionEnabled.pop_back();
 
        }
        else throw std::runtime_error("Unrecognized directive: \""+list[0]+"\"");
        else throw std::runtime_error("Unrecognized directive: \""+list[0]+"\"");
}
}
 
 
LinkableObject::Word Assembler::elaborateDataDefinition(TokenList &list) {
LinkableObject::Word Assembler::elaborateDataDefinition(TokenList &list) {
        assert(!list.empty());
        assert(!list.empty());
Line 390... Line 435...
        else if(list[0]=="xor") encodeXor(list);
        else if(list[0]=="xor") encodeXor(list);
        else throw std::runtime_error("Unrecognized instruction: \""+list[0]+"\"");
        else throw std::runtime_error("Unrecognized instruction: \""+list[0]+"\"");
        return rva;
        return rva;
}
}
 
 
 
bool Assembler::isSectionEnabled() const {
 
        if(_sectionEnabled.empty()) return true;
 
        bool enabled=true;
 
        for(auto b: _sectionEnabled) enabled=enabled&&b;
 
        return enabled;
 
}
 
 
bool Assembler::validateIdentifier(const std::string &str) {
bool Assembler::validateIdentifier(const std::string &str) {
/*
/*
 * Valid identifier must satisfy the following requirements:
 * Valid identifier must satisfy the following requirements:
 *  1. Must not be empty
 *  1. Must not be empty
 *  2. The first character must be either alphabetic or an underscore
 *  2. The first character must be either alphabetic or an underscore

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.