Implement doubleword multiply and divide, and conversions between doubleword and single/double precision floats (#16)

This commit is contained in:
Tharo 2024-05-11 19:08:15 +01:00 committed by GitHub
parent 5838e4223a
commit dbf0e623c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 34 additions and 4 deletions

View file

@ -141,10 +141,6 @@ std::unordered_set<std::string> reimplemented_funcs{
"__osInitialize_kmc", "__osInitialize_kmc",
"__osInitialize_isv", "__osInitialize_isv",
"__osRdbSend", "__osRdbSend",
// libgcc math routines (these throw off the recompiler)
"__udivdi3",
"__divdi3",
"__umoddi3",
// ido math routines // ido math routines
"__ull_div", "__ull_div",
"__ll_div", "__ll_div",

View file

@ -386,16 +386,28 @@ bool process_instruction(const RecompPort::Context& context, const RecompPort::C
case InstrId::cpu_mult: 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); 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; break;
case InstrId::cpu_dmult:
print_line("DMULT(S64({}{}), S64({}{}), &lo, &hi)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt);
break;
case InstrId::cpu_multu: 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); 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; break;
case InstrId::cpu_dmultu:
print_line("DMULTU(U64({}{}), U64({}{}), &lo, &hi)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt);
break;
case InstrId::cpu_div: case InstrId::cpu_div:
// Cast to 64-bits before division to prevent artihmetic exception for s32(0x80000000) / -1 // 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); 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; break;
case InstrId::cpu_ddiv:
print_line("DDIV(S64({}{}), S64({}{}), &lo, &hi)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt);
break;
case InstrId::cpu_divu: 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); 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; break;
case InstrId::cpu_ddivu:
print_line("DDIVU(U64({}{}), U64({}{}), &lo, &hi)", ctx_gpr_prefix(rs), rs, ctx_gpr_prefix(rt), rt);
break;
case InstrId::cpu_mflo: case InstrId::cpu_mflo:
print_line("{}{} = lo", ctx_gpr_prefix(rd), rd); print_line("{}{} = lo", ctx_gpr_prefix(rd), rd);
break; 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("NAN_CHECK(ctx->f{}.d)", fs);
print_line("ctx->f{}.fl = CVT_S_D(ctx->f{}.d)", fd, fs); print_line("ctx->f{}.fl = CVT_S_D(ctx->f{}.d)", fd, fs);
break; 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: case InstrId::cpu_trunc_w_s:
print_line("CHECK_FR(ctx, {})", fd); print_line("CHECK_FR(ctx, {})", fd);
print_line("CHECK_FR(ctx, {})", fs); print_line("CHECK_FR(ctx, {})", fs);