summaryrefslogtreecommitdiffhomepage
path: root/CompilerDriver
diff options
context:
space:
mode:
Diffstat (limited to 'CompilerDriver')
-rw-r--r--CompilerDriver/cc.cxx809
-rw-r--r--CompilerDriver/ld.cxx15
-rw-r--r--CompilerDriver/masm.cxx210
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)
{