From ee2e81eed256f8b115ab54c226979ac7b264cd8b Mon Sep 17 00:00:00 2001 From: Tharo <17233964+Thar0@users.noreply.github.com> Date: Sat, 11 May 2024 18:02:37 +0100 Subject: [PATCH] Implement doubleword multiply and divide, and conversions between doubleword and single/double precision floats --- src/main.cpp | 4 ---- src/recompilation.cpp | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3cdf1dd..10231ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -141,10 +141,6 @@ std::unordered_set reimplemented_funcs{ "__osInitialize_kmc", "__osInitialize_isv", "__osRdbSend", - // libgcc math routines (these throw off the recompiler) - "__udivdi3", - "__divdi3", - "__umoddi3", // ido math routines "__ull_div", "__ll_div", diff --git a/src/recompilation.cpp b/src/recompilation.cpp index e525278..b656f05 100644 --- a/src/recompilation.cpp +++ b/src/recompilation.cpp @@ -386,16 +386,28 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C case InstrId::cpu_mult: print_line("result = S64(S32({}{})) * S64(S32({}{})); lo = S32(result >> 0); hi = S32(result >> 32)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); break; + case InstrId::cpu_dmult: + print_line("MUL128_S({}{}, {}{}, hi, lo)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); + break; case InstrId::cpu_multu: print_line("result = U64(U32({}{})) * U64(U32({}{})); lo = S32(result >> 0); hi = S32(result >> 32)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); break; + case InstrId::cpu_dmultu: + print_line("MUL128_U({}{}, {}{}, hi, lo)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); + break; case InstrId::cpu_div: // Cast to 64-bits before division to prevent artihmetic exception for s32(0x80000000) / -1 print_line("lo = S32(S64(S32({}{})) / S64(S32({}{}))); hi = S32(S64(S32({}{})) % S64(S32({}{})))", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt, ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); break; + case InstrId::cpu_ddiv: + print_line("lo = S64({}{}) / S64({}{}); hi = S64({}{}) % S64({}{})", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt, ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); + break; case InstrId::cpu_divu: print_line("lo = S32(U32({}{}) / U32({}{})); hi = S32(U32({}{}) % U32({}{}))", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt, ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); break; + case InstrId::cpu_ddivu: + print_line("lo = U64({}{}) / U64({}{}); hi = U64({}{}) % U64({}{})", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt, ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt); + break; case InstrId::cpu_mflo: print_line("{}{} = lo", ctx_gpr_prefix(rd), rd); break; @@ -929,6 +941,28 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C print_line("NAN_CHECK(ctx->f{}.d)", fs); print_line("ctx->f{}.fl = CVT_S_D(ctx->f{}.d)", fd, fs); break; + case InstrId::cpu_cvt_d_l: + print_line("CHECK_FR(ctx, {})", fd); + print_line("CHECK_FR(ctx, {})", fs); + print_line("ctx->f{}.d = CVT_D_L(ctx->f{}.u64)", fd, fs); + break; + case InstrId::cpu_cvt_l_d: + print_line("CHECK_FR(ctx, {})", fd); + print_line("CHECK_FR(ctx, {})", fs); + print_line("NAN_CHECK(ctx->f{}.d)", fs); + print_line("ctx->f{}.u64 = CVT_L_D(ctx->f{}.d)", fd, fs); + break; + case InstrId::cpu_cvt_s_l: + print_line("CHECK_FR(ctx, {})", fd); + print_line("CHECK_FR(ctx, {})", fs); + print_line("ctx->f{}.fl = CVT_S_L(ctx->f{}.u64)", fd, fs); + break; + case InstrId::cpu_cvt_l_s: + print_line("CHECK_FR(ctx, {})", fd); + print_line("CHECK_FR(ctx, {})", fs); + print_line("NAN_CHECK(ctx->f{}.fl)", fs); + print_line("ctx->f{}.u64 = CVT_L_S(ctx->f{}.fl)", fd, fs); + break; case InstrId::cpu_trunc_w_s: print_line("CHECK_FR(ctx, {})", fd); print_line("CHECK_FR(ctx, {})", fs);