void n_expression::code_gen(status& stat, std::ostream& out) { // left OP right : result_reg = t0 OP t1 bool unlock = false; if (!stat.get_assign_expr()) { stat.lock_register(out); stat.set_assign_expr(); unlock = true; } if (opstr == "+") { if (left != NULL) { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tadd.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else { right->code_gen(stat, out); } } else if (opstr == "-") { if (left != NULL) { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tsub.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else { stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tneg\t$t" << stat.get_register() << ",$t" << op2 << "\n"; } } else if (opstr == "*") { if (left != NULL) // if operation is left MULT right { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tmul.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tmul\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else // if operation is dereferencing { if (stat.get_assign_var()) stat.lock_register(out); int op2 = stat.get_register(); stat.set_dereference(); right->code_gen(stat, out); stat.set_dereference(); if (stat.get_assign_var()) // if variable needs to be saved stat.unlock_register(out); out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n"; } } else if (opstr == "/") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tdiv.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tdiv\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "%") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\trem\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "&") { if (left != NULL) // if operation is left AND right { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tand\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else // if operation is referencing { stat.set_reference(); right->code_gen(stat, out); stat.set_reference(); } } else if (opstr == "|") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tor\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "^") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\txor\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "<<") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsllv\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == ">>") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsrav\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "==") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tseq\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "!=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsne\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "<") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tslt\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == ">") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tslt\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; } else if (opstr == "<=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsge\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; } else if (opstr == ">=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsge\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "++") { if (left != NULL) // postfix { left->code_gen(stat, out); int op1 = stat.get_register(); stat.lock_register(out); out << "\tadd\t$t" << stat.get_register() << ",$t" << op1 << ",1\n"; stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); stat.unlock_register(out); } else if (right != NULL) // prefix { right->code_gen(stat, out); out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n"; stat.set_assign_var(); right->code_gen(stat, out); stat.set_assign_var(); } } else if (opstr == "--") { if (left != NULL) // postfix { left->code_gen(stat, out); int op1 = stat.get_register(); stat.lock_register(out); out << "\tsub\t$t" << stat.get_register() << ",$t" << op1 << ",1\n"; stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); stat.unlock_register(out); } else if (right != NULL) // prefix { right->code_gen(stat, out); out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n"; stat.set_assign_var(); right->code_gen(stat, out); stat.set_assign_var(); } } else if (opstr == "[]") { if (stat.get_assign_var()) stat.lock_register(out); // get offset of first element stat.lock_register(out); int op2 = stat.get_register(); stat.set_reference(); left->code_gen(stat, out); stat.set_reference(); stat.unlock_register(out); // evaluate operation right->code_gen(stat, out); // shift the operation to get number of bytes for array offset out << "\tsll\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",2\n"; // subtract array offset from first element offset out << "\tsubu\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; // store or load the variable op2 = stat.get_register(); if (stat.get_assign_var()) stat.unlock_register(out); out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n"; } else if (opstr == "!") { left->code_gen(stat, out); out << "\tseq\t$" << stat.get_register() << ",$zero,$t" << stat.get_register(); } else if (opstr == "~") { left->code_gen(stat, out); out << "\tnot\t$" << stat.get_register() << ",$t" << stat.get_register() << "\n"; } else if (opstr == "=") { right->code_gen(stat, out); stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); } if (unlock) { stat.unlock_register(out); stat.set_assign_expr(); } return; }