mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-22 03:14:59 +00:00
Removed output file from generator signatures, implement some of the luajit generator
This commit is contained in:
parent
f3f4a5cd73
commit
c54855b05d
4 changed files with 656 additions and 234 deletions
|
@ -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{};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue