diff --git a/ps2xRecomp/src/lib/control_flow_emitter.cpp b/ps2xRecomp/src/lib/control_flow_emitter.cpp index 4bf8dc550..ce3020675 100644 --- a/ps2xRecomp/src/lib/control_flow_emitter.cpp +++ b/ps2xRecomp/src/lib/control_flow_emitter.cpp @@ -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"; }