}
#endif
-#if !LJ_TARGET_X86ORX64
+#if !LJ_64
/* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */
static void ra_destpair(ASMState *as, IRIns *ir)
{
/* Check for conflicts and shuffle the registers as needed. */
if (destlo == RID_RETHI) {
if (desthi == RID_RETLO) {
+#if LJ_TARGET_X86
+ *--as->mcp = XI_XCHGa + RID_RETHI;
+#else
emit_movrr(as, ir, RID_RETHI, RID_TMP);
emit_movrr(as, ir, RID_RETLO, RID_RETHI);
emit_movrr(as, ir, RID_TMP, RID_RETLO);
+#endif
} else {
emit_movrr(as, ir, RID_RETHI, RID_RETLO);
if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI);
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
{
RegSet drop = RSET_SCRATCH;
+ int hiop = (LJ_32 && (ir+1)->o == IR_HIOP);
if ((ci->flags & CCI_NOFPRCLOBBER))
drop &= ~RSET_FPR;
if (ra_hasreg(ir->r))
rset_clear(drop, ir->r); /* Dest reg handled below. */
+ if (hiop && ra_hasreg((ir+1)->r))
+ rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
ra_evictset(as, drop); /* Evictions must be performed first. */
if (ra_used(ir)) {
if (irt_isfp(ir->t)) {
irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs);
}
#endif
+ } else if (hiop) {
+ ra_destpair(as, ir);
} else {
lua_assert(!irt_ispri(ir->t));
ra_destreg(as, ir, RID_RET);
}
case IR_CALLN:
case IR_CALLXS:
- ra_destreg(as, ir, RID_RETHI);
if (!uselo)
- ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark call as used. */
+ ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
case IR_CNEWI:
/* Nothing to do here. Handled by CNEWI itself. */