Removed output file from generator signatures, implement some of the luajit generator

This commit is contained in:
Mr-Wiseguy 2024-09-29 17:17:05 -04:00
parent f3f4a5cd73
commit c54855b05d
4 changed files with 656 additions and 234 deletions

View file

@ -8,7 +8,7 @@
struct BinaryOpFields { std::string func_string; std::string infix_string; };
std::vector<BinaryOpFields> c_op_fields = []() {
static std::vector<BinaryOpFields> c_op_fields = []() {
std::vector<BinaryOpFields> ret{};
ret.resize(static_cast<size_t>(N64Recomp::BinaryOpType::COUNT));
std::vector<char> ops_setup{};
@ -72,22 +72,22 @@ std::vector<BinaryOpFields> c_op_fields = []() {
return ret;
}();
std::string gpr_to_string(int gpr_index) {
static std::string gpr_to_string(int gpr_index) {
if (gpr_index == 0) {
return "0";
}
return fmt::format("ctx->r{}", gpr_index);
}
std::string fpr_to_string(int fpr_index) {
static std::string fpr_to_string(int fpr_index) {
return fmt::format("ctx->f{}.fl", fpr_index);
}
std::string fpr_double_to_string(int fpr_index) {
static std::string fpr_double_to_string(int fpr_index) {
return fmt::format("ctx->f{}.d", fpr_index);
}
std::string fpr_u32l_to_string(int fpr_index) {
static std::string fpr_u32l_to_string(int fpr_index) {
if (fpr_index & 1) {
return fmt::format("ctx->f_odd[({} - 1) * 2]", fpr_index);
}
@ -96,11 +96,11 @@ std::string fpr_u32l_to_string(int fpr_index) {
}
}
std::string fpr_u64_to_string(int fpr_index) {
static std::string fpr_u64_to_string(int fpr_index) {
return fmt::format("ctx->f{}.u64", fpr_index);
}
std::string unsigned_reloc(const N64Recomp::InstructionContext& context) {
static std::string unsigned_reloc(const N64Recomp::InstructionContext& context) {
switch (context.reloc_type) {
case N64Recomp::RelocType::R_MIPS_HI16:
return fmt::format("{}RELOC_HI16({}, {:#X})",
@ -113,7 +113,7 @@ std::string unsigned_reloc(const N64Recomp::InstructionContext& context) {
}
}
std::string signed_reloc(const N64Recomp::InstructionContext& context) {
static std::string signed_reloc(const N64Recomp::InstructionContext& context) {
return "(int16_t)" + unsigned_reloc(context);
}
@ -365,7 +365,7 @@ void N64Recomp::CGenerator::get_binary_expr_string(BinaryOpType type, const Bina
}
}
void N64Recomp::CGenerator::emit_function_start(std::ostream& output_file, const std::string& function_name) const {
void N64Recomp::CGenerator::emit_function_start(const std::string& function_name) const {
fmt::print(output_file,
"RECOMP_FUNC void {}(uint8_t* rdram, recomp_context* ctx) {{\n"
// these variables shouldn't need to be preserved across function boundaries, so make them local for more efficient output
@ -375,37 +375,37 @@ void N64Recomp::CGenerator::emit_function_start(std::ostream& output_file, const
function_name);
}
void N64Recomp::CGenerator::emit_function_end(std::ostream& output_file) const {
void N64Recomp::CGenerator::emit_function_end() const {
fmt::print(output_file, ";}}\n");
}
void N64Recomp::CGenerator::emit_function_call_lookup(std::ostream& output_file, uint32_t addr) const {
void N64Recomp::CGenerator::emit_function_call_lookup(uint32_t addr) const {
fmt::print(output_file, "LOOKUP_FUNC(0x{:08X})(rdram, ctx);\n", addr);
}
void N64Recomp::CGenerator::emit_function_call_by_register(std::ostream& output_file, int reg) const {
void N64Recomp::CGenerator::emit_function_call_by_register(int reg) const {
fmt::print(output_file, "LOOKUP_FUNC({})(rdram, ctx);\n", gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_function_call_by_name(std::ostream& output_file, const std::string& func_name) const {
void N64Recomp::CGenerator::emit_function_call_by_name(const std::string& func_name) const {
fmt::print(output_file, "{}(rdram, ctx);\n", func_name);
}
void N64Recomp::CGenerator::emit_goto(std::ostream& output_file, const std::string& target) const {
void N64Recomp::CGenerator::emit_goto(const std::string& target) const {
fmt::print(output_file,
" goto {};\n", target);
}
void N64Recomp::CGenerator::emit_label(std::ostream& output_file, const std::string& label_name) const {
void N64Recomp::CGenerator::emit_label(const std::string& label_name) const {
fmt::print(output_file,
"{}:\n", label_name);
}
void N64Recomp::CGenerator::emit_variable_declaration(std::ostream& output_file, const std::string& var_name, int reg) const {
void N64Recomp::CGenerator::emit_variable_declaration(const std::string& var_name, int reg) const {
fmt::print(output_file, "gpr {} = {};\n", var_name, gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const {
void N64Recomp::CGenerator::emit_branch_condition(const ConditionalBranchOp& op, const InstructionContext& ctx) const {
// Thread local variables to prevent allocations when possible.
// TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations.
thread_local std::string expr_string{};
@ -413,55 +413,55 @@ void N64Recomp::CGenerator::emit_branch_condition(std::ostream& output_file, con
fmt::print(output_file, "if ({}) {{\n", expr_string);
}
void N64Recomp::CGenerator::emit_branch_close(std::ostream& output_file) const {
void N64Recomp::CGenerator::emit_branch_close() const {
fmt::print(output_file, "}}\n");
}
void N64Recomp::CGenerator::emit_switch_close(std::ostream& output_file) const {
void N64Recomp::CGenerator::emit_switch_close() const {
fmt::print(output_file, "}}\n");
}
void N64Recomp::CGenerator::emit_switch(std::ostream& output_file, const std::string& jump_variable, int shift_amount) const {
void N64Recomp::CGenerator::emit_switch(const std::string& jump_variable, int shift_amount) const {
fmt::print(output_file, "switch ({} >> {}) {{\n", jump_variable, shift_amount);
}
void N64Recomp::CGenerator::emit_case(std::ostream& output_file, int case_index, const std::string& target_label) const {
void N64Recomp::CGenerator::emit_case(int case_index, const std::string& target_label) const {
fmt::print(output_file, "case {}: goto {}; break;\n", case_index, target_label);
}
void N64Recomp::CGenerator::emit_switch_error(std::ostream& output_file, uint32_t instr_vram, uint32_t jtbl_vram) const {
void N64Recomp::CGenerator::emit_switch_error(uint32_t instr_vram, uint32_t jtbl_vram) const {
fmt::print(output_file, "default: switch_error(__func__, 0x{:08X}, 0x{:08X});\n", instr_vram, jtbl_vram);
}
void N64Recomp::CGenerator::emit_return(std::ostream& output_file) const {
void N64Recomp::CGenerator::emit_return() const {
fmt::print(output_file, "return;\n");
}
void N64Recomp::CGenerator::emit_check_fr(std::ostream& output_file, int fpr) const {
void N64Recomp::CGenerator::emit_check_fr(int fpr) const {
fmt::print(output_file, "CHECK_FR(ctx, {});\n ", fpr);
}
void N64Recomp::CGenerator::emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const {
void N64Recomp::CGenerator::emit_check_nan(int fpr, bool is_double) const {
fmt::print(output_file, "NAN_CHECK(ctx->f{}.{}); ", fpr, is_double ? "d" : "fl");
}
void N64Recomp::CGenerator::emit_cop0_status_read(std::ostream& output_file, int reg) const {
void N64Recomp::CGenerator::emit_cop0_status_read(int reg) const {
fmt::print(output_file, "{} = cop0_status_read(ctx);\n", gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_cop0_status_write(std::ostream& output_file, int reg) const {
void N64Recomp::CGenerator::emit_cop0_status_write(int reg) const {
fmt::print(output_file, "cop0_status_write(ctx, {})", gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_cop1_cs_read(std::ostream& output_file, int reg) const {
void N64Recomp::CGenerator::emit_cop1_cs_read(int reg) const {
fmt::print(output_file, "{} = rounding_mode;\n", gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_cop1_cs_write(std::ostream& output_file, int reg) const {
void N64Recomp::CGenerator::emit_cop1_cs_write(int reg) const {
fmt::print(output_file, "rounding_mode = ({}) & 0x3;\n", gpr_to_string(reg));
}
void N64Recomp::CGenerator::emit_muldiv(std::ostream& output_file, InstrId instr_id, int reg1, int reg2) const {
void N64Recomp::CGenerator::emit_muldiv(InstrId instr_id, int reg1, int reg2) const {
switch (instr_id) {
case InstrId::cpu_mult:
fmt::print(output_file, "result = S64(S32({})) * S64(S32({})); lo = S32(result >> 0); hi = S32(result >> 32);\n", gpr_to_string(reg1), gpr_to_string(reg2));
@ -491,27 +491,27 @@ void N64Recomp::CGenerator::emit_muldiv(std::ostream& output_file, InstrId instr
}
}
void N64Recomp::CGenerator::emit_syscall(std::ostream& output_file, uint32_t instr_vram) const {
void N64Recomp::CGenerator::emit_syscall(uint32_t instr_vram) const {
fmt::print(output_file, "recomp_syscall_handler(rdram, ctx, 0x{:08X});\n", instr_vram);
}
void N64Recomp::CGenerator::emit_do_break(std::ostream& output_file, uint32_t instr_vram) const {
void N64Recomp::CGenerator::emit_do_break(uint32_t instr_vram) const {
fmt::print(output_file, "do_break({});\n", instr_vram);
}
void N64Recomp::CGenerator::emit_pause_self(std::ostream& output_file) const {
void N64Recomp::CGenerator::emit_pause_self() const {
fmt::print(output_file, "pause_self(rdram);\n");
}
void N64Recomp::CGenerator::emit_trigger_event(std::ostream& output_file, size_t event_index) const {
void N64Recomp::CGenerator::emit_trigger_event(size_t event_index) const {
fmt::print(output_file, "recomp_trigger_event(rdram, ctx, base_event_index + {});\n", event_index);
}
void N64Recomp::CGenerator::emit_comment(std::ostream& output_file, const std::string& comment) const {
void N64Recomp::CGenerator::emit_comment(const std::string& comment) const {
fmt::print(output_file, "// {}\n", comment);
}
void N64Recomp::CGenerator::process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const {
void N64Recomp::CGenerator::process_binary_op(const BinaryOp& op, const InstructionContext& ctx) const {
// Thread local variables to prevent allocations when possible.
// TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations.
thread_local std::string output{};
@ -521,7 +521,7 @@ void N64Recomp::CGenerator::process_binary_op(std::ostream& output_file, const B
fmt::print(output_file, "{} = {};\n", output, expression);
}
void N64Recomp::CGenerator::process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const {
void N64Recomp::CGenerator::process_unary_op(const UnaryOp& op, const InstructionContext& ctx) const {
// Thread local variables to prevent allocations when possible.
// TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations.
thread_local std::string output{};
@ -532,7 +532,7 @@ void N64Recomp::CGenerator::process_unary_op(std::ostream& output_file, const Un
fmt::print(output_file, "{} = {};\n", output, input);
}
void N64Recomp::CGenerator::process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const {
void N64Recomp::CGenerator::process_store_op(const StoreOp& op, const InstructionContext& ctx) const {
// Thread local variables to prevent allocations when possible.
// TODO these thread locals probably don't actually help right now, so figure out a better way to prevent allocations.
thread_local std::string base_str{};