/* * Created by Brett on 17/11/23. * Licensed under GNU General Public License V3.0 * See LICENSE file for license detail */ #include <bf_mips_codegen.h> #include <iostream> std::string preamble = ".data\n" "\tdata_address: \t.word \t0\n" "\tdata_pointer:\t.word\t0\n" "\tnewline: .asciiz \"\\n\"\n" ".text\n" "setup:\n" "\tli $v0, 9\n" "\tli $a0, 30000\n" "\tsyscall\n" "\t\n" "\tla $t1, data_address\n" "\tsw $v0, ($t1)\n" "\t\n" "\t# t0 - current address (data_pointer)\n" "\t# t1 -\n" "\t# t2 - temp\n" "\tmove $t0, $v0\n" "bf:\n"; void process_print(const std::vector<token_t>& tokens, size_t index); void codegen(const std::vector<token_t>& tokens, std::ostream& out) { out << preamble; size_t index = 0; // skip past comments if (tokens[index].token == bf_token::OPEN) while (tokens[index].token != bf_token::CLOSE) index++; process_print(tokens, index); size_t sp = 0; while (index < tokens.size()) { auto& token = tokens[index++]; std::string name{"UNNAMED"}; if (token.name.has_value()) name = token.name.value(); switch (token.token) { case bf_token::INC_DP: out << "\taddi $t0, $t0, 1\n"; break; case bf_token::DEC_DP: out << "\tsubi $t0, $t0, 1\n"; break; case bf_token::INC_DV: out << "\tlb $t1, ($t0)\n" << "\taddi $t1, $t1, 1\n" << "\tsb $t1, ($t0)\n"; break; case bf_token::DEC_DV: out << "\tlb $t1, ($t0)\n" << "\tsubi $t1, $t1, 1\n" << "\tsb $t1, ($t0)\n"; break; case bf_token::PRINT: out << "\tli $v0, 11\n" << "\tlb $a0, ($t0)\n" << "\tsyscall\n"; break; case bf_token::READ: out << "\tli $v0, 12\n" << "\tsyscall\n" << "\tsb $v0, ($t0)\n"; break; case bf_token::OPEN: out << "\tlb $t1, ($t0)\n" << "\tbeqz $t1, BF_CLOSE_" << name << "_" << std::to_string(sp) << '\n' << "BF_OPEN_" << name << "_" << std::to_string(sp) << ":\n"; sp++; break; case bf_token::CLOSE: sp--; out << "\tlb $t1, ($t0)\n" << "\tbnez $t1, BF_OPEN_" << name << "_" << std::to_string(sp) << '\n' << "BF_CLOSE_" << name << "_" << std::to_string(sp) << ":\n"; break; } } } inline void tabulate(size_t v) { for (size_t i = 0; i < v; i++) std::cout << '\t'; } void process_print(const std::vector<token_t>& tokens, size_t index) { size_t sp = 0; while (index < tokens.size()) { auto& token = tokens[index++]; switch (token.token) { case bf_token::INC_DP: tabulate(sp); std::cout << "Increase DP\n"; break; case bf_token::DEC_DP: tabulate(sp); std::cout << "Decrease DP\n"; break; case bf_token::INC_DV: tabulate(sp); std::cout << "Increase DV\n"; break; case bf_token::DEC_DV: tabulate(sp); std::cout << "Decrease DV\n"; break; case bf_token::PRINT: tabulate(sp); std::cout << "Print\n"; break; case bf_token::READ: tabulate(sp); std::cout << "Read\n"; break; case bf_token::OPEN: tabulate(sp); std::cout << "If("; if (token.name.has_value()) std::cout << token.name.value() << "\n"; else std::cout << "UNNAMED" << "\n"; sp++; break; case bf_token::CLOSE: sp--; tabulate(sp); if (token.name.has_value()) std::cout << token.name.value(); else std::cout << "UNNAMED"; std::cout << ")\n"; break; } } }