aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm_mips.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_asm_mips.h')
-rw-r--r--src/lj_asm_mips.h349
1 files changed, 97 insertions, 252 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 9fe7c9c3..3d061eb4 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -226,7 +226,7 @@ static void asm_fusexref(ASMState *as, MIPSIns mi, Reg rt, IRRef ref,
226/* Generate a call to a C function. */ 226/* Generate a call to a C function. */
227static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) 227static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
228{ 228{
229 uint32_t n, nargs = CCI_NARGS(ci); 229 uint32_t n, nargs = CCI_XNARGS(ci);
230 int32_t ofs = 16; 230 int32_t ofs = 16;
231 Reg gpr, fpr = REGARG_FIRSTFPR; 231 Reg gpr, fpr = REGARG_FIRSTFPR;
232 if ((void *)ci->func) 232 if ((void *)ci->func)
@@ -326,15 +326,6 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
326 } 326 }
327} 327}
328 328
329static void asm_call(ASMState *as, IRIns *ir)
330{
331 IRRef args[CCI_NARGS_MAX];
332 const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
333 asm_collectargs(as, ir, ci, args);
334 asm_setupresult(as, ir, ci);
335 asm_gencall(as, ci, args);
336}
337
338static void asm_callx(ASMState *as, IRIns *ir) 329static void asm_callx(ASMState *as, IRIns *ir)
339{ 330{
340 IRRef args[CCI_NARGS_MAX*2]; 331 IRRef args[CCI_NARGS_MAX*2];
@@ -362,16 +353,6 @@ static void asm_callx(ASMState *as, IRIns *ir)
362 asm_gencall(as, &ci, args); 353 asm_gencall(as, &ci, args);
363} 354}
364 355
365static void asm_callid(ASMState *as, IRIns *ir, IRCallID id)
366{
367 const CCallInfo *ci = &lj_ir_callinfo[id];
368 IRRef args[2];
369 args[0] = ir->op1;
370 args[1] = ir->op2;
371 asm_setupresult(as, ir, ci);
372 asm_gencall(as, ci, args);
373}
374
375static void asm_callround(ASMState *as, IRIns *ir, IRCallID id) 356static void asm_callround(ASMState *as, IRIns *ir, IRCallID id)
376{ 357{
377 /* The modified regs must match with the *.dasc implementation. */ 358 /* The modified regs must match with the *.dasc implementation. */
@@ -519,28 +500,6 @@ static void asm_conv(ASMState *as, IRIns *ir)
519 } 500 }
520} 501}
521 502
522#if LJ_HASFFI
523static void asm_conv64(ASMState *as, IRIns *ir)
524{
525 IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
526 IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
527 IRCallID id;
528 const CCallInfo *ci;
529 IRRef args[2];
530 args[LJ_BE?0:1] = ir->op1;
531 args[LJ_BE?1:0] = (ir-1)->op1;
532 if (st == IRT_NUM || st == IRT_FLOAT) {
533 id = IRCALL_fp64_d2l + ((st == IRT_FLOAT) ? 2 : 0) + (dt - IRT_I64);
534 ir--;
535 } else {
536 id = IRCALL_fp64_l2d + ((dt == IRT_FLOAT) ? 2 : 0) + (st - IRT_I64);
537 }
538 ci = &lj_ir_callinfo[id];
539 asm_setupresult(as, ir, ci);
540 asm_gencall(as, ci, args);
541}
542#endif
543
544static void asm_strto(ASMState *as, IRIns *ir) 503static void asm_strto(ASMState *as, IRIns *ir)
545{ 504{
546 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num]; 505 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num];
@@ -557,6 +516,8 @@ static void asm_strto(ASMState *as, IRIns *ir)
557 RID_SP, sps_scale(ir->s)); 516 RID_SP, sps_scale(ir->s));
558} 517}
559 518
519/* -- Memory references --------------------------------------------------- */
520
560/* Get pointer to TValue. */ 521/* Get pointer to TValue. */
561static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) 522static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
562{ 523{
@@ -580,27 +541,6 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
580 } 541 }
581} 542}
582 543
583static void asm_tostr(ASMState *as, IRIns *ir)
584{
585 IRRef args[2];
586 args[0] = ASMREF_L;
587 as->gcsteps++;
588 if (irt_isnum(IR(ir->op1)->t) || (ir+1)->o == IR_HIOP) {
589 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromnum];
590 args[1] = ASMREF_TMP1; /* const lua_Number * */
591 asm_setupresult(as, ir, ci); /* GCstr * */
592 asm_gencall(as, ci, args);
593 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
594 } else {
595 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_fromint];
596 args[1] = ir->op1; /* int32_t k */
597 asm_setupresult(as, ir, ci); /* GCstr * */
598 asm_gencall(as, ci, args);
599 }
600}
601
602/* -- Memory references --------------------------------------------------- */
603
604static void asm_aref(ASMState *as, IRIns *ir) 544static void asm_aref(ASMState *as, IRIns *ir)
605{ 545{
606 Reg dest = ra_dest(as, ir, RSET_GPR); 546 Reg dest = ra_dest(as, ir, RSET_GPR);
@@ -630,7 +570,7 @@ static void asm_aref(ASMState *as, IRIns *ir)
630** } while ((n = nextnode(n))); 570** } while ((n = nextnode(n)));
631** return niltv(L); 571** return niltv(L);
632*/ 572*/
633static void asm_href(ASMState *as, IRIns *ir) 573static void asm_href(ASMState *as, IRIns *ir, IROp merge)
634{ 574{
635 RegSet allow = RSET_GPR; 575 RegSet allow = RSET_GPR;
636 int destused = ra_used(ir); 576 int destused = ra_used(ir);
@@ -656,37 +596,42 @@ static void asm_href(ASMState *as, IRIns *ir)
656 tmp2 = ra_scratch(as, allow); 596 tmp2 = ra_scratch(as, allow);
657 rset_clear(allow, tmp2); 597 rset_clear(allow, tmp2);
658 598
659 /* Key not found in chain: load niltv. */ 599 /* Key not found in chain: jump to exit (if merged) or load niltv. */
660 l_end = emit_label(as); 600 l_end = emit_label(as);
661 if (destused) 601 as->invmcp = NULL;
602 if (merge == IR_NE)
603 asm_guard(as, MIPSI_B, RID_ZERO, RID_ZERO);
604 else if (destused)
662 emit_loada(as, dest, niltvg(J2G(as->J))); 605 emit_loada(as, dest, niltvg(J2G(as->J)));
663 else
664 *--as->mcp = MIPSI_NOP;
665 /* Follow hash chain until the end. */ 606 /* Follow hash chain until the end. */
666 emit_move(as, dest, tmp1); 607 emit_move(as, dest, tmp2);
667 l_loop = --as->mcp; 608 l_loop = --as->mcp;
668 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, next)); 609 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, next));
669 l_next = emit_label(as); 610 l_next = emit_label(as);
670 611
671 /* Type and value comparison. */ 612 /* Type and value comparison. */
613 if (merge == IR_EQ) { /* Must match asm_guard(). */
614 emit_ti(as, MIPSI_LI, RID_TMP, as->snapno);
615 l_end = asm_exitstub_addr(as);
616 }
672 if (irt_isnum(kt)) { 617 if (irt_isnum(kt)) {
673 emit_branch(as, MIPSI_BC1T, 0, 0, l_end); 618 emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
674 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); 619 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
675 emit_tg(as, MIPSI_MFC1, tmp1, key+1); 620 *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
676 emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); 621 emit_branch(as, MIPSI_BEQ, tmp2, RID_ZERO, l_next);
677 emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); 622 emit_tsi(as, MIPSI_SLTIU, tmp2, tmp2, (int32_t)LJ_TISNUM);
678 emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n)); 623 emit_hsi(as, MIPSI_LDC1, tmpnum, dest, (int32_t)offsetof(Node, key.n));
679 } else { 624 } else {
680 if (irt_ispri(kt)) { 625 if (irt_ispri(kt)) {
681 emit_branch(as, MIPSI_BEQ, tmp1, type, l_end); 626 emit_branch(as, MIPSI_BEQ, tmp2, type, l_end);
682 } else { 627 } else {
683 emit_branch(as, MIPSI_BEQ, tmp2, key, l_end); 628 emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
684 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.gcr)); 629 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.gcr));
685 emit_branch(as, MIPSI_BNE, tmp1, type, l_next); 630 emit_branch(as, MIPSI_BNE, tmp2, type, l_next);
686 } 631 }
687 } 632 }
688 emit_tsi(as, MIPSI_LW, tmp1, dest, (int32_t)offsetof(Node, key.it)); 633 emit_tsi(as, MIPSI_LW, tmp2, dest, (int32_t)offsetof(Node, key.it));
689 *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu); 634 *l_loop = MIPSI_BNE | MIPSF_S(tmp2) | ((as->mcp-l_loop-1) & 0xffffu);
690 635
691 /* Load main position relative to tab->node into dest. */ 636 /* Load main position relative to tab->node into dest. */
692 khash = irref_isk(refkey) ? ir_khash(irkey) : 1; 637 khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
@@ -776,20 +721,6 @@ nolo:
776 emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow)); 721 emit_tsi(as, MIPSI_ADDU, dest, node, ra_allock(as, ofs, allow));
777} 722}
778 723
779static void asm_newref(ASMState *as, IRIns *ir)
780{
781 if (ir->r != RID_SINK) {
782 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey];
783 IRRef args[3];
784 args[0] = ASMREF_L; /* lua_State *L */
785 args[1] = ir->op1; /* GCtab *t */
786 args[2] = ASMREF_TMP1; /* cTValue *key */
787 asm_setupresult(as, ir, ci); /* TValue * */
788 asm_gencall(as, ci, args);
789 asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
790 }
791}
792
793static void asm_uref(ASMState *as, IRIns *ir) 724static void asm_uref(ASMState *as, IRIns *ir)
794{ 725{
795 /* NYI: Check that UREFO is still open and not aliasing a slot. */ 726 /* NYI: Check that UREFO is still open and not aliasing a slot. */
@@ -918,7 +849,7 @@ static void asm_xload(ASMState *as, IRIns *ir)
918 asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0); 849 asm_fusexref(as, asm_fxloadins(ir), dest, ir->op1, RSET_GPR, 0);
919} 850}
920 851
921static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs) 852static void asm_xstore_(ASMState *as, IRIns *ir, int32_t ofs)
922{ 853{
923 if (ir->r != RID_SINK) { 854 if (ir->r != RID_SINK) {
924 Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); 855 Reg src = ra_alloc1z(as, ir->op2, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR);
@@ -927,6 +858,8 @@ static void asm_xstore(ASMState *as, IRIns *ir, int32_t ofs)
927 } 858 }
928} 859}
929 860
861#define asm_xstore(as, ir) asm_xstore_(as, ir, 0)
862
930static void asm_ahuvload(ASMState *as, IRIns *ir) 863static void asm_ahuvload(ASMState *as, IRIns *ir)
931{ 864{
932 IRType1 t = ir->t; 865 IRType1 t = ir->t;
@@ -1002,7 +935,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
1002 if (irt_isint(t)) { 935 if (irt_isint(t)) {
1003 Reg tmp = ra_scratch(as, RSET_FPR); 936 Reg tmp = ra_scratch(as, RSET_FPR);
1004 emit_tg(as, MIPSI_MFC1, dest, tmp); 937 emit_tg(as, MIPSI_MFC1, dest, tmp);
1005 emit_fg(as, MIPSI_CVT_W_D, tmp, tmp); 938 emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp);
1006 dest = tmp; 939 dest = tmp;
1007 t.irt = IRT_NUM; /* Check for original type. */ 940 t.irt = IRT_NUM; /* Check for original type. */
1008 } else { 941 } else {
@@ -1042,19 +975,15 @@ dotypecheck:
1042static void asm_cnew(ASMState *as, IRIns *ir) 975static void asm_cnew(ASMState *as, IRIns *ir)
1043{ 976{
1044 CTState *cts = ctype_ctsG(J2G(as->J)); 977 CTState *cts = ctype_ctsG(J2G(as->J));
1045 CTypeID ctypeid = (CTypeID)IR(ir->op1)->i; 978 CTypeID id = (CTypeID)IR(ir->op1)->i;
1046 CTSize sz = (ir->o == IR_CNEWI || ir->op2 == REF_NIL) ? 979 CTSize sz;
1047 lj_ctype_size(cts, ctypeid) : (CTSize)IR(ir->op2)->i; 980 CTInfo info = lj_ctype_info(cts, id, &sz);
1048 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco]; 981 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_mem_newgco];
1049 IRRef args[2]; 982 IRRef args[4];
1050 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
1051 RegSet drop = RSET_SCRATCH; 983 RegSet drop = RSET_SCRATCH;
1052 lua_assert(sz != CTSIZE_INVALID); 984 lua_assert(sz != CTSIZE_INVALID || (ir->o == IR_CNEW && ir->op2 != REF_NIL));
1053 985
1054 args[0] = ASMREF_L; /* lua_State *L */
1055 args[1] = ASMREF_TMP1; /* MSize size */
1056 as->gcsteps++; 986 as->gcsteps++;
1057
1058 if (ra_hasreg(ir->r)) 987 if (ra_hasreg(ir->r))
1059 rset_clear(drop, ir->r); /* Dest reg handled below. */ 988 rset_clear(drop, ir->r); /* Dest reg handled below. */
1060 ra_evictset(as, drop); 989 ra_evictset(as, drop);
@@ -1063,6 +992,7 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1063 992
1064 /* Initialize immutable cdata object. */ 993 /* Initialize immutable cdata object. */
1065 if (ir->o == IR_CNEWI) { 994 if (ir->o == IR_CNEWI) {
995 RegSet allow = (RSET_GPR & ~RSET_SCRATCH);
1066 int32_t ofs = sizeof(GCcdata); 996 int32_t ofs = sizeof(GCcdata);
1067 lua_assert(sz == 4 || sz == 8); 997 lua_assert(sz == 4 || sz == 8);
1068 if (sz == 8) { 998 if (sz == 8) {
@@ -1077,12 +1007,24 @@ static void asm_cnew(ASMState *as, IRIns *ir)
1077 if (ofs == sizeof(GCcdata)) break; 1007 if (ofs == sizeof(GCcdata)) break;
1078 ofs -= 4; if (LJ_BE) ir++; else ir--; 1008 ofs -= 4; if (LJ_BE) ir++; else ir--;
1079 } 1009 }
1010 } else if (ir->op2 != REF_NIL) { /* Create VLA/VLS/aligned cdata. */
1011 ci = &lj_ir_callinfo[IRCALL_lj_cdata_newv];
1012 args[0] = ASMREF_L; /* lua_State *L */
1013 args[1] = ir->op1; /* CTypeID id */
1014 args[2] = ir->op2; /* CTSize sz */
1015 args[3] = ASMREF_TMP1; /* CTSize align */
1016 asm_gencall(as, ci, args);
1017 emit_loadi(as, ra_releasetmp(as, ASMREF_TMP1), (int32_t)ctype_align(info));
1018 return;
1080 } 1019 }
1020
1081 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */ 1021 /* Initialize gct and ctypeid. lj_mem_newgco() already sets marked. */
1082 emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct)); 1022 emit_tsi(as, MIPSI_SB, RID_RET+1, RID_RET, offsetof(GCcdata, gct));
1083 emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid)); 1023 emit_tsi(as, MIPSI_SH, RID_TMP, RID_RET, offsetof(GCcdata, ctypeid));
1084 emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA); 1024 emit_ti(as, MIPSI_LI, RID_RET+1, ~LJ_TCDATA);
1085 emit_ti(as, MIPSI_LI, RID_TMP, ctypeid); /* Lower 16 bit used. Sign-ext ok. */ 1025 emit_ti(as, MIPSI_LI, RID_TMP, id); /* Lower 16 bit used. Sign-ext ok. */
1026 args[0] = ASMREF_L; /* lua_State *L */
1027 args[1] = ASMREF_TMP1; /* MSize size */
1086 asm_gencall(as, ci, args); 1028 asm_gencall(as, ci, args);
1087 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)), 1029 ra_allockreg(as, (int32_t)(sz+sizeof(GCcdata)),
1088 ra_releasetmp(as, ASMREF_TMP1)); 1030 ra_releasetmp(as, ASMREF_TMP1));
@@ -1152,23 +1094,16 @@ static void asm_fpunary(ASMState *as, IRIns *ir, MIPSIns mi)
1152 emit_fg(as, mi, dest, left); 1094 emit_fg(as, mi, dest, left);
1153} 1095}
1154 1096
1155static int asm_fpjoin_pow(ASMState *as, IRIns *ir) 1097static void asm_fpmath(ASMState *as, IRIns *ir)
1156{ 1098{
1157 IRIns *irp = IR(ir->op1); 1099 if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
1158 if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) { 1100 return;
1159 IRIns *irpp = IR(irp->op1); 1101 if (ir->op2 <= IRFPM_TRUNC)
1160 if (irpp == ir-2 && irpp->o == IR_FPMATH && 1102 asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
1161 irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) { 1103 else if (ir->op2 == IRFPM_SQRT)
1162 const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow]; 1104 asm_fpunary(as, ir, MIPSI_SQRT_D);
1163 IRRef args[2]; 1105 else
1164 args[0] = irpp->op1; 1106 asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
1165 args[1] = irp->op2;
1166 asm_setupresult(as, ir, ci);
1167 asm_gencall(as, ci, args);
1168 return 1;
1169 }
1170 }
1171 return 0;
1172} 1107}
1173 1108
1174static void asm_add(ASMState *as, IRIns *ir) 1109static void asm_add(ASMState *as, IRIns *ir)
@@ -1214,6 +1149,10 @@ static void asm_mul(ASMState *as, IRIns *ir)
1214 } 1149 }
1215} 1150}
1216 1151
1152#define asm_div(as, ir) asm_fparith(as, ir, MIPSI_DIV_D)
1153#define asm_mod(as, ir) asm_callid(as, ir, IRCALL_lj_vm_modi)
1154#define asm_pow(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
1155
1217static void asm_neg(ASMState *as, IRIns *ir) 1156static void asm_neg(ASMState *as, IRIns *ir)
1218{ 1157{
1219 if (irt_isnum(ir->t)) { 1158 if (irt_isnum(ir->t)) {
@@ -1225,6 +1164,10 @@ static void asm_neg(ASMState *as, IRIns *ir)
1225 } 1164 }
1226} 1165}
1227 1166
1167#define asm_abs(as, ir) asm_fpunary(as, ir, MIPSI_ABS_D)
1168#define asm_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
1169#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
1170
1228static void asm_arithov(ASMState *as, IRIns *ir) 1171static void asm_arithov(ASMState *as, IRIns *ir)
1229{ 1172{
1230 Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR); 1173 Reg right, left, tmp, dest = ra_dest(as, ir, RSET_GPR);
@@ -1258,13 +1201,21 @@ static void asm_arithov(ASMState *as, IRIns *ir)
1258 emit_move(as, RID_TMP, dest == left ? left : right); 1201 emit_move(as, RID_TMP, dest == left ? left : right);
1259} 1202}
1260 1203
1204#define asm_addov(as, ir) asm_arithov(as, ir)
1205#define asm_subov(as, ir) asm_arithov(as, ir)
1206
1261static void asm_mulov(ASMState *as, IRIns *ir) 1207static void asm_mulov(ASMState *as, IRIns *ir)
1262{ 1208{
1263#if LJ_DUALNUM 1209 Reg dest = ra_dest(as, ir, RSET_GPR);
1264#error "NYI: MULOV" 1210 Reg tmp, right, left = ra_alloc2(as, ir, RSET_GPR);
1265#else 1211 right = (left >> 8); left &= 255;
1266 UNUSED(as); UNUSED(ir); lua_assert(0); /* Unused in single-number mode. */ 1212 tmp = ra_scratch(as, rset_exclude(rset_exclude(rset_exclude(RSET_GPR, left),
1267#endif 1213 right), dest));
1214 asm_guard(as, MIPSI_BNE, RID_TMP, tmp);
1215 emit_dta(as, MIPSI_SRA, RID_TMP, dest, 31);
1216 emit_dst(as, MIPSI_MFHI, tmp, 0, 0);
1217 emit_dst(as, MIPSI_MFLO, dest, 0, 0);
1218 emit_dst(as, MIPSI_MULT, 0, left, right);
1268} 1219}
1269 1220
1270#if LJ_HASFFI 1221#if LJ_HASFFI
@@ -1351,7 +1302,7 @@ static void asm_neg64(ASMState *as, IRIns *ir)
1351} 1302}
1352#endif 1303#endif
1353 1304
1354static void asm_bitnot(ASMState *as, IRIns *ir) 1305static void asm_bnot(ASMState *as, IRIns *ir)
1355{ 1306{
1356 Reg left, right, dest = ra_dest(as, ir, RSET_GPR); 1307 Reg left, right, dest = ra_dest(as, ir, RSET_GPR);
1357 IRIns *irl = IR(ir->op1); 1308 IRIns *irl = IR(ir->op1);
@@ -1365,7 +1316,7 @@ static void asm_bitnot(ASMState *as, IRIns *ir)
1365 emit_dst(as, MIPSI_NOR, dest, left, right); 1316 emit_dst(as, MIPSI_NOR, dest, left, right);
1366} 1317}
1367 1318
1368static void asm_bitswap(ASMState *as, IRIns *ir) 1319static void asm_bswap(ASMState *as, IRIns *ir)
1369{ 1320{
1370 Reg dest = ra_dest(as, ir, RSET_GPR); 1321 Reg dest = ra_dest(as, ir, RSET_GPR);
1371 Reg left = ra_alloc1(as, ir->op1, RSET_GPR); 1322 Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
@@ -1401,6 +1352,10 @@ static void asm_bitop(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
1401 emit_dst(as, mi, dest, left, right); 1352 emit_dst(as, mi, dest, left, right);
1402} 1353}
1403 1354
1355#define asm_band(as, ir) asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI)
1356#define asm_bor(as, ir) asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI)
1357#define asm_bxor(as, ir) asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI)
1358
1404static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik) 1359static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
1405{ 1360{
1406 Reg dest = ra_dest(as, ir, RSET_GPR); 1361 Reg dest = ra_dest(as, ir, RSET_GPR);
@@ -1414,7 +1369,12 @@ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
1414 } 1369 }
1415} 1370}
1416 1371
1417static void asm_bitror(ASMState *as, IRIns *ir) 1372#define asm_bshl(as, ir) asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL)
1373#define asm_bshr(as, ir) asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL)
1374#define asm_bsar(as, ir) asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA)
1375#define asm_brol(as, ir) lua_assert(0)
1376
1377static void asm_bror(ASMState *as, IRIns *ir)
1418{ 1378{
1419 if ((as->flags & JIT_F_MIPS32R2)) { 1379 if ((as->flags & JIT_F_MIPS32R2)) {
1420 asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR); 1380 asm_bitshift(as, ir, MIPSI_ROTRV, MIPSI_ROTR);
@@ -1463,6 +1423,9 @@ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
1463 } 1423 }
1464} 1424}
1465 1425
1426#define asm_min(as, ir) asm_min_max(as, ir, 0)
1427#define asm_max(as, ir) asm_min_max(as, ir, 1)
1428
1466/* -- Comparisons --------------------------------------------------------- */ 1429/* -- Comparisons --------------------------------------------------------- */
1467 1430
1468static void asm_comp(ASMState *as, IRIns *ir) 1431static void asm_comp(ASMState *as, IRIns *ir)
@@ -1500,7 +1463,7 @@ static void asm_comp(ASMState *as, IRIns *ir)
1500 } 1463 }
1501} 1464}
1502 1465
1503static void asm_compeq(ASMState *as, IRIns *ir) 1466static void asm_equal(ASMState *as, IRIns *ir)
1504{ 1467{
1505 Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR); 1468 Reg right, left = ra_alloc2(as, ir, irt_isnum(ir->t) ? RSET_FPR : RSET_GPR);
1506 right = (left >> 8); left &= 255; 1469 right = (left >> 8); left &= 255;
@@ -1574,8 +1537,8 @@ static void asm_hiop(ASMState *as, IRIns *ir)
1574 } else if ((ir-1)->o == IR_XSTORE) { 1537 } else if ((ir-1)->o == IR_XSTORE) {
1575 as->curins--; /* Handle both stores here. */ 1538 as->curins--; /* Handle both stores here. */
1576 if ((ir-1)->r != RID_SINK) { 1539 if ((ir-1)->r != RID_SINK) {
1577 asm_xstore(as, ir, LJ_LE ? 4 : 0); 1540 asm_xstore_(as, ir, LJ_LE ? 4 : 0);
1578 asm_xstore(as, ir-1, LJ_LE ? 0 : 4); 1541 asm_xstore_(as, ir-1, LJ_LE ? 0 : 4);
1579 } 1542 }
1580 return; 1543 return;
1581 } 1544 }
@@ -1771,131 +1734,13 @@ static void asm_tail_prep(ASMState *as)
1771 as->invmcp = as->loopref ? as->mcp : NULL; 1734 as->invmcp = as->loopref ? as->mcp : NULL;
1772} 1735}
1773 1736
1774/* -- Instruction dispatch ------------------------------------------------ */
1775
1776/* Assemble a single instruction. */
1777static void asm_ir(ASMState *as, IRIns *ir)
1778{
1779 switch ((IROp)ir->o) {
1780 /* Miscellaneous ops. */
1781 case IR_LOOP: asm_loop(as); break;
1782 case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break;
1783 case IR_USE:
1784 ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
1785 case IR_PHI: asm_phi(as, ir); break;
1786 case IR_HIOP: asm_hiop(as, ir); break;
1787 case IR_GCSTEP: asm_gcstep(as, ir); break;
1788
1789 /* Guarded assertions. */
1790 case IR_EQ: case IR_NE: asm_compeq(as, ir); break;
1791 case IR_LT: case IR_GE: case IR_LE: case IR_GT:
1792 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
1793 case IR_ABC:
1794 asm_comp(as, ir);
1795 break;
1796
1797 case IR_RETF: asm_retf(as, ir); break;
1798
1799 /* Bit ops. */
1800 case IR_BNOT: asm_bitnot(as, ir); break;
1801 case IR_BSWAP: asm_bitswap(as, ir); break;
1802
1803 case IR_BAND: asm_bitop(as, ir, MIPSI_AND, MIPSI_ANDI); break;
1804 case IR_BOR: asm_bitop(as, ir, MIPSI_OR, MIPSI_ORI); break;
1805 case IR_BXOR: asm_bitop(as, ir, MIPSI_XOR, MIPSI_XORI); break;
1806
1807 case IR_BSHL: asm_bitshift(as, ir, MIPSI_SLLV, MIPSI_SLL); break;
1808 case IR_BSHR: asm_bitshift(as, ir, MIPSI_SRLV, MIPSI_SRL); break;
1809 case IR_BSAR: asm_bitshift(as, ir, MIPSI_SRAV, MIPSI_SRA); break;
1810 case IR_BROL: lua_assert(0); break;
1811 case IR_BROR: asm_bitror(as, ir); break;
1812
1813 /* Arithmetic ops. */
1814 case IR_ADD: asm_add(as, ir); break;
1815 case IR_SUB: asm_sub(as, ir); break;
1816 case IR_MUL: asm_mul(as, ir); break;
1817 case IR_DIV: asm_fparith(as, ir, MIPSI_DIV_D); break;
1818 case IR_MOD: asm_callid(as, ir, IRCALL_lj_vm_modi); break;
1819 case IR_POW: asm_callid(as, ir, IRCALL_lj_vm_powi); break;
1820 case IR_NEG: asm_neg(as, ir); break;
1821
1822 case IR_ABS: asm_fpunary(as, ir, MIPSI_ABS_D); break;
1823 case IR_ATAN2: asm_callid(as, ir, IRCALL_atan2); break;
1824 case IR_LDEXP: asm_callid(as, ir, IRCALL_ldexp); break;
1825 case IR_MIN: asm_min_max(as, ir, 0); break;
1826 case IR_MAX: asm_min_max(as, ir, 1); break;
1827 case IR_FPMATH:
1828 if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
1829 break;
1830 if (ir->op2 <= IRFPM_TRUNC)
1831 asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
1832 else if (ir->op2 == IRFPM_SQRT)
1833 asm_fpunary(as, ir, MIPSI_SQRT_D);
1834 else
1835 asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
1836 break;
1837
1838 /* Overflow-checking arithmetic ops. */
1839 case IR_ADDOV: asm_arithov(as, ir); break;
1840 case IR_SUBOV: asm_arithov(as, ir); break;
1841 case IR_MULOV: asm_mulov(as, ir); break;
1842
1843 /* Memory references. */
1844 case IR_AREF: asm_aref(as, ir); break;
1845 case IR_HREF: asm_href(as, ir); break;
1846 case IR_HREFK: asm_hrefk(as, ir); break;
1847 case IR_NEWREF: asm_newref(as, ir); break;
1848 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
1849 case IR_FREF: asm_fref(as, ir); break;
1850 case IR_STRREF: asm_strref(as, ir); break;
1851
1852 /* Loads and stores. */
1853 case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
1854 asm_ahuvload(as, ir);
1855 break;
1856 case IR_FLOAD: asm_fload(as, ir); break;
1857 case IR_XLOAD: asm_xload(as, ir); break;
1858 case IR_SLOAD: asm_sload(as, ir); break;
1859
1860 case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break;
1861 case IR_FSTORE: asm_fstore(as, ir); break;
1862 case IR_XSTORE: asm_xstore(as, ir, 0); break;
1863
1864 /* Allocations. */
1865 case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
1866 case IR_TNEW: asm_tnew(as, ir); break;
1867 case IR_TDUP: asm_tdup(as, ir); break;
1868 case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break;
1869
1870 /* Write barriers. */
1871 case IR_TBAR: asm_tbar(as, ir); break;
1872 case IR_OBAR: asm_obar(as, ir); break;
1873
1874 /* Type conversions. */
1875 case IR_CONV: asm_conv(as, ir); break;
1876 case IR_TOBIT: asm_tobit(as, ir); break;
1877 case IR_TOSTR: asm_tostr(as, ir); break;
1878 case IR_STRTO: asm_strto(as, ir); break;
1879
1880 /* Calls. */
1881 case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break;
1882 case IR_CALLXS: asm_callx(as, ir); break;
1883 case IR_CARG: break;
1884
1885 default:
1886 setintV(&as->J->errinfo, ir->o);
1887 lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
1888 break;
1889 }
1890}
1891
1892/* -- Trace setup --------------------------------------------------------- */ 1737/* -- Trace setup --------------------------------------------------------- */
1893 1738
1894/* Ensure there are enough stack slots for call arguments. */ 1739/* Ensure there are enough stack slots for call arguments. */
1895static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci) 1740static Reg asm_setup_call_slots(ASMState *as, IRIns *ir, const CCallInfo *ci)
1896{ 1741{
1897 IRRef args[CCI_NARGS_MAX*2]; 1742 IRRef args[CCI_NARGS_MAX*2];
1898 uint32_t i, nargs = (int)CCI_NARGS(ci); 1743 uint32_t i, nargs = CCI_XNARGS(ci);
1899 int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR; 1744 int nslots = 4, ngpr = REGARG_NUMGPR, nfpr = REGARG_NUMFPR;
1900 asm_collectargs(as, ir, ci, args); 1745 asm_collectargs(as, ir, ci, args);
1901 for (i = 0; i < nargs; i++) { 1746 for (i = 0; i < nargs; i++) {