mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-22 03:14:59 +00:00
Moved remaining instruction processing text generation into Generator class
This commit is contained in:
parent
d33d381617
commit
053242263f
5 changed files with 332 additions and 151 deletions
|
@ -365,6 +365,46 @@ 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 {
|
||||
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
|
||||
" uint64_t hi = 0, lo = 0, result = 0;\n"
|
||||
" unsigned int rounding_mode = DEFAULT_ROUNDING_MODE;\n"
|
||||
" int c1cs = 0;\n", // cop1 conditional signal
|
||||
function_name);
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_function_end(std::ostream& output_file) const {
|
||||
fmt::print(output_file, ";}}\n");
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_function_call_lookup(std::ostream& output_file, 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 {
|
||||
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 {
|
||||
fmt::print(output_file, "{}(rdram, ctx);\n", func_name);
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_goto(std::ostream& output_file, 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 {
|
||||
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 {
|
||||
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 {
|
||||
// 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.
|
||||
|
@ -374,7 +414,27 @@ void N64Recomp::CGenerator::emit_branch_condition(std::ostream& output_file, con
|
|||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_branch_close(std::ostream& output_file) const {
|
||||
fmt::print(output_file, " }}\n");
|
||||
fmt::print(output_file, "}}\n");
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_switch_close(std::ostream& output_file) const {
|
||||
fmt::print(output_file, "}}\n");
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_switch(std::ostream& output_file, 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 {
|
||||
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 {
|
||||
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 {
|
||||
fmt::print(output_file, "return;\n");
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_check_fr(std::ostream& output_file, int fpr) const {
|
||||
|
@ -385,6 +445,72 @@ void N64Recomp::CGenerator::emit_check_nan(std::ostream& output_file, int fpr, b
|
|||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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));
|
||||
break;
|
||||
case InstrId::cpu_dmult:
|
||||
fmt::print(output_file, "DMULT(S64({}), S64({}), &lo, &hi);\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_multu:
|
||||
fmt::print(output_file, "result = U64(U32({})) * U64(U32({})); lo = S32(result >> 0); hi = S32(result >> 32);\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_dmultu:
|
||||
fmt::print(output_file, "DMULTU(U64({}), U64({}), &lo, &hi);\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_div:
|
||||
// Cast to 64-bits before division to prevent artihmetic exception for s32(0x80000000) / -1
|
||||
fmt::print(output_file, "lo = S32(S64(S32({0})) / S64(S32({1}))); hi = S32(S64(S32({0})) % S64(S32({1})));\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_ddiv:
|
||||
fmt::print(output_file, "DDIV(S64({}), S64({}), &lo, &hi);\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_divu:
|
||||
fmt::print(output_file, "lo = S32(U32({0}) / U32({1})); hi = S32(U32({0}) % U32({1}));\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
case InstrId::cpu_ddivu:
|
||||
fmt::print(output_file, "DDIVU(U64({}), U64({}), &lo, &hi);\n", gpr_to_string(reg1), gpr_to_string(reg2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_syscall(std::ostream& output_file, 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 {
|
||||
fmt::print(output_file, "do_break({});\n", instr_vram);
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_pause_self(std::ostream& output_file) const {
|
||||
fmt::print(output_file, "pause_self(rdram);\n");
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::emit_trigger_event(std::ostream& output_file, 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 {
|
||||
fmt::print(output_file, "// {}\n", comment);
|
||||
}
|
||||
|
||||
void N64Recomp::CGenerator::process_binary_op(std::ostream& output_file, 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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue