Fix sign extension issue with mfc1, add TODO for banker's rounding

This commit is contained in:
Mr-Wiseguy 2025-01-25 21:17:55 -05:00
parent e2e5b349b4
commit cb2a5487e2
2 changed files with 14 additions and 3 deletions

View file

@ -797,6 +797,7 @@ void N64Recomp::LiveGenerator::process_binary_op(const BinaryOp& op, const Instr
} }
} }
// TODO these four operations should use banker's rounding, but roundeven is C23 so it's unavailable here.
int32_t do_round_w_s(float num) { int32_t do_round_w_s(float num) {
return lroundf(num); return lroundf(num);
} }
@ -1092,7 +1093,13 @@ void N64Recomp::LiveGenerator::process_unary_op(const UnaryOp& op, const Instruc
break; break;
case UnaryOpType::ToS32: case UnaryOpType::ToS32:
case UnaryOpType::ToInt32: case UnaryOpType::ToInt32:
jit_op = SLJIT_MOV_S32; // sljit won't emit a sign extension with SLJIT_MOV_32 if the destination is memory,
// so emit an explicit move into a register and set that register as the new src.
sljit_emit_op1(compiler, SLJIT_MOV_S32, Registers::arithmetic_temp1, 0, src, srcw);
// Replace the original input with the temporary register.
src = Registers::arithmetic_temp1;
srcw = 0;
jit_op = SLJIT_MOV;
break; break;
// Unary ops that can't be used as a standalone operation // Unary ops that can't be used as a standalone operation
case UnaryOpType::ToU32: case UnaryOpType::ToU32:
@ -1665,8 +1672,11 @@ void N64Recomp::LiveGenerator::emit_cop1_cs_read(int reg) const {
// Call get_cop1_cs. // Call get_cop1_cs.
sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS0(32), SLJIT_IMM, sljit_sw(get_cop1_cs)); sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS0(32), SLJIT_IMM, sljit_sw(get_cop1_cs));
// Store the result in the output register. // Sign extend the result into a temp register.
sljit_emit_op1(compiler, SLJIT_MOV_S32, dst, dstw, SLJIT_RETURN_REG, 0); sljit_emit_op1(compiler, SLJIT_MOV_S32, Registers::arithmetic_temp1, 0, SLJIT_RETURN_REG, 0);
// Move the sign extended result into the destination.
sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, Registers::arithmetic_temp1, 0);
} }
} }

View file

@ -301,6 +301,7 @@ void N64Recomp::CGenerator::get_operand_string(Operand operand, UnaryOpType oper
case UnaryOpType::TruncateLFromD: case UnaryOpType::TruncateLFromD:
operand_string = "TRUNC_L_D(" + operand_string + ")"; operand_string = "TRUNC_L_D(" + operand_string + ")";
break; break;
// TODO these four operations should use banker's rounding, but roundeven is C23 so it's unavailable here.
case UnaryOpType::RoundWFromS: case UnaryOpType::RoundWFromS:
operand_string = "lroundf(" + operand_string + ")"; operand_string = "lroundf(" + operand_string + ")";
break; break;