diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_asm_x86.h | 175 |
1 files changed, 53 insertions, 122 deletions
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index 1e32b6c9..e79dca93 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
@@ -576,15 +576,6 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) | |||
576 | } | 576 | } |
577 | } | 577 | } |
578 | 578 | ||
579 | static void asm_call(ASMState *as, IRIns *ir) | ||
580 | { | ||
581 | IRRef args[CCI_NARGS_MAX]; | ||
582 | const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; | ||
583 | asm_collectargs(as, ir, ci, args); | ||
584 | asm_setupresult(as, ir, ci); | ||
585 | asm_gencall(as, ci, args); | ||
586 | } | ||
587 | |||
588 | /* Return a constant function pointer or NULL for indirect calls. */ | 579 | /* Return a constant function pointer or NULL for indirect calls. */ |
589 | static void *asm_callx_func(ASMState *as, IRIns *irf, IRRef func) | 580 | static void *asm_callx_func(ASMState *as, IRIns *irf, IRRef func) |
590 | { | 581 | { |
@@ -891,6 +882,14 @@ static void asm_conv_int64_fp(ASMState *as, IRIns *ir) | |||
891 | st == IRT_NUM ? XOg_FLDq: XOg_FLDd, | 882 | st == IRT_NUM ? XOg_FLDq: XOg_FLDd, |
892 | asm_fuseload(as, ir->op1, RSET_EMPTY)); | 883 | asm_fuseload(as, ir->op1, RSET_EMPTY)); |
893 | } | 884 | } |
885 | |||
886 | static void asm_conv64(ASMState *as, IRIns *ir) | ||
887 | { | ||
888 | if (irt_isfp(ir->t)) | ||
889 | asm_conv_fp_int64(as, ir); | ||
890 | else | ||
891 | asm_conv_int64_fp(as, ir); | ||
892 | } | ||
894 | #endif | 893 | #endif |
895 | 894 | ||
896 | static void asm_strto(ASMState *as, IRIns *ir) | 895 | static void asm_strto(ASMState *as, IRIns *ir) |
@@ -912,29 +911,32 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
912 | RID_ESP, sps_scale(ir->s)); | 911 | RID_ESP, sps_scale(ir->s)); |
913 | } | 912 | } |
914 | 913 | ||
915 | static void asm_tostr(ASMState *as, IRIns *ir) | 914 | /* -- Memory references --------------------------------------------------- */ |
915 | |||
916 | /* Get pointer to TValue. */ | ||
917 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | ||
916 | { | 918 | { |
917 | IRIns *irl = IR(ir->op1); | 919 | IRIns *ir = IR(ref); |
918 | IRRef args[2]; | 920 | if (irt_isnum(ir->t)) { |
919 | args[0] = ASMREF_L; | 921 | /* For numbers use the constant itself or a spill slot as a TValue. */ |
920 | as->gcsteps++; | 922 | if (irref_isk(ref)) |
921 | if (irt_isnum(irl->t)) { | 923 | emit_loada(as, dest, ir_knum(ir)); |
922 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum]; | 924 | else |
923 | args[1] = ASMREF_TMP1; /* const lua_Number * */ | 925 | emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir)); |
924 | asm_setupresult(as, ir, ci); /* GCstr * */ | ||
925 | asm_gencall(as, ci, args); | ||
926 | emit_rmro(as, XO_LEA, ra_releasetmp(as, ASMREF_TMP1)|REX_64, | ||
927 | RID_ESP, ra_spill(as, irl)); | ||
928 | } else { | 926 | } else { |
929 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint]; | 927 | /* Otherwise use g->tmptv to hold the TValue. */ |
930 | args[1] = ir->op1; /* int32_t k */ | 928 | if (!irref_isk(ref)) { |
931 | asm_setupresult(as, ir, ci); /* GCstr * */ | 929 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); |
932 | asm_gencall(as, ci, args); | 930 | emit_movtomro(as, REX_64IR(ir, src), dest, 0); |
931 | } else if (!irt_ispri(ir->t)) { | ||
932 | emit_movmroi(as, dest, 0, ir->i); | ||
933 | } | ||
934 | if (!(LJ_64 && irt_islightud(ir->t))) | ||
935 | emit_movmroi(as, dest, 4, irt_toitype(ir->t)); | ||
936 | emit_loada(as, dest, &J2G(as->J)->tmptv); | ||
933 | } | 937 | } |
934 | } | 938 | } |
935 | 939 | ||
936 | /* -- Memory references --------------------------------------------------- */ | ||
937 | |||
938 | static void asm_aref(ASMState *as, IRIns *ir) | 940 | static void asm_aref(ASMState *as, IRIns *ir) |
939 | { | 941 | { |
940 | Reg dest = ra_dest(as, ir, RSET_GPR); | 942 | Reg dest = ra_dest(as, ir, RSET_GPR); |
@@ -1163,41 +1165,6 @@ static void asm_hrefk(ASMState *as, IRIns *ir) | |||
1163 | #endif | 1165 | #endif |
1164 | } | 1166 | } |
1165 | 1167 | ||
1166 | static void asm_newref(ASMState *as, IRIns *ir) | ||
1167 | { | ||
1168 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey]; | ||
1169 | IRRef args[3]; | ||
1170 | IRIns *irkey; | ||
1171 | Reg tmp; | ||
1172 | if (ir->r == RID_SINK) | ||
1173 | return; | ||
1174 | args[0] = ASMREF_L; /* lua_State *L */ | ||
1175 | args[1] = ir->op1; /* GCtab *t */ | ||
1176 | args[2] = ASMREF_TMP1; /* cTValue *key */ | ||
1177 | asm_setupresult(as, ir, ci); /* TValue * */ | ||
1178 | asm_gencall(as, ci, args); | ||
1179 | tmp = ra_releasetmp(as, ASMREF_TMP1); | ||
1180 | irkey = IR(ir->op2); | ||
1181 | if (irt_isnum(irkey->t)) { | ||
1182 | /* For numbers use the constant itself or a spill slot as a TValue. */ | ||
1183 | if (irref_isk(ir->op2)) | ||
1184 | emit_loada(as, tmp, ir_knum(irkey)); | ||
1185 | else | ||
1186 | emit_rmro(as, XO_LEA, tmp|REX_64, RID_ESP, ra_spill(as, irkey)); | ||
1187 | } else { | ||
1188 | /* Otherwise use g->tmptv to hold the TValue. */ | ||
1189 | if (!irref_isk(ir->op2)) { | ||
1190 | Reg src = ra_alloc1(as, ir->op2, rset_exclude(RSET_GPR, tmp)); | ||
1191 | emit_movtomro(as, REX_64IR(irkey, src), tmp, 0); | ||
1192 | } else if (!irt_ispri(irkey->t)) { | ||
1193 | emit_movmroi(as, tmp, 0, irkey->i); | ||
1194 | } | ||
1195 | if (!(LJ_64 && irt_islightud(irkey->t))) | ||
1196 | emit_movmroi(as, tmp, 4, irt_toitype(irkey->t)); | ||
1197 | emit_loada(as, tmp, &J2G(as->J)->tmptv); | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | static void asm_uref(ASMState *as, IRIns *ir) | 1168 | static void asm_uref(ASMState *as, IRIns *ir) |
1202 | { | 1169 | { |
1203 | /* NYI: Check that UREFO is still open and not aliasing a slot. */ | 1170 | /* NYI: Check that UREFO is still open and not aliasing a slot. */ |
@@ -1621,31 +1588,21 @@ static void asm_x87load(ASMState *as, IRRef ref) | |||
1621 | } | 1588 | } |
1622 | } | 1589 | } |
1623 | 1590 | ||
1624 | /* Try to rejoin pow from EXP2, MUL and LOG2 (if still unsplit). */ | 1591 | static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref) |
1625 | static int fpmjoin_pow(ASMState *as, IRIns *ir) | ||
1626 | { | 1592 | { |
1627 | IRIns *irp = IR(ir->op1); | 1593 | /* The modified regs must match with the *.dasc implementation. */ |
1628 | if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) { | 1594 | RegSet drop = RSET_RANGE(RID_XMM0, RID_XMM2+1)|RID2RSET(RID_EAX); |
1629 | IRIns *irpp = IR(irp->op1); | 1595 | IRIns *irx; |
1630 | if (irpp == ir-2 && irpp->o == IR_FPMATH && | 1596 | if (ra_hasreg(ir->r)) |
1631 | irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) { | 1597 | rset_clear(drop, ir->r); /* Dest reg handled below. */ |
1632 | /* The modified regs must match with the *.dasc implementation. */ | 1598 | ra_evictset(as, drop); |
1633 | RegSet drop = RSET_RANGE(RID_XMM0, RID_XMM2+1)|RID2RSET(RID_EAX); | 1599 | ra_destreg(as, ir, RID_XMM0); |
1634 | IRIns *irx; | 1600 | emit_call(as, lj_vm_pow_sse); |
1635 | if (ra_hasreg(ir->r)) | 1601 | irx = IR(lref); |
1636 | rset_clear(drop, ir->r); /* Dest reg handled below. */ | 1602 | if (ra_noreg(irx->r) && ra_gethint(irx->r) == RID_XMM1) |
1637 | ra_evictset(as, drop); | 1603 | irx->r = RID_INIT; /* Avoid allocating xmm1 for x. */ |
1638 | ra_destreg(as, ir, RID_XMM0); | 1604 | ra_left(as, RID_XMM0, lref); |
1639 | emit_call(as, lj_vm_pow_sse); | 1605 | ra_left(as, RID_XMM1, rref); |
1640 | irx = IR(irpp->op1); | ||
1641 | if (ra_noreg(irx->r) && ra_gethint(irx->r) == RID_XMM1) | ||
1642 | irx->r = RID_INIT; /* Avoid allocating xmm1 for x. */ | ||
1643 | ra_left(as, RID_XMM0, irpp->op1); | ||
1644 | ra_left(as, RID_XMM1, irp->op2); | ||
1645 | return 1; | ||
1646 | } | ||
1647 | } | ||
1648 | return 0; | ||
1649 | } | 1606 | } |
1650 | 1607 | ||
1651 | static void asm_fpmath(ASMState *as, IRIns *ir) | 1608 | static void asm_fpmath(ASMState *as, IRIns *ir) |
@@ -1681,7 +1638,7 @@ static void asm_fpmath(ASMState *as, IRIns *ir) | |||
1681 | fpm == IRFPM_CEIL ? lj_vm_ceil_sse : lj_vm_trunc_sse); | 1638 | fpm == IRFPM_CEIL ? lj_vm_ceil_sse : lj_vm_trunc_sse); |
1682 | ra_left(as, RID_XMM0, ir->op1); | 1639 | ra_left(as, RID_XMM0, ir->op1); |
1683 | } | 1640 | } |
1684 | } else if (fpm == IRFPM_EXP2 && fpmjoin_pow(as, ir)) { | 1641 | } else if (fpm == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) { |
1685 | /* Rejoined to pow(). */ | 1642 | /* Rejoined to pow(). */ |
1686 | } else { /* Handle x87 ops. */ | 1643 | } else { /* Handle x87 ops. */ |
1687 | int32_t ofs = sps_scale(ir->s); /* Use spill slot or temp slots. */ | 1644 | int32_t ofs = sps_scale(ir->s); /* Use spill slot or temp slots. */ |
@@ -1741,28 +1698,6 @@ static void asm_fppowi(ASMState *as, IRIns *ir) | |||
1741 | ra_left(as, RID_EAX, ir->op2); | 1698 | ra_left(as, RID_EAX, ir->op2); |
1742 | } | 1699 | } |
1743 | 1700 | ||
1744 | #if LJ_64 && LJ_HASFFI | ||
1745 | static void asm_arith64(ASMState *as, IRIns *ir, IRCallID id) | ||
1746 | { | ||
1747 | const CCallInfo *ci = &lj_ir_callinfo[id]; | ||
1748 | IRRef args[2]; | ||
1749 | args[0] = ir->op1; | ||
1750 | args[1] = ir->op2; | ||
1751 | asm_setupresult(as, ir, ci); | ||
1752 | asm_gencall(as, ci, args); | ||
1753 | } | ||
1754 | #endif | ||
1755 | |||
1756 | static void asm_intmod(ASMState *as, IRIns *ir) | ||
1757 | { | ||
1758 | const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_vm_modi]; | ||
1759 | IRRef args[2]; | ||
1760 | args[0] = ir->op1; | ||
1761 | args[1] = ir->op2; | ||
1762 | asm_setupresult(as, ir, ci); | ||
1763 | asm_gencall(as, ci, args); | ||
1764 | } | ||
1765 | |||
1766 | static int asm_swapops(ASMState *as, IRIns *ir) | 1701 | static int asm_swapops(ASMState *as, IRIns *ir) |
1767 | { | 1702 | { |
1768 | IRIns *irl = IR(ir->op1); | 1703 | IRIns *irl = IR(ir->op1); |
@@ -2268,13 +2203,9 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
2268 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ | 2203 | int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ |
2269 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; | 2204 | if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; |
2270 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ | 2205 | if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ |
2271 | if (usehi || uselo) { | ||
2272 | if (irt_isfp(ir->t)) | ||
2273 | asm_conv_fp_int64(as, ir); | ||
2274 | else | ||
2275 | asm_conv_int64_fp(as, ir); | ||
2276 | } | ||
2277 | as->curins--; /* Always skip the CONV. */ | 2206 | as->curins--; /* Always skip the CONV. */ |
2207 | if (usehi || uselo) | ||
2208 | asm_conv64(as, ir); | ||
2278 | return; | 2209 | return; |
2279 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ | 2210 | } else if ((ir-1)->o <= IR_NE) { /* 64 bit integer comparisons. ORDER IR. */ |
2280 | asm_comp_int64(as, ir); | 2211 | asm_comp_int64(as, ir); |
@@ -2627,8 +2558,8 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
2627 | case IR_DIV: | 2558 | case IR_DIV: |
2628 | #if LJ_64 && LJ_HASFFI | 2559 | #if LJ_64 && LJ_HASFFI |
2629 | if (!irt_isnum(ir->t)) | 2560 | if (!irt_isnum(ir->t)) |
2630 | asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : | 2561 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_divi64 : |
2631 | IRCALL_lj_carith_divu64); | 2562 | IRCALL_lj_carith_divu64); |
2632 | else | 2563 | else |
2633 | #endif | 2564 | #endif |
2634 | asm_fparith(as, ir, XO_DIVSD); | 2565 | asm_fparith(as, ir, XO_DIVSD); |
@@ -2636,11 +2567,11 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
2636 | case IR_MOD: | 2567 | case IR_MOD: |
2637 | #if LJ_64 && LJ_HASFFI | 2568 | #if LJ_64 && LJ_HASFFI |
2638 | if (!irt_isint(ir->t)) | 2569 | if (!irt_isint(ir->t)) |
2639 | asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : | 2570 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_modi64 : |
2640 | IRCALL_lj_carith_modu64); | 2571 | IRCALL_lj_carith_modu64); |
2641 | else | 2572 | else |
2642 | #endif | 2573 | #endif |
2643 | asm_intmod(as, ir); | 2574 | asm_callid(as, ir, IRCALL_lj_vm_modi); |
2644 | break; | 2575 | break; |
2645 | 2576 | ||
2646 | case IR_NEG: | 2577 | case IR_NEG: |
@@ -2670,8 +2601,8 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
2670 | case IR_POW: | 2601 | case IR_POW: |
2671 | #if LJ_64 && LJ_HASFFI | 2602 | #if LJ_64 && LJ_HASFFI |
2672 | if (!irt_isnum(ir->t)) | 2603 | if (!irt_isnum(ir->t)) |
2673 | asm_arith64(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 2604 | asm_callid(as, ir, irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
2674 | IRCALL_lj_carith_powu64); | 2605 | IRCALL_lj_carith_powu64); |
2675 | else | 2606 | else |
2676 | #endif | 2607 | #endif |
2677 | asm_fppowi(as, ir); | 2608 | asm_fppowi(as, ir); |