From 274bbde1c43be2fe72eac51a326462e3ac660d6d Mon Sep 17 00:00:00 2001 From: avinal <185067@nith.ac.in> Date: Fri, 21 Aug 2020 17:54:38 +0530 Subject: [PATCH] added newer definations for part 2 --- code_writer.cpp | 399 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 344 insertions(+), 55 deletions(-) diff --git a/code_writer.cpp b/code_writer.cpp index 600541f..3432e66 100644 --- a/code_writer.cpp +++ b/code_writer.cpp @@ -1,19 +1,31 @@ #include "code_writer.hpp" -code_writer::code_writer(std::string name) +code_writer::code_writer(lots_of_files names) { - file_name = name; - name.erase(name.find('.')); - name.append(".asm"); - outfile.open(name); + this->files = names; + std::string outfile_name; + outfile_name = files.front(); + if (files.size() > 1) + { + files.erase(files.begin()); + std::string check = files.front(); + if (check.substr(check.length() - 6) == "Sys.vm") + { + this->is_dir = true; + } + outfile_name = outfile_name + "/" + outfile_name; + } + else + { + outfile_name.erase(outfile_name.find('.')); + } + + outfile_name.append(".asm"); + outfile.open(outfile_name); } void code_writer::write_assembly() { - parser toparse(file_name); - toparse.parse(); - commands = toparse.get_commands(); - std::unordered_map> write_map({{C_ARITHMETIC, @@ -27,31 +39,65 @@ void code_writer::write_assembly() {C_POP, [this](std::string arg1, int arg2, bool arg3) { this->write_pop(arg1, arg2, arg3); + }}, + {C_LABEL, + [this](std::string arg1, int arg2, bool arg3) { + this->write_label(arg1, arg2, arg3); + }}, + {C_FUNCTION, + [this](std::string arg1, int arg2, bool arg3) { + this->write_function(arg1, arg2, arg3); + }}, + {C_RETURN, + [this](std::string arg1, int arg2, bool arg3) { + this->write_return(arg3); + }}, + {C_GOTO, + [this](std::string arg1, int arg2, bool arg3) { + this->write_goto(arg1, arg2, arg3); + }}, + {C_IF, + [this](std::string arg1, int arg2, bool arg3) { + this->write_if(arg1, arg2, arg3); + }}, + {C_CALL, + [this](std::string arg1, int arg2, bool arg3) { + this->write_call(arg1, arg2, arg3); }}}); - for (auto curr : commands) + parser lets_parse; + this->write_init(this->dbg); + for (auto curr_file : this->files) { - c_type write_type; - std::string instruction; - int index; - std::tie(write_type, instruction, index) = curr; - if (outfile.is_open()) + lets_parse.change_file(curr_file); + lets_parse.parse(); + this->commands = lets_parse.get_commands(); + this->current_file = curr_file; + for (auto curr : commands) { - write_map[write_type](instruction, index, this->dbg); + c_type write_type; + std::string instruction; + int index; + std::tie(write_type, instruction, index) = curr; + if (outfile.is_open()) + { + write_map[write_type](instruction, index, this->dbg); + } } + this->commands.clear(); } outfile.close(); } void code_writer::write_push(std::string segment, int index, bool debug) { - std::string toname = file_name; + std::string toname = this->current_file; toname = toname.substr(toname.find_last_of('/') + 1); toname = toname.erase(toname.find('.')); if (debug) { - outfile << "// push " << segment << " " << index << std::endl; + outfile << "// push " << segment << " " << index << " " << this->ins_no << std::endl; } if (segment == "constant") @@ -128,15 +174,30 @@ void code_writer::write_push(std::string segment, int index, bool debug) } } +void code_writer::write_push(std::string segment, bool debug) +{ + if (debug) + { + outfile << "// push " << segment << " " << this->ins_no << std::endl; + } + outfile << "@" << segment << std::endl + << "D=M" << std::endl + << "@SP" << std::endl + << "AM=M+1" << std::endl + << "A=A-1" << std::endl + << "M=D" << std::endl; + this->ins_no += 6; +} + void code_writer::write_pop(std::string segment, int index, bool debug) { - std::string toname = file_name; - toname = toname.substr(toname.find_last_of('/')+1); + std::string toname = this->current_file; + toname = toname.substr(toname.find_last_of('/') + 1); toname = toname.erase(toname.find('.')); if (debug && segment != "constant") { - outfile << "// pop " << segment << " " << index << std::endl; + outfile << "// pop " << segment << " " << index << " " << this->ins_no << std::endl; } if (segment == "static") @@ -156,7 +217,7 @@ void code_writer::write_pop(std::string segment, int index, bool debug) << "D=M" << std::endl << "@" << which << std::endl << "M=D" << std::endl; - this->ins_no += 4; + this->ins_no += 5; } else if (segment == "temp") { @@ -202,34 +263,103 @@ void code_writer::write_pop(std::string segment, int index, bool debug) } } +void code_writer::write_pop(std::string segment, bool debug) +{ + if (debug) + { + outfile << "// pop " << segment << " " << this->ins_no << std::endl; + } + + outfile << "@SP" << std::endl + << "A=M-1" << std::endl + << "D=M" << std::endl + << "@" << segment << std::endl + << "A=M" << std::endl + << "M=D" << std::endl; + this->ins_no += 6; +} + void code_writer::write_arithmetic(std::string comm, int index, bool debug) { std::unordered_map> + std::function> arith_mapic({ {"add", - [this](bool arg1) { this->write_add(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }}, {"sub", - [this](bool arg1) { this->write_sub(arg1); }}, - {"neg", - [this](bool arg1) { this->write_neg(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }}, {"and", - [this](bool arg1) { this->write_and(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }}, {"or", - [this](bool arg1) { this->write_or(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_add_sub_and_or(arg0, arg1); }}, + {"neg", + [this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }}, {"not", - [this](bool arg1) { this->write_not(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_neg_not(arg0, arg1); }}, {"gt", - [this](bool arg1) { this->write_gt(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }}, {"lt", - [this](bool arg1) { this->write_lt(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }}, {"eq", - [this](bool arg1) { this->write_eq(arg1); }}, + [this](std::string arg0, bool arg1) { this->write_eq_lt_gt(arg0, arg1); }}, }); - arith_mapic[comm](debug); + arith_mapic[comm](comm, debug); } +void code_writer::write_add_sub_and_or(std::string op, bool debug) +{ + if (debug) + { + outfile << "// " << op << " " << this->ins_no << std::endl; + } + outfile << "@SP" << std::endl + << "AM=M-1" << std::endl + << "D=M" << std::endl + << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=" << operation_map.at(op) << std::endl; + this->ins_no += 6; +} + +void code_writer::write_neg_not(std::string op, bool debug) +{ + if (debug) + { + outfile << "// " << op << " " << this->ins_no << std::endl; + } + outfile << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=" << operation_map.at(op) << std::endl; + this->ins_no += 3; +} + +void code_writer::write_eq_lt_gt(std::string op, bool debug) +{ + if (debug) + { + outfile << "// " << op << " " << this->ins_no << std::endl; + } + outfile << "@SP" << std::endl + << "AM=M-1" << std::endl + << "D=M" << std::endl + << "A=A-1" << std::endl + << "D=M-D" << std::endl; + this->ins_no += 5; + outfile << "@" << this->ins_no + 6 << std::endl + << "D;" << operation_map.at(op) << std::endl + << "D=0" << std::endl; + this->ins_no += 3; + outfile << "@" << this->ins_no + 4 << std::endl + << "0;JMP" << std::endl + << "D=-1" << std::endl + << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=D" << std::endl; + this->ins_no += 6; +} + +/* void code_writer::write_add(bool debug) { if (debug) @@ -272,6 +402,48 @@ void code_writer::write_neg(bool debug) this->ins_no += 3; } +void code_writer::write_and(bool debug) +{ + if (debug) + { + outfile << "// and" << std::endl; + } + outfile << "@SP" << std::endl + << "AM=M-1" << std::endl + << "D=M" << std::endl + << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=D&M" << std::endl; + this->ins_no += 6; +} + +void code_writer::write_or(bool debug) +{ + if (debug) + { + outfile << "// or" << std::endl; + } + outfile << "@SP" << std::endl + << "AM=M-1" << std::endl + << "D=M" << std::endl + << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=D|M" << std::endl; + this->ins_no += 6; +} + +void code_writer::write_not(bool debug) +{ + if (debug) + { + outfile << "// not" << std::endl; + } + outfile << "@SP" << std::endl + << "A=M-1" << std::endl + << "M=!M" << std::endl; + this->ins_no += 3; +} + void code_writer::write_eq(bool debug) { if (debug) @@ -346,45 +518,162 @@ void code_writer::write_gt(bool debug) << "M=D" << std::endl; this->ins_no += 6; } +*/ -void code_writer::write_and(bool debug) +void code_writer::write_init(bool debug) { if (debug) { - outfile << "// and" << std::endl; + outfile << "// bootstrap code" + << " " << this->ins_no << std::endl; } - outfile << "@SP" << std::endl - << "AM=M-1" << std::endl - << "D=M" << std::endl + outfile << "@256" << std::endl + << "D=A" << std::endl << "@SP" << std::endl - << "A=M-1" << std::endl - << "M=D&M" << std::endl; - this->ins_no += 6; + << "M=D" << std::endl; + this->ins_no += 4; + + if (this->is_dir) + { + outfile << "// Sys.init defined adding function call..." + << " " << this->ins_no << std::endl; + this->write_call("Sys.init", 0, debug); + } } -void code_writer::write_or(bool debug) +void code_writer::write_call(std::string fun_name, int args, bool debug) { if (debug) { - outfile << "// or" << std::endl; + outfile << "// call" << fun_name << " " << args << " " << this->ins_no << std::endl; } - outfile << "@SP" << std::endl - << "AM=M-1" << std::endl - << "D=M" << std::endl + std::string curr_ins = std::to_string(this->ins_no); + std::string ret_label("ret." + fun_name + "$" + curr_ins); + + outfile << "@" << ret_label << std::endl + << "D=A" << std::endl << "@SP" << std::endl - << "A=M-1" << std::endl - << "M=D|M" << std::endl; + << "AM=M+1" << std::endl + << "A=A-1" << std::endl + << "M=D" << std::endl; this->ins_no += 6; + + this->write_push("LCL", debug); + this->write_push("ARG", debug); + this->write_push("THIS", debug); + this->write_push("THAT", debug); + + outfile << "@SP" << std::endl + << "D=M" << std::endl + << "@5" << std::endl + << "D=D-A" << std::endl + << "@" << args << std::endl + << "D=D-A" << std::endl + << "@ARG" << std::endl + << "M=D" << std::endl + << "@SP" << std::endl + << "D=M" << std::endl + << "@LCL" << std::endl + << "M=D" << std::endl + << "@" << fun_name << std::endl + << "0;JMP" << std::endl + << "(" << ret_label << ")" << std::endl; + this->ins_no += 14; } -void code_writer::write_not(bool debug) +void code_writer::write_label(std::string label, int index, bool debug) { if (debug) { - outfile << "// not" << std::endl; + outfile << "// label " << label << " " << this->ins_no << std::endl; } - outfile << "@SP" << std::endl - << "A=M-1" << std::endl - << "M=!M" << std::endl; + outfile << "(" << current_function << "$" << label << ")" << std::endl; +} + +void code_writer::write_goto(std::string label, int index, bool debug) +{ + if (debug) + { + outfile << "// goto " << label << " " << this->ins_no << std::endl; + } + outfile << "@" << current_function << "$" << label << std::endl + << "0;JMP" << std::endl; + this->ins_no += 2; +} + +void code_writer::write_function(std::string fun_name, int locals, bool debug) +{ + if (debug) + { + outfile << "// function " << fun_name << " " << locals << " " << this->ins_no << std::endl; + } + current_function = fun_name; + outfile << "(" << fun_name << ")" << std::endl; + for (int l = 0; l < locals; l++) + { + this->write_push("constant", 0, debug); + } +} + +void code_writer::write_return(bool debug) +{ + if (debug) + { + outfile << "// return " << current_function << " " << this->ins_no << std::endl; + } + outfile << "@LCL" << std::endl + << "D=M" << std::endl + << "@R7" << std::endl + << "M=D" << std::endl + << "@5" << std::endl + << "A=D-A" << std::endl + << "D=M" << std::endl + << "@R14" << std::endl + << "M=D" << std::endl; + this->ins_no += 9; + this->write_pop("ARG", debug); + outfile << "@ARG" << std::endl + << "D=M" << std::endl + << "@SP" << std::endl + << "M=D+1" << std::endl; + this->ins_no += 4; + this->write_frame_restore("THAT", 1, debug); + this->write_frame_restore("THIS", 2, debug); + this->write_frame_restore("ARG", 3, debug); + this->write_frame_restore("LCL", 4, debug); + outfile << "@R14" << std::endl + << "A=M" << std ::endl + << "0;JMP" << std::endl; this->ins_no += 3; -} \ No newline at end of file +} + +void code_writer::write_frame_restore(std::string segment, int minus, bool debug) +{ + if (debug) + { + outfile << "// restoring " << segment << " " << this->ins_no << std::endl; + } + + outfile << "@R7" << std::endl + << "D=M" << std::endl + << "@" << minus << std::endl + << "A=D-A" << std::endl + << "D=M" << std::endl + << "@" << segment << std::endl + << "M=D" << std::endl; + this->ins_no += 7; +} + +void code_writer::write_if(std::string label, int index, bool debug) +{ + if (debug) + { + outfile << "// if " << label << " " << this->ins_no << std::endl; + } + outfile << "@SP" << std::endl + << "AM=M-1" << std::endl + << "D=M" << std::endl + << "@" << current_function << "$" << label << std::endl + << "D;JNE" << std::endl; + this->ins_no += 5; +}