aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm_mips.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_asm_mips.h48
1 files changed, 30 insertions, 18 deletions
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 44cb85e5..cbbd2966 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -570,7 +570,7 @@ static void asm_aref(ASMState *as, IRIns *ir)
570** } while ((n = nextnode(n))); 570** } while ((n = nextnode(n)));
571** return niltv(L); 571** return niltv(L);
572*/ 572*/
573static void asm_href(ASMState *as, IRIns *ir) 573static void asm_href(ASMState *as, IRIns *ir, IROp merge)
574{ 574{
575 RegSet allow = RSET_GPR; 575 RegSet allow = RSET_GPR;
576 int destused = ra_used(ir); 576 int destused = ra_used(ir);
@@ -596,37 +596,42 @@ static void asm_href(ASMState *as, IRIns *ir)
596 tmp2 = ra_scratch(as, allow); 596 tmp2 = ra_scratch(as, allow);
597 rset_clear(allow, tmp2); 597 rset_clear(allow, tmp2);
598 598
599 /* Key not found in chain: load niltv. */ 599 /* Key not found in chain: jump to exit (if merged) or load niltv. */
600 l_end = emit_label(as); 600 l_end = emit_label(as);
601 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)
602 emit_loada(as, dest, niltvg(J2G(as->J))); 605 emit_loada(as, dest, niltvg(J2G(as->J)));
603 else
604 *--as->mcp = MIPSI_NOP;
605 /* Follow hash chain until the end. */ 606 /* Follow hash chain until the end. */
606 emit_move(as, dest, tmp1); 607 emit_move(as, dest, tmp2);
607 l_loop = --as->mcp; 608 l_loop = --as->mcp;
608 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));
609 l_next = emit_label(as); 610 l_next = emit_label(as);
610 611
611 /* 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 }
612 if (irt_isnum(kt)) { 617 if (irt_isnum(kt)) {
613 emit_branch(as, MIPSI_BC1T, 0, 0, l_end); 618 emit_branch(as, MIPSI_BC1T, 0, 0, l_end);
614 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key); 619 emit_fgh(as, MIPSI_C_EQ_D, 0, tmpnum, key);
615 emit_tg(as, MIPSI_MFC1, tmp1, key+1); 620 *--as->mcp = MIPSI_NOP; /* Avoid NaN comparison overhead. */
616 emit_branch(as, MIPSI_BEQ, tmp1, RID_ZERO, l_next); 621 emit_branch(as, MIPSI_BEQ, tmp2, RID_ZERO, l_next);
617 emit_tsi(as, MIPSI_SLTIU, tmp1, tmp1, (int32_t)LJ_TISNUM); 622 emit_tsi(as, MIPSI_SLTIU, tmp2, tmp2, (int32_t)LJ_TISNUM);
618 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));
619 } else { 624 } else {
620 if (irt_ispri(kt)) { 625 if (irt_ispri(kt)) {
621 emit_branch(as, MIPSI_BEQ, tmp1, type, l_end); 626 emit_branch(as, MIPSI_BEQ, tmp2, type, l_end);
622 } else { 627 } else {
623 emit_branch(as, MIPSI_BEQ, tmp2, key, l_end); 628 emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
624 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));
625 emit_branch(as, MIPSI_BNE, tmp1, type, l_next); 630 emit_branch(as, MIPSI_BNE, tmp2, type, l_next);
626 } 631 }
627 } 632 }
628 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));
629 *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);
630 635
631 /* Load main position relative to tab->node into dest. */ 636 /* Load main position relative to tab->node into dest. */
632 khash = irref_isk(refkey) ? ir_khash(irkey) : 1; 637 khash = irref_isk(refkey) ? ir_khash(irkey) : 1;
@@ -1694,7 +1699,14 @@ static void asm_ir(ASMState *as, IRIns *ir)
1694 case IR_GCSTEP: asm_gcstep(as, ir); break; 1699 case IR_GCSTEP: asm_gcstep(as, ir); break;
1695 1700
1696 /* Guarded assertions. */ 1701 /* Guarded assertions. */
1697 case IR_EQ: case IR_NE: asm_compeq(as, ir); break; 1702 case IR_EQ: case IR_NE:
1703 if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
1704 as->curins--;
1705 asm_href(as, ir-1, (IROp)ir->o);
1706 break;
1707 }
1708 asm_compeq(as, ir);
1709 break;
1698 case IR_LT: case IR_GE: case IR_LE: case IR_GT: 1710 case IR_LT: case IR_GE: case IR_LE: case IR_GT:
1699 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT: 1711 case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
1700 case IR_ABC: 1712 case IR_ABC:
@@ -1749,7 +1761,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
1749 1761
1750 /* Memory references. */ 1762 /* Memory references. */
1751 case IR_AREF: asm_aref(as, ir); break; 1763 case IR_AREF: asm_aref(as, ir); break;
1752 case IR_HREF: asm_href(as, ir); break; 1764 case IR_HREF: asm_href(as, ir, 0); break;
1753 case IR_HREFK: asm_hrefk(as, ir); break; 1765 case IR_HREFK: asm_hrefk(as, ir); break;
1754 case IR_NEWREF: asm_newref(as, ir); break; 1766 case IR_NEWREF: asm_newref(as, ir); break;
1755 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; 1767 case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;