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, |
