Example #1
0
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;
}