mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-14 08:12:19 +00:00
Split Negate operation into NegateFloat and NegateDouble, added support for custom recompiler backends
This commit is contained in:
parent
c54855b05d
commit
485a9e14c9
6 changed files with 28 additions and 35 deletions
|
@ -517,8 +517,10 @@ namespace N64Recomp {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool recompile_function(const Context& context, const Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool tag_reference_relocs);
|
class Generator;
|
||||||
bool recompile_function_luajit(const Context& context, const Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool tag_reference_relocs);
|
bool recompile_function(const Context& context, const Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool tag_reference_relocs);
|
||||||
|
bool recompile_function_luajit(const Context& context, const Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool tag_reference_relocs);
|
||||||
|
bool recompile_function_custom(Generator& generator, const Context& context, const Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs);
|
||||||
|
|
||||||
enum class ModSymbolsError {
|
enum class ModSymbolsError {
|
||||||
Good,
|
Good,
|
||||||
|
|
|
@ -28,13 +28,12 @@ namespace N64Recomp {
|
||||||
ToU32,
|
ToU32,
|
||||||
ToS64,
|
ToS64,
|
||||||
ToU64,
|
ToU64,
|
||||||
NegateS32,
|
|
||||||
NegateS64,
|
|
||||||
Lui,
|
Lui,
|
||||||
Mask5, // Mask to 5 bits
|
Mask5, // Mask to 5 bits
|
||||||
Mask6, // Mask to 5 bits
|
Mask6, // Mask to 5 bits
|
||||||
ToInt32, // Functionally equivalent to ToS32, only exists for parity with old codegen
|
ToInt32, // Functionally equivalent to ToS32, only exists for parity with old codegen
|
||||||
Negate,
|
NegateFloat,
|
||||||
|
NegateDouble,
|
||||||
AbsFloat,
|
AbsFloat,
|
||||||
AbsDouble,
|
AbsDouble,
|
||||||
SqrtFloat,
|
SqrtFloat,
|
||||||
|
|
|
@ -223,12 +223,6 @@ void N64Recomp::CGenerator::get_operand_string(Operand operand, UnaryOpType oper
|
||||||
case UnaryOpType::ToU64:
|
case UnaryOpType::ToU64:
|
||||||
// Nothing to do here, they're already U64
|
// Nothing to do here, they're already U64
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::NegateS32:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
case UnaryOpType::NegateS64:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
case UnaryOpType::Lui:
|
case UnaryOpType::Lui:
|
||||||
operand_string = "S32(" + operand_string + " << 16)";
|
operand_string = "S32(" + operand_string + " << 16)";
|
||||||
break;
|
break;
|
||||||
|
@ -241,7 +235,10 @@ void N64Recomp::CGenerator::get_operand_string(Operand operand, UnaryOpType oper
|
||||||
case UnaryOpType::ToInt32:
|
case UnaryOpType::ToInt32:
|
||||||
operand_string = "(int32_t)" + operand_string;
|
operand_string = "(int32_t)" + operand_string;
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::Negate:
|
case UnaryOpType::NegateFloat:
|
||||||
|
operand_string = "-" + operand_string;
|
||||||
|
break;
|
||||||
|
case UnaryOpType::NegateDouble:
|
||||||
operand_string = "-" + operand_string;
|
operand_string = "-" + operand_string;
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::AbsFloat:
|
case UnaryOpType::AbsFloat:
|
||||||
|
|
|
@ -224,12 +224,6 @@ void N64Recomp::LuajitGenerator::get_operand_string(Operand operand, UnaryOpType
|
||||||
case UnaryOpType::ToU64:
|
case UnaryOpType::ToU64:
|
||||||
// Nothing to do here, they're already U64
|
// Nothing to do here, they're already U64
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::NegateS32:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
case UnaryOpType::NegateS64:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
case UnaryOpType::Lui:
|
case UnaryOpType::Lui:
|
||||||
operand_string = "S32(bit.lshift(" + operand_string + "), 16ULL)";
|
operand_string = "S32(bit.lshift(" + operand_string + "), 16ULL)";
|
||||||
break;
|
break;
|
||||||
|
@ -239,7 +233,10 @@ void N64Recomp::LuajitGenerator::get_operand_string(Operand operand, UnaryOpType
|
||||||
case UnaryOpType::Mask6:
|
case UnaryOpType::Mask6:
|
||||||
operand_string = "(bit.band(" + operand_string + "), 63ULL)";
|
operand_string = "(bit.band(" + operand_string + "), 63ULL)";
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::Negate:
|
case UnaryOpType::NegateFloat:
|
||||||
|
operand_string = "-" + operand_string;
|
||||||
|
break;
|
||||||
|
case UnaryOpType::NegateDouble:
|
||||||
operand_string = "-" + operand_string;
|
operand_string = "-" + operand_string;
|
||||||
break;
|
break;
|
||||||
case UnaryOpType::AbsFloat:
|
case UnaryOpType::AbsFloat:
|
||||||
|
|
|
@ -12,8 +12,8 @@ namespace N64Recomp {
|
||||||
// Float operations
|
// Float operations
|
||||||
{ InstrId::cpu_mov_s, { UnaryOpType::None, Operand::Fd, Operand::Fs, true } },
|
{ InstrId::cpu_mov_s, { UnaryOpType::None, Operand::Fd, Operand::Fs, true } },
|
||||||
{ InstrId::cpu_mov_d, { UnaryOpType::None, Operand::FdDouble, Operand::FsDouble, true } },
|
{ InstrId::cpu_mov_d, { UnaryOpType::None, Operand::FdDouble, Operand::FsDouble, true } },
|
||||||
{ InstrId::cpu_neg_s, { UnaryOpType::Negate, Operand::Fd, Operand::Fs, true, true } },
|
{ InstrId::cpu_neg_s, { UnaryOpType::NegateFloat, Operand::Fd, Operand::Fs, true, true } },
|
||||||
{ InstrId::cpu_neg_d, { UnaryOpType::Negate, Operand::FdDouble, Operand::FsDouble, true, true } },
|
{ InstrId::cpu_neg_d, { UnaryOpType::NegateDouble, Operand::FdDouble, Operand::FsDouble, true, true } },
|
||||||
{ InstrId::cpu_abs_s, { UnaryOpType::AbsFloat, Operand::Fd, Operand::Fs, true, true } },
|
{ InstrId::cpu_abs_s, { UnaryOpType::AbsFloat, Operand::Fd, Operand::Fs, true, true } },
|
||||||
{ InstrId::cpu_abs_d, { UnaryOpType::AbsDouble, Operand::FdDouble, Operand::FsDouble, true, true } },
|
{ InstrId::cpu_abs_d, { UnaryOpType::AbsDouble, Operand::FdDouble, Operand::FsDouble, true, true } },
|
||||||
{ InstrId::cpu_sqrt_s, { UnaryOpType::SqrtFloat, Operand::Fd, Operand::Fs, true, true } },
|
{ InstrId::cpu_sqrt_s, { UnaryOpType::SqrtFloat, Operand::Fd, Operand::Fs, true, true } },
|
||||||
|
|
|
@ -110,7 +110,7 @@ std::string_view ctx_gpr_prefix(int reg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename GeneratorType>
|
template <typename GeneratorType>
|
||||||
bool process_instruction(GeneratorType& generator, const N64Recomp::Context& context, const N64Recomp::Function& func, const N64Recomp::FunctionStats& stats, const std::unordered_set<uint32_t>& skipped_insns, size_t instr_index, const std::vector<rabbitizer::InstructionCpu>& instructions, std::ofstream& output_file, bool indent, bool emit_link_branch, int link_branch_index, size_t reloc_index, bool& needs_link_branch, bool& is_branch_likely, bool tag_reference_relocs, std::span<std::vector<uint32_t>> static_funcs_out) {
|
bool process_instruction(GeneratorType& generator, const N64Recomp::Context& context, const N64Recomp::Function& func, const N64Recomp::FunctionStats& stats, const std::unordered_set<uint32_t>& skipped_insns, size_t instr_index, const std::vector<rabbitizer::InstructionCpu>& instructions, std::ostream& output_file, bool indent, bool emit_link_branch, int link_branch_index, size_t reloc_index, bool& needs_link_branch, bool& is_branch_likely, bool tag_reference_relocs, std::span<std::vector<uint32_t>> static_funcs_out) {
|
||||||
using namespace N64Recomp;
|
using namespace N64Recomp;
|
||||||
|
|
||||||
const auto& section = context.sections[func.section_index];
|
const auto& section = context.sections[func.section_index];
|
||||||
|
@ -260,16 +260,6 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto print_func_call_lookup = [&](uint32_t target_vram) {
|
|
||||||
if (!process_delay_slot(false)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
print_indent();
|
|
||||||
generator.emit_function_call_lookup(target_vram);
|
|
||||||
print_link_branch();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto print_func_call_by_address = [&generator, reloc_target_section_offset, reloc_section, reloc_reference_symbol, reloc_type, &context, §ion, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &output_file, &print_link_branch]
|
auto print_func_call_by_address = [&generator, reloc_target_section_offset, reloc_section, reloc_reference_symbol, reloc_type, &context, §ion, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &output_file, &print_link_branch]
|
||||||
(uint32_t target_func_vram, bool tail_call = false, bool indent = false)
|
(uint32_t target_func_vram, bool tail_call = false, bool indent = false)
|
||||||
{
|
{
|
||||||
|
@ -364,6 +354,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
}
|
}
|
||||||
print_indent();
|
print_indent();
|
||||||
generator.emit_return();
|
generator.emit_return();
|
||||||
|
// TODO check if this branch close should exist.
|
||||||
print_indent();
|
print_indent();
|
||||||
generator.emit_branch_close();
|
generator.emit_branch_close();
|
||||||
return true;
|
return true;
|
||||||
|
@ -379,6 +370,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
print_indent();
|
print_indent();
|
||||||
print_indent();
|
print_indent();
|
||||||
generator.emit_goto(fmt::format("L_{:08X}", branch_target));
|
generator.emit_goto(fmt::format("L_{:08X}", branch_target));
|
||||||
|
// TODO check if this link branch ever exists.
|
||||||
if (needs_link_branch) {
|
if (needs_link_branch) {
|
||||||
print_indent();
|
print_indent();
|
||||||
print_indent();
|
print_indent();
|
||||||
|
@ -704,6 +696,8 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
auto find_conditional_branch_it = conditional_branch_ops.find(instr.getUniqueId());
|
auto find_conditional_branch_it = conditional_branch_ops.find(instr.getUniqueId());
|
||||||
if (find_conditional_branch_it != conditional_branch_ops.end()) {
|
if (find_conditional_branch_it != conditional_branch_ops.end()) {
|
||||||
print_indent();
|
print_indent();
|
||||||
|
// TODO combining the branch condition and branch target into one generator call would allow better optimization in the runtime's JIT generator.
|
||||||
|
// This would require splitting into a conditional jump method and conditional function call method.
|
||||||
generator.emit_branch_condition(find_conditional_branch_it->second, instruction_context);
|
generator.emit_branch_condition(find_conditional_branch_it->second, instruction_context);
|
||||||
|
|
||||||
print_indent();
|
print_indent();
|
||||||
|
@ -753,7 +747,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename GeneratorType>
|
template <typename GeneratorType>
|
||||||
bool recompile_function_impl(GeneratorType& generator, const N64Recomp::Context& context, const N64Recomp::Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
bool recompile_function_impl(GeneratorType& generator, const N64Recomp::Context& context, const N64Recomp::Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
||||||
//fmt::print("Recompiling {}\n", func.name);
|
//fmt::print("Recompiling {}\n", func.name);
|
||||||
std::vector<rabbitizer::InstructionCpu> instructions;
|
std::vector<rabbitizer::InstructionCpu> instructions;
|
||||||
|
|
||||||
|
@ -859,12 +853,16 @@ bool recompile_function_impl(GeneratorType& generator, const N64Recomp::Context&
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the templated function with CGenerator as the template parameter.
|
// Wrap the templated function with CGenerator as the template parameter.
|
||||||
bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
bool N64Recomp::recompile_function(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
||||||
CGenerator generator{output_file};
|
CGenerator generator{output_file};
|
||||||
return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs);
|
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<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
bool N64Recomp::recompile_function_luajit(const N64Recomp::Context& context, const N64Recomp::Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
||||||
LuajitGenerator generator{output_file};
|
LuajitGenerator generator{output_file};
|
||||||
return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs);
|
return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool N64Recomp::recompile_function_custom(Generator& generator, const Context& context, const Function& func, std::ostream& output_file, std::span<std::vector<uint32_t>> static_funcs_out, bool tag_reference_relocs) {
|
||||||
|
return recompile_function_impl(generator, context, func, output_file, static_funcs_out, tag_reference_relocs);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue