diff options
author | Mike Pall <mike> | 2012-09-27 14:16:18 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-09-27 14:16:18 +0200 |
commit | 0ecdff43e80dcd1d489c3daca0077dbfae9042b6 (patch) | |
tree | e5b58de741d0d23ee3296ae08e2a1d86eeb13c6e /src | |
parent | cfca926cc2e2b63e94492f0a1f5c033f6db3a6f5 (diff) | |
download | luajit-0ecdff43e80dcd1d489c3daca0077dbfae9042b6.tar.gz luajit-0ecdff43e80dcd1d489c3daca0077dbfae9042b6.tar.bz2 luajit-0ecdff43e80dcd1d489c3daca0077dbfae9042b6.zip |
x86: Fix register allocation for calls returning register pair.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 6 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 8 | ||||
-rw-r--r-- | src/lj_target_x86.h | 1 |
3 files changed, 12 insertions, 3 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 79097759..6afc70a0 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -719,7 +719,7 @@ static void ra_leftov(ASMState *as, Reg dest, IRRef lref) | |||
719 | } | 719 | } |
720 | #endif | 720 | #endif |
721 | 721 | ||
722 | #if !LJ_TARGET_X86ORX64 | 722 | #if !LJ_64 |
723 | /* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */ | 723 | /* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */ |
724 | static void ra_destpair(ASMState *as, IRIns *ir) | 724 | static void ra_destpair(ASMState *as, IRIns *ir) |
725 | { | 725 | { |
@@ -747,9 +747,13 @@ static void ra_destpair(ASMState *as, IRIns *ir) | |||
747 | /* Check for conflicts and shuffle the registers as needed. */ | 747 | /* Check for conflicts and shuffle the registers as needed. */ |
748 | if (destlo == RID_RETHI) { | 748 | if (destlo == RID_RETHI) { |
749 | if (desthi == RID_RETLO) { | 749 | if (desthi == RID_RETLO) { |
750 | #if LJ_TARGET_X86 | ||
751 | *--as->mcp = XI_XCHGa + RID_RETHI; | ||
752 | #else | ||
750 | emit_movrr(as, ir, RID_RETHI, RID_TMP); | 753 | emit_movrr(as, ir, RID_RETHI, RID_TMP); |
751 | emit_movrr(as, ir, RID_RETLO, RID_RETHI); | 754 | emit_movrr(as, ir, RID_RETLO, RID_RETHI); |
752 | emit_movrr(as, ir, RID_TMP, RID_RETLO); | 755 | emit_movrr(as, ir, RID_TMP, RID_RETLO); |
756 | #endif | ||
753 | } else { | 757 | } else { |
754 | emit_movrr(as, ir, RID_RETHI, RID_RETLO); | 758 | emit_movrr(as, ir, RID_RETHI, RID_RETLO); |
755 | if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); | 759 | if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); |
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index da4cf7e2..7288d72a 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
@@ -510,10 +510,13 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) | |||
510 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | 510 | static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) |
511 | { | 511 | { |
512 | RegSet drop = RSET_SCRATCH; | 512 | RegSet drop = RSET_SCRATCH; |
513 | int hiop = (LJ_32 && (ir+1)->o == IR_HIOP); | ||
513 | if ((ci->flags & CCI_NOFPRCLOBBER)) | 514 | if ((ci->flags & CCI_NOFPRCLOBBER)) |
514 | drop &= ~RSET_FPR; | 515 | drop &= ~RSET_FPR; |
515 | if (ra_hasreg(ir->r)) | 516 | if (ra_hasreg(ir->r)) |
516 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 517 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
518 | if (hiop && ra_hasreg((ir+1)->r)) | ||
519 | rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ | ||
517 | ra_evictset(as, drop); /* Evictions must be performed first. */ | 520 | ra_evictset(as, drop); /* Evictions must be performed first. */ |
518 | if (ra_used(ir)) { | 521 | if (ra_used(ir)) { |
519 | if (irt_isfp(ir->t)) { | 522 | if (irt_isfp(ir->t)) { |
@@ -547,6 +550,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
547 | irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs); | 550 | irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs); |
548 | } | 551 | } |
549 | #endif | 552 | #endif |
553 | } else if (hiop) { | ||
554 | ra_destpair(as, ir); | ||
550 | } else { | 555 | } else { |
551 | lua_assert(!irt_ispri(ir->t)); | 556 | lua_assert(!irt_ispri(ir->t)); |
552 | ra_destreg(as, ir, RID_RET); | 557 | ra_destreg(as, ir, RID_RET); |
@@ -2288,9 +2293,8 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
2288 | } | 2293 | } |
2289 | case IR_CALLN: | 2294 | case IR_CALLN: |
2290 | case IR_CALLXS: | 2295 | case IR_CALLXS: |
2291 | ra_destreg(as, ir, RID_RETHI); | ||
2292 | if (!uselo) | 2296 | if (!uselo) |
2293 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark call as used. */ | 2297 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
2294 | break; | 2298 | break; |
2295 | case IR_CNEWI: | 2299 | case IR_CNEWI: |
2296 | /* Nothing to do here. Handled by CNEWI itself. */ | 2300 | /* Nothing to do here. Handled by CNEWI itself. */ |
diff --git a/src/lj_target_x86.h b/src/lj_target_x86.h index cc15490b..c718bdb5 100644 --- a/src/lj_target_x86.h +++ b/src/lj_target_x86.h | |||
@@ -191,6 +191,7 @@ typedef struct { | |||
191 | typedef enum { | 191 | typedef enum { |
192 | /* Fixed length opcodes. XI_* prefix. */ | 192 | /* Fixed length opcodes. XI_* prefix. */ |
193 | XI_NOP = 0x90, | 193 | XI_NOP = 0x90, |
194 | XI_XCHGa = 0x90, | ||
194 | XI_CALL = 0xe8, | 195 | XI_CALL = 0xe8, |
195 | XI_JMP = 0xe9, | 196 | XI_JMP = 0xe9, |
196 | XI_JMPs = 0xeb, | 197 | XI_JMPs = 0xeb, |