mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-29 01:47:44 -04:00
Compare all 64 bits in the relational branches
BEQ and BNE already compare the full GPR, but BLEZ, BGTZ, BLTZ and BGEZ (and their likely/and-link variants) were emitted against the low word only. The R5900 compares the whole 64-bit register, so any value whose upper half is significant takes the wrong branch. Compilers reach these opcodes through the dsll32/dsra32 sign-extension idiom, which leaves a canonical value and hides the bug; code that keeps a genuine 64-bit quantity in the register does not.
This commit is contained in:
@@ -404,12 +404,16 @@ namespace ps2recomp
|
||||
case OPCODE_BNE:
|
||||
case OPCODE_BNEL:
|
||||
return fmt::format("GPR_U64(ctx, {}) != GPR_U64(ctx, {})", rsReg, rtReg);
|
||||
// The R5900 compares the full 64-bit GPR for the relational branches, as it
|
||||
// already does for BEQ/BNE above. Comparing only the low word takes the wrong
|
||||
// branch whenever the upper half is significant, which happens with the
|
||||
// dsll32/dsra32 sign-extension idiom compilers emit ahead of these opcodes.
|
||||
case OPCODE_BLEZ:
|
||||
case OPCODE_BLEZL:
|
||||
return fmt::format("GPR_S32(ctx, {}) <= 0", rsReg);
|
||||
return fmt::format("GPR_S64(ctx, {}) <= 0", rsReg);
|
||||
case OPCODE_BGTZ:
|
||||
case OPCODE_BGTZL:
|
||||
return fmt::format("GPR_S32(ctx, {}) > 0", rsReg);
|
||||
return fmt::format("GPR_S64(ctx, {}) > 0", rsReg);
|
||||
case OPCODE_REGIMM:
|
||||
switch (m_branchInst.rt)
|
||||
{
|
||||
@@ -417,12 +421,12 @@ namespace ps2recomp
|
||||
case REGIMM_BLTZL:
|
||||
case REGIMM_BLTZAL:
|
||||
case REGIMM_BLTZALL:
|
||||
return fmt::format("GPR_S32(ctx, {}) < 0", rsReg);
|
||||
return fmt::format("GPR_S64(ctx, {}) < 0", rsReg);
|
||||
case REGIMM_BGEZ:
|
||||
case REGIMM_BGEZL:
|
||||
case REGIMM_BGEZAL:
|
||||
case REGIMM_BGEZALL:
|
||||
return fmt::format("GPR_S32(ctx, {}) >= 0", rsReg);
|
||||
return fmt::format("GPR_S64(ctx, {}) >= 0", rsReg);
|
||||
default:
|
||||
return "false";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user