diff options
| author | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2023-12-31 09:42:34 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2023-12-31 09:42:34 +0100 |
| commit | 9dabe3339883ff78463372fc074213d018d73080 (patch) | |
| tree | 61fc5df42638c1ffcb83dd5084a83ddd68ce6a37 /CompilerDriver | |
| parent | 9bea6c59da8934bb7144be684f7b234978877047 (diff) | |
[masm/ld] Major improvements done to the assembler.
[cc] reinstated the previous C compiler engine.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'CompilerDriver')
| -rw-r--r-- | CompilerDriver/cc.cxx | 809 | ||||
| -rw-r--r-- | CompilerDriver/ld.cxx | 15 | ||||
| -rw-r--r-- | CompilerDriver/masm.cxx | 210 |
3 files changed, 958 insertions, 76 deletions
diff --git a/CompilerDriver/cc.cxx b/CompilerDriver/cc.cxx index 46bcfeb..23efbd7 100644 --- a/CompilerDriver/cc.cxx +++ b/CompilerDriver/cc.cxx @@ -219,7 +219,814 @@ namespace detail void CompilerBackendClang::Compile(const char* text, const char* file) { - +std::string _text = text; + + auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); + bool type_found = false; + bool function_found = false; + + // start parsing + for (size_t text_index = 0; text_index < _text.size(); ++text_index) + { + uuid_t out{0}; + + uuid_generate_random(out); + detail::number_type time_off = (UInt64)out; + + if (!type_found) + { + auto substr = _text.substr(text_index); + std::string match_type; + + for (size_t y = 0; y < substr.size(); ++y) + { + if (substr[y] == ' ') + { + while (match_type.find(' ') != std::string::npos) { + match_type.erase(match_type.find(' ')); + } + + for (auto& clType : kCompilerTypes) + { + if (clType.fName == match_type) + { + match_type.clear(); + + std::string buf; + + buf += clType.fValue; + buf += ' '; + + if (clType.fName == "struct" || + clType.fName == "union") + { + for (size_t a = y + 1; a < substr.size(); a++) + { + if (substr[a] == ' ') + { + break; + } + + if (substr[a] == '\n') + break; + + buf += substr[a]; + } + } + + if (substr.find('=') != std::string::npos) + { + break; + } + + if (_text.find('(') != std::string::npos) + { + syntax_tree.fUserValue = buf; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + + type_found = true; + break; + } + } + + break; + } + + match_type += substr[y]; + } + } + + if (_text[text_index] == '{') + { + if (kInStruct) + { + continue; + } + + kInBraces = true; + ++kBracesCount; + + if (kOnWhileLoop || + kOnForLoop) + { + syntax_tree.fUserValue = "void __export .text _L"; + syntax_tree.fUserValue += std::to_string(kBracesCount) + "_" + std::to_string(time_off.raw); + syntax_tree.fUserValue += "\nbegin"; + } + else + { + syntax_tree.fUserValue = "begin\n"; + syntax_tree.fUserValue += kAddIfAnyBegin; + } + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + + // return keyword handler + if (_text[text_index] == 'r') + { + std::string return_keyword; + return_keyword += "return"; + + std::size_t index = 0UL; + + std::string value; + + for (size_t return_index = text_index; return_index < _text.size(); ++return_index) + { + if (_text[return_index] != return_keyword[index]) + { + for (size_t value_index = return_index; value_index < _text.size(); ++value_index) + { + if (_text[value_index] == ';') + break; + + value += _text[value_index]; + } + + break; + } + + ++index; + } + + if (index == return_keyword.size()) + { + if (!value.empty()) + { + if (value.find('(') != std::string::npos) + { + value.erase(value.find('(')); + } + + if (!isdigit(value[value.find('(') + 2])) + { + std::string tmp = value; + + value.clear(); + value += " __import"; + value += tmp; + } + + syntax_tree.fUserValue = "\tldw r31, "; + + // make it pretty. + if (value.find('\t') != std::string::npos) + value.erase(value.find('\t'), 1); + + syntax_tree.fUserValue += value + "\n"; + } + + syntax_tree.fUserValue += "\tjlr r31"; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + break; + } + } + + if (_text[text_index] == 'i' && + _text[text_index + 1] == 'f') + { + std::string format = "ldw r15, %s\nldw r16, %s2\n"; + std::string expr = format; + + if (ParserKit::find_word(_text, "==")) + { + expr += "\nbeq"; + } + + if (ParserKit::find_word(_text, "!=")) + { + expr += "\nbneq"; + } + + if (ParserKit::find_word(_text, ">=")) + { + expr += "\nbge"; + } + else if (ParserKit::find_word(_text, ">")) + { + expr += "\nbg"; + } + + if (ParserKit::find_word(_text, "<=")) + { + expr += "\nble"; + } + else if (ParserKit::find_word(_text, "<")) + { + expr += "\nbl"; + } + + std::string substr = expr; + + std::string buf; + + for (size_t text_index_2 = (_text.find("if") + std::string("if").size()); text_index_2 < _text.size(); ++text_index_2) + { + if (_text[text_index_2] == ';') + { + buf.clear(); + + for (size_t text_index_3 = text_index_2 + 1; text_index_3 < _text.size(); text_index_3++) + { + if (_text[text_index_3] == '{') + continue; + + if (_text[text_index_3] == '}') + continue; + + if (_text[text_index_3] == ' ') + continue; + + if (_text[text_index_3] == '=') + continue; + + if (_text[text_index_3] == '<' && + _text[text_index_3+1] == '=' || + _text[text_index_3] == '=' && + _text[text_index_3+1] == '=' || + _text[text_index_3] == '>' && + _text[text_index_3+1] == '=' || + _text[text_index_3] == '>' || + _text[text_index_3] == '<' && + _text[text_index_3+1] == '=' || + _text[text_index_3] == '!') + { + buf += ", "; + continue; + } + else if (_text[text_index_3] == '=') + { + continue; + } + + buf += _text[text_index_3]; + } + + break; + } + + if (_text[text_index_2] == '{') + continue; + + if (_text[text_index_2] == '}') + continue; + + if (_text[text_index_2] == '<' && + _text[text_index_2+1] == '=' || + _text[text_index_2] == '=' && + _text[text_index_2+1] == '=' || + _text[text_index_2] == '>' && + _text[text_index_2+1] == '=' || + _text[text_index_2] == '>' || + _text[text_index_2] == '<' && + _text[text_index_2+1] == '=' || + _text[text_index_2] == '!') + { + buf += ", "; + continue; + } + else if (_text[text_index_2] == '=') + { + continue; + } + + buf += _text[text_index_2]; + } + + if (buf.find(",") == std::string::npos && + buf.find("(") != std::string::npos && + buf.find(")") != std::string::npos ) + { + + std::string cond = buf.substr(buf.find("(") + 1, buf.find(")") - 1); + cond.erase(cond.find("(")); + + std::string cond2 = buf.substr(buf.find("(") + 1, buf.find(")") - 1); + cond2.erase(cond2.find(")")); + + substr.replace(substr.find("%s"), 2, cond); + substr.replace(substr.find("%s2"), 3, cond2); + + buf.replace(buf.find(cond), cond.size(), "r15"); + buf.replace(buf.find(cond2), cond2.size(), "r16"); + + substr += buf; + + syntax_tree.fUserValue = substr + "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + break; + } + else + { + continue; + } + + // dealing with pointer + if (buf.find("*") != std::string::npos) + { + buf.erase(buf.find("*"), 1); + } + + std::string cond = buf.substr(buf.find("(") + 1, buf.find(",") - 1); + cond.erase(cond.find(",")); + + std::string cond2 = buf.substr(buf.find(",") + 1, buf.find(")") - 1); + cond2.erase(cond2.find(")")); + + substr.replace(substr.find("%s"), 2, cond); + substr.replace(substr.find("%s2"), 3, cond2); + + buf.replace(buf.find(cond), cond.size(), "r15"); + buf.replace(buf.find(cond2), cond2.size(), "r16"); + + substr += buf; + + syntax_tree.fUserValue = substr + "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + break; + } + + // Parse expressions and instructions here. + // what does this mean? + // we encounter an assignment, or we reached the end of an expression. + if (_text[text_index] == '=' || + _text[text_index] == ';') + { + if (function_found) + continue; + + if (_text[text_index] == ';' && + kInStruct) + continue; + + if (_text.find("typedef ") != std::string::npos) + continue; + + if (_text[text_index] == '=' && + kInStruct) + { + continue; + } + + if (_text[text_index+1] == '=' || + _text[text_index-1] == '!' || + _text[text_index-1] == '<' || + _text[text_index-1] == '>') + { + continue; + } + + std::string substr; + + if (_text.find('=') != std::string::npos && + kInBraces) + { + if (_text.find("*") != std::string::npos) + { + if (_text.find("=") > _text.find("*")) + substr += "\tlda "; + else + substr += "\tldw "; + } + else + { + substr += "\tldw "; + } + } + else if (_text.find('=') != std::string::npos && + !kInBraces) + { + substr += "stw __export .data "; + } + + int first_encountered = 0; + + std::string str_name; + + for (size_t text_index_2 = 0; text_index_2 < _text.size(); ++text_index_2) + { + if (_text[text_index_2] == '\"') + { + ++text_index_2; + + // want to add this, so that the parser recognizes that this is a string. + substr += '"'; + + for (; text_index_2 < _text.size(); ++text_index_2) + { + if (_text[text_index_2] == '\"') + break; + + kLatestVar += _text[text_index_2]; + substr += _text[text_index_2]; + } + } + + if (_text[text_index_2] == '{' || + _text[text_index_2] == '}') + continue; + + if (_text[text_index_2] == ';') + { + break; + } + + if (_text[text_index_2] == ' ' || + _text[text_index_2] == '\t') + { + if (first_encountered != 2) + { + if (_text[text_index] != '=' && + substr.find("__export .data") == std::string::npos && + !kInStruct && + _text.find("struct") == std::string::npos && + _text.find("extern") == std::string::npos && + _text.find("union") == std::string::npos && + _text.find("typedef") == std::string::npos) + substr += "__export .data "; + } + + ++first_encountered; + + continue; + } + + if (_text[text_index_2] == '=') + { + if (!kInBraces) + { + substr.replace(substr.find("__export .data"), strlen("__export .data"), "__export .page_zero "); + } + + substr += ","; + continue; + } + + kLatestVar += _text[text_index_2]; + substr += _text[text_index_2]; + } + + for (auto& clType : kCompilerTypes) + { + if (substr.find(clType.fName) != std::string::npos) + { + if (substr.find(clType.fName) > substr.find('"')) + continue; + + substr.erase(substr.find(clType.fName), clType.fName.size()); + } + else if (substr.find(clType.fValue) != std::string::npos) + { + if (substr.find(clType.fValue) > substr.find('"')) + continue; + + if (clType.fName == "const") + continue; + + substr.erase(substr.find(clType.fValue), clType.fValue.size()); + } + } + + if (substr.find("struct") != std::string::npos) + { + substr.replace(substr.find("struct"), strlen("struct"), "ldw "); + substr += ", 0"; + } + + if (substr.find("union") != std::string::npos) + { + substr.replace(substr.find("union"), strlen("union"), "ldw "); + substr += ", 0"; + } + + if (substr.find("static") != std::string::npos) + { + substr.replace(substr.find("static"), strlen("static"), "__export .data "); + } + else if (substr.find("extern") != std::string::npos) + { + substr.replace(substr.find("extern"), strlen("extern"), "__import "); + + if (substr.find("__export .data") != std::string::npos) + substr.erase(substr.find("__export .data"), strlen("__export .data")); + } + + auto var_to_find = std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), [&](detail::CompilerType type) { + return type.fName.find(substr) != std::string::npos; + }); + + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); + + if (var_to_find == kCompilerVariables.cend()) + { + ++kRegisterCounter; + + kState.kStackFrame.push_back({ .fName = substr, .fRegister = reg }); + kCompilerVariables.push_back({ .fName = substr }); + } + + syntax_tree.fUserValue += substr; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + if (_text[text_index] == '=') + break; + } + + // function handler. + + if (_text[text_index] == '(' && + !function_found) + { + std::string substr; + std::string args_buffer; + std::string args; + + bool type_crossed = false; + + for (size_t idx = _text.find('(') + 1; idx < _text.size(); ++idx) + { + if (_text[idx] == ',') + continue; + + if (_text[idx] == ' ') + continue; + + if (_text[idx] == ')') + break; + } + + for (char substr_first_index : _text) + { + args_buffer += substr_first_index; + + if (substr_first_index == ';') + { + args_buffer = args_buffer.erase(0, args_buffer.find('(')); + args_buffer = args_buffer.erase(args_buffer.find(';'), 1); + args_buffer = args_buffer.erase(args_buffer.find(')'), 1); + args_buffer = args_buffer.erase(args_buffer.find('('), 1); + + if (!args_buffer.empty()) + args += "\tpsh "; + + while (args_buffer.find(',') != std::string::npos) + { + args_buffer.replace(args_buffer.find(','), 1, "\n\tpsh "); + } + + args += args_buffer; + args += "\n\tjlr __import "; + } + } + + for (char _text_i : _text) + { + if (_text_i == '\t' || + _text_i == ' ') + { + if (!type_crossed) + { + substr.clear(); + type_crossed = true; + } + + continue; + } + + if (_text_i == '(') + break; + + substr += _text_i; + } + + if (kInBraces) + { + syntax_tree.fUserValue = args; + + syntax_tree.fUserValue += substr; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + function_found = true; + } + else + { + syntax_tree.fUserValue.clear(); + + syntax_tree.fUserValue += "__export .text "; + + syntax_tree.fUserValue += substr; + syntax_tree.fUserValue += "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + function_found = true; + } + + kCompilerFunctions.push_back(_text); + } + + if (_text[text_index] == 's') + { + if (_text.find("struct") != text_index) + continue; + + if (_text.find(";") == std::string::npos) + kInStruct = true; + } + + if (_text[text_index] == 'u') + { + if (_text.find("union") != text_index) + continue; + + if (_text.find(";") == std::string::npos) + kInStruct = true; + } + + if (_text[text_index] == 'e') + { + if (_text.find("enum") != text_index) + continue; + + if (_text.find(";") == std::string::npos) + kInStruct = true; + } + + if (_text[text_index] == '-' && + _text[text_index+1] == '-') + { + _text = _text.replace(_text.find("--"), strlen("--"), ""); + + for (int _text_i = 0; _text_i < _text.size(); ++_text_i) + { + if (_text[_text_i] == '\t' || + _text[_text_i] == ' ') + _text.erase(_text_i, 1); + } + + syntax_tree.fUserValue += "dec "; + syntax_tree.fUserValue += _text; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + break; + } + + // while loop + if (_text[text_index] == 'w') + { + if (_text.find("while") == std::string::npos) + continue; + + if (_text.find("while") != text_index) + continue; + + syntax_tree.fUserValue = "jrl [r32+0x04]"; + + std::string symbol_loop = "_loop_while_"; + symbol_loop += std::to_string(time_off.raw); + symbol_loop += " "; + + syntax_tree.fUserValue = "beq "; + syntax_tree.fUserValue += kState.kStackFrame[kState.kStackFrame.size() - 2].fRegister; + syntax_tree.fUserValue += ","; + syntax_tree.fUserValue += kState.kStackFrame[kState.kStackFrame.size() - 1].fRegister; + syntax_tree.fUserValue += ", __end%s\njb __continue%s\n__export .text __end%s\nbegin\njlr r31\nend\nvoid __export .text __continue%s\nbegin\njb _L"; + syntax_tree.fUserValue += std::to_string(kBracesCount + 1) + "_" + std::to_string(time_off.raw); + syntax_tree.fUserValue += "\nend\nend"; + + while (syntax_tree.fUserValue.find("%s") != std::string::npos) + { + syntax_tree.fUserValue.replace(syntax_tree.fUserValue.find("%s"), strlen("%s"), symbol_loop); + } + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + kOnWhileLoop = true; + + break; + } + + if (_text[text_index] == 'f') + { + if (_text.find("for") == std::string::npos) + continue; + + if (_text.find("for") != text_index) + continue; + + syntax_tree.fUserValue = "jrl [r32+0x1]\n"; + + // actually set registers now. + + auto expr = _text.substr(_text.find("for") + strlen("for")); + + kLatestVar.clear(); + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + + kOnForLoop = true; + break; + } + + if (_text[text_index] == '+' && + _text[text_index+1] == '+') + { + _text = _text.replace(_text.find("++"), strlen("++"), ""); + + for (int _text_i = 0; _text_i < _text.size(); ++_text_i) + { + if (_text[_text_i] == '\t' || + _text[_text_i] == ' ') + _text.erase(_text_i, 1); + } + + syntax_tree.fUserValue += "add "; + syntax_tree.fUserValue += _text; + + if (syntax_tree.fUserValue.find(";") != std::string::npos) + syntax_tree.fUserValue.erase(syntax_tree.fUserValue.find(";"), 1); + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + + if (_text[text_index] == '}') + { + kRegisterCounter = kStartUsable; + + --kBracesCount; + + if (kBracesCount < 1) + { + kInBraces = false; + kBracesCount = 0; + } + + if (kInStruct) + kInStruct = false; + + if (!kInBraces) + { + syntax_tree.fUserValue += kAddIfAnyEnd; + syntax_tree.fUserValue = "\nend "; + + kAddIfAnyEnd.clear(); + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + else + { + if (kOnWhileLoop || + kOnForLoop) + { + if (kOnForLoop) + kOnForLoop = false; + + if (kOnWhileLoop) + kOnWhileLoop = false; + + std::string symbol_loop = "_loop_for_"; + symbol_loop += std::to_string(time_off.raw); + symbol_loop += " "; + + syntax_tree.fUserValue = "beq "; + syntax_tree.fUserValue += kState.kStackFrame[kState.kStackFrame.size() - 2].fRegister; + syntax_tree.fUserValue += ","; + syntax_tree.fUserValue += kState.kStackFrame[kState.kStackFrame.size() - 1].fRegister; + syntax_tree.fUserValue += ", __end%s\njb __continue%s\n__export .text __end%s\nbegin\njlr r31\nend\nvoid __export .text __continue%s\nbegin\njb _L"; + syntax_tree.fUserValue += std::to_string(kBracesCount + 1) + "_" + std::to_string(time_off.raw); + syntax_tree.fUserValue += "\nend\nend"; + + while (syntax_tree.fUserValue.find("%s") != std::string::npos) + { + syntax_tree.fUserValue.replace(syntax_tree.fUserValue.find("%s"), strlen("%s"), symbol_loop); + } + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + else + { + syntax_tree.fUserValue = "\nend "; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } + } + } + + syntax_tree.fUserValue.clear(); + } + + syntax_tree.fUserValue = "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); } static bool kShouldHaveBraces = false; diff --git a/CompilerDriver/ld.cxx b/CompilerDriver/ld.cxx index cea3edc..a4ce070 100644 --- a/CompilerDriver/ld.cxx +++ b/CompilerDriver/ld.cxx @@ -37,12 +37,12 @@ #define kPefNoCpu 0U #define kPefNoSubCpu 0U -#define kWhite "\e[0;97m" +#define kWhite "\e[0;97m" #define kStdOut (std::cout << kWhite) #define kPefDefaultStart 0x8000000 #define kPefLinkerNumId 0x333D -#define kPefAbiId "Container:Abi:MultiProcessor-UNIX" +#define kPefAbiId "Container:Abi:MP-UX" enum { kAbiMpUx = 0xDEAD1 }; @@ -84,7 +84,9 @@ int main(int argc, char** argv) kStdOut << kToolVersion << "\n"; kStdOut << "-v: Print program version.\n"; kStdOut << "-shared: Output as a shared library.\n"; - kStdOut << "-marc, -m64000: Compile to specific ISA.\n"; + kStdOut << "-m64000: Link for the X64000 instruction set.\n"; + kStdOut << "-m68000: Link for the NXP 68000 instruction set.\n"; + kStdOut << "-mppc64: Link for the PowerPC instruction set.\n"; kStdOut << "--fat-binary: Output as FAT PEF.\n"; kStdOut << "-o: Select output filename.\n"; @@ -127,11 +129,6 @@ int main(int argc, char** argv) continue; } - else if (StringCompare(argv[i], "-marc") == 0) - { - kArch = CxxKit::kPefArchARC; - continue; - } else if (StringCompare(argv[i], "-o") == 0) { kOutput = argv[i+1]; @@ -236,7 +233,7 @@ int main(int argc, char** argv) std::string(command_header.Name).find(".data") == std::string::npos && std::string(command_header.Name).find(".page_zero") == std::string::npos) { - if (std::string(command_header.Name).find("$__start") == std::string::npos && + if (std::string(command_header.Name).find(kPefStart) == std::string::npos && *command_header.Name == 0) { if (std::string(command_header.Name).find(kLdDefineSymbol) != std::string::npos) diff --git a/CompilerDriver/masm.cxx b/CompilerDriver/masm.cxx index 78ddc4c..17385d7 100644 --- a/CompilerDriver/masm.cxx +++ b/CompilerDriver/masm.cxx @@ -37,10 +37,9 @@ #define kWhite "\e[0;97m" #define kYellow "\e[0;33m" -static char kOutputArch = CxxKit::kPefArchRISCV; +#define kStdOut (std::cout << kWhite) -static std::vector<bool> kLabelLevel; -static std::vector<std::string> kTypes = { "void", "byte", "qword", "hword", "dword" }; +static char kOutputArch = CxxKit::kPefArch64000; //! base relocation address for every mp-ux app. static UInt32 kErrorLimit = 10; @@ -48,19 +47,21 @@ static UInt32 kAcceptableErrors = 0; static std::size_t kCounter = 1UL; +static bool kVerbose = false; + static std::vector<char> kBytes; static CxxKit::AERecordHeader kCurrentRecord{ .fName = "", .fKind = CxxKit::kPefCode, .fSize = 0, .fOffset = 0 }; static std::vector<CxxKit::AERecordHeader> kRecords; static std::vector<std::string> kUndefinedSymbols; + static const std::string kUndefinedSymbol = ":ld:"; static const std::string kRelocSymbol = ":mld:"; // \brief forward decl. static std::string masm_check_line(std::string& line, const std::string& file); -static void masm_check_export(std::string& line); -static void masm_read_labels(std::string& line); -static void masm_read_instr(std::string& line, const std::string& file); +static bool masm_read_attributes(std::string& line); +static void masm_read_instruction(std::string& line, const std::string& file); namespace detail { @@ -69,8 +70,8 @@ namespace detail if (reason[0] == '\n') reason.erase(0, 1); - std::cout << kRed << "[ masm ] " << kWhite << ((file == "masm") ? "internal assembler error " : ("in file, " + file)) << kBlank << std::endl; - std::cout << kRed << "[ masm ] " << kWhite << reason << kBlank << std::endl; + kStdOut << kRed << "[ masm ] " << kWhite << ((file == "masm") ? "internal assembler error " : ("in file, " + file)) << kBlank << std::endl; + kStdOut << kRed << "[ masm ] " << kWhite << reason << kBlank << std::endl; if (kAcceptableErrors > kErrorLimit) std::exit(3); @@ -85,10 +86,10 @@ namespace detail if (!file.empty()) { - std::cout << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; } - std::cout << kYellow << "[ masm ] " << kWhite << reason << kBlank << std::endl; + kStdOut << kYellow << "[ masm ] " << kWhite << reason << kBlank << std::endl; } } @@ -122,7 +123,19 @@ int main(int argc, char** argv) { if (strcmp(argv[i], "-v") == 0) { - std::cout << "masm: The MP-UX Assembler.\nmasm: Copyright (c) 2023 WestCo.\n"; + kStdOut << "masm: The MP-UX Assembler.\nmasm: Copyright (c) 2023 WestCo.\n"; + return 0; + } + + if (strcmp(argv[i], "-h") == 0) + { + kStdOut << "masm: The MP-UX Assembler.\nmasm: Copyright (c) 2023 WestCo.\n"; + kStdOut << "-v: Print program version.\n"; + kStdOut << "--verbose: Print verbose output.\n"; + kStdOut << "-m64000: Compile for the X64000 instruction set.\n"; + kStdOut << "-m68000: Compile for the NXP 68000 instruction set.\n"; + kStdOut << "-mppc64: Compile for the PowerPC instruction set.\n"; + return 0; } @@ -132,7 +145,13 @@ int main(int argc, char** argv) continue; } - std::cout << "masm: ignore " << argv[i] << "\n"; + if (strcmp(argv[i], "--verbose") == 0) + { + kVerbose = true; + continue; + } + + kStdOut << "masm: ignore " << argv[i] << "\n"; continue; } @@ -181,11 +200,13 @@ int main(int argc, char** argv) if (ParserKit::find_word(line, "#")) continue; - masm_check_export(line); - masm_read_labels(line); - masm_read_instr(line, argv[i]); + masm_read_attributes(line); + masm_read_instruction(line, argv[i]); } + if (kVerbose) + kStdOut << "masm: writing to file...\n"; + // this is the final step, write everything to the file. auto pos = file_ptr_out.tellp(); @@ -206,6 +227,9 @@ int main(int argc, char** argv) for (auto& rec : kRecords) { + if (kVerbose) + kStdOut << "masm: wrote record " << rec.fName << " to file...\n"; + rec.fFlags |= CxxKit::kKindRelocationAtRuntime; rec.fOffset = record_count; ++record_count; @@ -220,6 +244,9 @@ int main(int argc, char** argv) { CxxKit::AERecordHeader _record_hdr{ 0 }; + if (kVerbose) + kStdOut << "masm: wrote symbol " << sym << " to file...\n"; + _record_hdr.fKind = kAEInvalidOpcode; _record_hdr.fSize = sym.size(); _record_hdr.fOffset = record_count; @@ -227,7 +254,6 @@ int main(int argc, char** argv) ++record_count; memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); - memcpy(_record_hdr.fName, sym.c_str(), sym.size()); file_ptr_out << _record_hdr; @@ -252,22 +278,32 @@ int main(int argc, char** argv) file_ptr_out.write(reinterpret_cast<const char *>(&byte), sizeof(byte)); } + if (kVerbose) + kStdOut << "masm: wrote program bytes to file...\n"; + file_ptr_out.flush(); file_ptr_out.close(); + + if (kVerbose) + kStdOut << "masm: exit succeed with 0.\n"; return 0; } - return 0; + if (kVerbose) + kStdOut << "masm: exit succeed with -1.\n"; + + return -1; } ///////////////////////////////////////////////////////////////////////////////////////// -// @brief Check for exported symbols +// @brief Check for attributes +// returns true if any was found. ///////////////////////////////////////////////////////////////////////////////////////// -static void masm_check_export(std::string& line) +static bool masm_read_attributes(std::string& line) { // __import is the opposite of export, it signals to the ld // that we need this symbol. @@ -327,7 +363,7 @@ static void masm_check_export(std::string& line) kRecords.emplace_back(kCurrentRecord); - return; + return true; } // __export is a special keyword used by masm to tell the AE output stage to mark this section as a header. @@ -383,7 +419,11 @@ static void masm_check_export(std::string& line) memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); kRecords.emplace_back(kCurrentRecord); + + return true; } + + return false; } // \brief algorithms and helpers. @@ -426,8 +466,6 @@ static std::string masm_check_line(std::string& line, const std::string& file) if (line.empty() || ParserKit::find_word(line, "__import") || ParserKit::find_word(line, "__export") || - ParserKit::find_word(line, "begin") || - ParserKit::find_word(line, "end") || ParserKit::find_word(line, "#") || ParserKit::find_word(line, "layout")) { @@ -515,15 +553,7 @@ static std::string masm_check_line(std::string& line, const std::string& file) } } - for (auto& type : kTypes) - { - if (ParserKit::find_word(line, type)) - { - return err_str; - } - } - - err_str += "Unknown syntax, "; + err_str += "Unknown syntax: "; err_str += line; return err_str; @@ -531,23 +561,10 @@ static std::string masm_check_line(std::string& line, const std::string& file) ///////////////////////////////////////////////////////////////////////////////////////// -// @brief Check if a line starts a new label. +// @brief internal namespace ///////////////////////////////////////////////////////////////////////////////////////// -static void masm_read_labels(std::string& line) -{ - if (ParserKit::find_word(line, "begin")) - { - kLabelLevel.emplace_back(true); - } - else if (ParserKit::find_word(line, "end")) - { - if (kLabelLevel.size() > 0) - kLabelLevel.pop_back(); - } -} - namespace detail { union number_type @@ -563,6 +580,9 @@ namespace detail static bool masm_write_number(std::size_t pos, std::string& jump_label) { + if (!isdigit(jump_label[pos])) + return false; + switch (jump_label[pos+1]) { case 'x': @@ -573,6 +593,7 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) { if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "masm"); return false; } } @@ -585,6 +606,11 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) kBytes.push_back(i); } + if (kVerbose) + { + kStdOut << "masm: found a base 16 number... " << jump_label.substr(pos) << "\n"; + } + return true; } case 'b': @@ -595,6 +621,7 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) { if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "masm"); return false; } } @@ -602,6 +629,39 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) detail::number_type num(strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + if (kVerbose) + { + kStdOut << "masm: found a base 2 number... " << jump_label.substr(pos) << "\n"; + } + + for (char i : num.number) + { + kBytes.push_back(i); + } + + return true; + } + case '0': + { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), + nullptr, 7); + !res) + { + if (errno != 0) + { + detail::print_error("invalid octal number: " + jump_label, "masm"); + return false; + } + } + + detail::number_type num(strtoq(jump_label.substr(pos + 2).c_str(), + nullptr, 7)); + + if (kVerbose) + { + kStdOut << "masm: found a base 8 number... " << jump_label.substr(pos) << "\n"; + } + for (char i : num.number) { kBytes.push_back(i); @@ -625,29 +685,30 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) return false; } } - else - { - detail::number_type num(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); - for (char i : num.number) - { - kBytes.push_back(i); - } + detail::number_type num(strtoq(jump_label.substr(pos).c_str(), + nullptr, 10)); - return true; + for (char i : num.number) + { + kBytes.push_back(i); } - return false; + if (kVerbose) + { + kStdOut << "masm: found a base 10 number... " << jump_label.substr(pos) << "\n"; + } + + return true; } ///////////////////////////////////////////////////////////////////////////////////////// -// @brief Read and write instruction to file. +// @brief Read and write instruction to kBytes array. ///////////////////////////////////////////////////////////////////////////////////////// -static void masm_read_instr(std::string& line, const std::string& file) +static void masm_read_instruction(std::string& line, const std::string& file) { for (auto& opcodes : kOpcodesStd) { @@ -670,19 +731,36 @@ static void masm_read_instr(std::string& line, const std::string& file) // \brief how many registers we found. std::size_t found_some = 0UL; - for (int reg_index = 0; reg_index < kAsmRegisterLimit; ++reg_index) + for (size_t line_index = 0UL; line_index < line.size(); line_index++) { - std::string register_syntax = kAsmRegisterPrefix; - register_syntax += std::to_string(reg_index); - - // if we found one - if (ParserKit::find_word(line, register_syntax)) + if (line[line_index] == 'r' && + isdigit(line[line_index + 1])) { - // emplace it. - kBytes.emplace_back(reg_index); - ++found_some; + std::string register_syntax = kAsmRegisterPrefix; + register_syntax += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + register_syntax += line[line_index + 2]; + + std::string reg_str; + reg_str += line[line_index + 1]; + reg_str += line[line_index + 2]; + + std::size_t reg_index = strtoq( + reg_str.c_str(), + nullptr, + 10); + + // if we found one + if (ParserKit::find_word(line, register_syntax)) + { + // emplace it. + kBytes.emplace_back(reg_index); + ++found_some; + } } } + if (opcodes.fFunct7 != kAsmImmediate) { |
