diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_asm_mips.h | 48 |
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 | */ |
573 | static void asm_href(ASMState *as, IRIns *ir) | 573 | static 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; |