aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm_x86.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_asm_x86.h175
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
579static 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. */
589static void *asm_callx_func(ASMState *as, IRIns *irf, IRRef func) 580static 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
886static 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
896static void asm_strto(ASMState *as, IRIns *ir) 895static 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
915static void asm_tostr(ASMState *as, IRIns *ir) 914/* -- Memory references --------------------------------------------------- */
915
916/* Get pointer to TValue. */
917static 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
938static void asm_aref(ASMState *as, IRIns *ir) 940static 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
1166static 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
1201static void asm_uref(ASMState *as, IRIns *ir) 1168static 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). */ 1591static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
1625static 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
1651static void asm_fpmath(ASMState *as, IRIns *ir) 1608static 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
1745static 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
1756static 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
1766static int asm_swapops(ASMState *as, IRIns *ir) 1701static 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);