diff --git a/CMakeLists.txt b/CMakeLists.txt index 2733666..99e76ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ target_sources(N64Recomp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/analysis.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/operations.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/cgenerator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/luajitgenerator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/recompilation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/mod_symbols.cpp ) diff --git a/include/generator.h b/include/generator.h index cd41b25..49973bd 100644 --- a/include/generator.h +++ b/include/generator.h @@ -97,6 +97,42 @@ namespace N64Recomp { void get_binary_expr_string(BinaryOpType type, const BinaryOperands& operands, const InstructionContext& ctx, const std::string& output, std::string& expr_string) const; void get_notation(BinaryOpType op_type, std::string& func_string, std::string& infix_string) const; }; + + class LuajitGenerator final : Generator { + public: + LuajitGenerator() = default; + void process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const final; + void process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const final; + void process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const final; + void emit_function_start(std::ostream& output_file, const std::string& function_name) const final; + void emit_function_end(std::ostream& output_file) const final; + void emit_function_call_lookup(std::ostream& output_file, uint32_t addr) const final; + void emit_function_call_by_register(std::ostream& output_file, int reg) const final; + void emit_function_call_by_name(std::ostream& output_file, const std::string& func_name) const final; + void emit_goto(std::ostream& output_file, const std::string& target) const final; + void emit_label(std::ostream& output_file, const std::string& label_name) const final; + void emit_variable_declaration(std::ostream& output_file, const std::string& var_name, int reg) const final; + void emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const final; + void emit_branch_close(std::ostream& output_file) const final; + void emit_switch(std::ostream& output_file, const std::string& jump_variable, int shift_amount) const final; + void emit_case(std::ostream& output_file, int case_index, const std::string& target_label) const final; + void emit_switch_error(std::ostream& output_file, uint32_t instr_vram, uint32_t jtbl_vram) const final; + void emit_switch_close(std::ostream& output_file) const final; + void emit_return(std::ostream& output_file) const final; + void emit_check_fr(std::ostream& output_file, int fpr) const final; + void emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const final; + void emit_cop0_status_read(std::ostream& output_file, int reg) const final; + void emit_cop0_status_write(std::ostream& output_file, int reg) const final; + void emit_cop1_cs_read(std::ostream& output_file, int reg) const final; + void emit_cop1_cs_write(std::ostream& output_file, int reg) const final; + void emit_muldiv(std::ostream& output_file, InstrId instr_id, int reg1, int reg2) const final; + void emit_syscall(std::ostream& output_file, uint32_t instr_vram) const final; + void emit_do_break(std::ostream& output_file, uint32_t instr_vram) const final; + void emit_pause_self(std::ostream& output_file) const final; + void emit_trigger_event(std::ostream& output_file, size_t event_index) const final; + void emit_comment(std::ostream& output_file, const std::string& comment) const final; + private: + }; } #endif diff --git a/include/n64recomp.h b/include/n64recomp.h index c214ac7..b197910 100644 --- a/include/n64recomp.h +++ b/include/n64recomp.h @@ -521,6 +521,7 @@ namespace N64Recomp { }; bool recompile_function(const Context& context, const Function& func, std::ofstream& output_file, std::span> static_funcs, bool tag_reference_relocs); + bool recompile_function_luajit(const Context& context, const Function& func, std::ofstream& output_file, std::span> static_funcs, bool tag_reference_relocs); enum class ModSymbolsError { Good, diff --git a/src/luajitgenerator.cpp b/src/luajitgenerator.cpp new file mode 100644 index 0000000..1074064 --- /dev/null +++ b/src/luajitgenerator.cpp @@ -0,0 +1,144 @@ +#include +#include + +#include "fmt/format.h" +#include "fmt/ostream.h" + +#include "generator.h" + +void N64Recomp::LuajitGenerator::process_binary_op(std::ostream& output_file, const BinaryOp& op, const InstructionContext& ctx) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::process_unary_op(std::ostream& output_file, const UnaryOp& op, const InstructionContext& ctx) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::process_store_op(std::ostream& output_file, const StoreOp& op, const InstructionContext& ctx) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_function_start(std::ostream& output_file, const std::string& function_name) const { + fmt::print(output_file, "function {}(rdram, ctx)\n", function_name); +} + +void N64Recomp::LuajitGenerator::emit_function_end(std::ostream& output_file) const { + fmt::print(output_file, "end\n"); +} + +void N64Recomp::LuajitGenerator::emit_function_call_lookup(std::ostream& output_file, uint32_t addr) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_function_call_by_register(std::ostream& output_file, int reg) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_function_call_by_name(std::ostream& output_file, const std::string& func_name) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_goto(std::ostream& output_file, const std::string& target) const { + fmt::print(output_file, "goto {}\n", target); +} + +void N64Recomp::LuajitGenerator::emit_label(std::ostream& output_file, const std::string& label_name) const { + fmt::print(output_file, "::{}::\n", label_name); +} + +void N64Recomp::LuajitGenerator::emit_variable_declaration(std::ostream& output_file, const std::string& var_name, int reg) const { + // TODO + fmt::print(output_file, "{} = 0\n", var_name); +} + +void N64Recomp::LuajitGenerator::emit_branch_condition(std::ostream& output_file, const ConditionalBranchOp& op, const InstructionContext& ctx) const { + // TODO + fmt::print(output_file, "if (true) then\n"); +} + +void N64Recomp::LuajitGenerator::emit_branch_close(std::ostream& output_file) const { + fmt::print(output_file, "end\n"); +} + +void N64Recomp::LuajitGenerator::emit_switch(std::ostream& output_file, const std::string& jump_variable, int shift_amount) const { + fmt::print(output_file, "do local case_index = bit.rshift({}, {}ULL)\n", jump_variable, shift_amount); +} + +void N64Recomp::LuajitGenerator::emit_case(std::ostream& output_file, int case_index, const std::string& target_label) const { + fmt::print(output_file, "if case_index == {} then goto {} end\n", case_index, target_label); +} + +void N64Recomp::LuajitGenerator::emit_switch_error(std::ostream& output_file, uint32_t instr_vram, uint32_t jtbl_vram) const { + fmt::print(output_file, "switch_error(\'lua\', {:08X}, {:08X})\n", instr_vram, jtbl_vram); +} + +void N64Recomp::LuajitGenerator::emit_switch_close(std::ostream& output_file) const { + fmt::print(output_file, "end\n"); +} + +void N64Recomp::LuajitGenerator::emit_return(std::ostream& output_file) const { + fmt::print(output_file, "return\n"); +} + +void N64Recomp::LuajitGenerator::emit_check_fr(std::ostream& output_file, int fpr) const { + // Not used +} + +void N64Recomp::LuajitGenerator::emit_check_nan(std::ostream& output_file, int fpr, bool is_double) const { + // Not used +} + +void N64Recomp::LuajitGenerator::emit_cop0_status_read(std::ostream& output_file, int reg) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_cop0_status_write(std::ostream& output_file, int reg) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_cop1_cs_read(std::ostream& output_file, int reg) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_cop1_cs_write(std::ostream& output_file, int reg) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_muldiv(std::ostream& output_file, InstrId instr_id, int reg1, int reg2) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_syscall(std::ostream& output_file, uint32_t instr_vram) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_do_break(std::ostream& output_file, uint32_t instr_vram) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_pause_self(std::ostream& output_file) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_trigger_event(std::ostream& output_file, size_t event_index) const { + // TODO + fmt::print(output_file, "\n"); +} + +void N64Recomp::LuajitGenerator::emit_comment(std::ostream& output_file, const std::string& comment) const { + fmt::print(output_file, "-- {}\n", comment); +} diff --git a/src/recompilation.cpp b/src/recompilation.cpp index dcee470..8b6941c 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -604,7 +604,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con instruction_context.reloc_section_index = reloc_section; instruction_context.reloc_target_section_offset = reloc_target_section_offset; - auto do_check_fr = [](std::ostream& output_file, const CGenerator& generator, const InstructionContext& ctx, Operand operand) { + auto do_check_fr = [](std::ostream& output_file, const GeneratorType& generator, const InstructionContext& ctx, Operand operand) { switch (operand) { case Operand::Fd: case Operand::FdDouble: @@ -633,7 +633,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con } }; - auto do_check_nan = [](std::ostream& output_file, const CGenerator& generator, const InstructionContext& ctx, Operand operand) { + auto do_check_nan = [](std::ostream& output_file, const GeneratorType& generator, const InstructionContext& ctx, Operand operand) { switch (operand) { case Operand::Fd: generator.emit_check_nan(output_file, ctx.fd, false); @@ -869,3 +869,8 @@ bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64R CGenerator generator{}; return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs); } + +bool N64Recomp::recompile_function_luajit(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ofstream& output_file, std::span> static_funcs_out, bool tag_reference_relocs) { + LuajitGenerator generator{}; + return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs); +}