summaryrefslogtreecommitdiff
path: root/src/vm_arm.dasc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/vm_arm.dasc481
1 files changed, 336 insertions, 145 deletions
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc
index 7dae1a53..4f0798e0 100644
--- a/src/vm_arm.dasc
+++ b/src/vm_arm.dasc
@@ -99,6 +99,7 @@
99|.type NODE, Node 99|.type NODE, Node
100|.type NARGS8, int 100|.type NARGS8, int
101|.type TRACE, GCtrace 101|.type TRACE, GCtrace
102|.type SBUF, SBuf
102| 103|
103|//----------------------------------------------------------------------- 104|//-----------------------------------------------------------------------
104| 105|
@@ -372,6 +373,17 @@ static void build_subroutines(BuildCtx *ctx)
372 | st_vmstate CARG2 373 | st_vmstate CARG2
373 | b ->vm_returnc 374 | b ->vm_returnc
374 | 375 |
376 |->vm_unwind_ext: // Complete external unwind.
377#if !LJ_NO_UNWIND
378 | push {r0, r1, r2, lr}
379 | bl extern _Unwind_Complete
380 | ldr r0, [sp]
381 | bl extern _Unwind_DeleteException
382 | pop {r0, r1, r2, lr}
383 | mov r0, r1
384 | bx r2
385#endif
386 |
375 |//----------------------------------------------------------------------- 387 |//-----------------------------------------------------------------------
376 |//-- Grow stack for calls ----------------------------------------------- 388 |//-- Grow stack for calls -----------------------------------------------
377 |//----------------------------------------------------------------------- 389 |//-----------------------------------------------------------------------
@@ -418,13 +430,14 @@ static void build_subroutines(BuildCtx *ctx)
418 | add CARG2, sp, #CFRAME_RESUME 430 | add CARG2, sp, #CFRAME_RESUME
419 | ldrb CARG1, L->status 431 | ldrb CARG1, L->status
420 | str CARG3, SAVE_ERRF 432 | str CARG3, SAVE_ERRF
421 | str CARG2, L->cframe 433 | str L, SAVE_PC // Any value outside of bytecode is ok.
422 | str CARG3, SAVE_CFRAME 434 | str CARG3, SAVE_CFRAME
423 | cmp CARG1, #0 435 | cmp CARG1, #0
424 | str L, SAVE_PC // Any value outside of bytecode is ok. 436 | str CARG2, L->cframe
425 | beq >3 437 | beq >3
426 | 438 |
427 | // Resume after yield (like a return). 439 | // Resume after yield (like a return).
440 | str L, [DISPATCH, #DISPATCH_GL(cur_L)]
428 | mov RA, BASE 441 | mov RA, BASE
429 | ldr BASE, L->base 442 | ldr BASE, L->base
430 | ldr CARG1, L->top 443 | ldr CARG1, L->top
@@ -458,14 +471,15 @@ static void build_subroutines(BuildCtx *ctx)
458 | str CARG3, SAVE_NRES 471 | str CARG3, SAVE_NRES
459 | mov L, CARG1 472 | mov L, CARG1
460 | str CARG1, SAVE_L 473 | str CARG1, SAVE_L
461 | mov BASE, CARG2
462 | str sp, L->cframe // Add our C frame to cframe chain.
463 | ldr DISPATCH, L->glref // Setup pointer to dispatch table. 474 | ldr DISPATCH, L->glref // Setup pointer to dispatch table.
475 | mov BASE, CARG2
464 | str CARG1, SAVE_PC // Any value outside of bytecode is ok. 476 | str CARG1, SAVE_PC // Any value outside of bytecode is ok.
465 | str RC, SAVE_CFRAME 477 | str RC, SAVE_CFRAME
466 | add DISPATCH, DISPATCH, #GG_G2DISP 478 | add DISPATCH, DISPATCH, #GG_G2DISP
479 | str sp, L->cframe // Add our C frame to cframe chain.
467 | 480 |
468 |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype). 481 |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
482 | str L, [DISPATCH, #DISPATCH_GL(cur_L)]
469 | ldr RB, L->base // RB = old base (for vmeta_call). 483 | ldr RB, L->base // RB = old base (for vmeta_call).
470 | ldr CARG1, L->top 484 | ldr CARG1, L->top
471 | mov MASKR8, #255 485 | mov MASKR8, #255
@@ -491,20 +505,21 @@ static void build_subroutines(BuildCtx *ctx)
491 | mov L, CARG1 505 | mov L, CARG1
492 | ldr RA, L:CARG1->stack 506 | ldr RA, L:CARG1->stack
493 | str CARG1, SAVE_L 507 | str CARG1, SAVE_L
508 | ldr DISPATCH, L->glref // Setup pointer to dispatch table.
494 | ldr RB, L->top 509 | ldr RB, L->top
495 | str CARG1, SAVE_PC // Any value outside of bytecode is ok. 510 | str CARG1, SAVE_PC // Any value outside of bytecode is ok.
496 | ldr RC, L->cframe 511 | ldr RC, L->cframe
512 | add DISPATCH, DISPATCH, #GG_G2DISP
497 | sub RA, RA, RB // Compute -savestack(L, L->top). 513 | sub RA, RA, RB // Compute -savestack(L, L->top).
498 | str sp, L->cframe // Add our C frame to cframe chain.
499 | mov RB, #0 514 | mov RB, #0
500 | str RA, SAVE_NRES // Neg. delta means cframe w/o frame. 515 | str RA, SAVE_NRES // Neg. delta means cframe w/o frame.
501 | str RB, SAVE_ERRF // No error function. 516 | str RB, SAVE_ERRF // No error function.
502 | str RC, SAVE_CFRAME 517 | str RC, SAVE_CFRAME
518 | str sp, L->cframe // Add our C frame to cframe chain.
519 | str L, [DISPATCH, #DISPATCH_GL(cur_L)]
503 | blx CARG4 // (lua_State *L, lua_CFunction func, void *ud) 520 | blx CARG4 // (lua_State *L, lua_CFunction func, void *ud)
504 | ldr DISPATCH, L->glref // Setup pointer to dispatch table.
505 | movs BASE, CRET1 521 | movs BASE, CRET1
506 | mov PC, #FRAME_CP 522 | mov PC, #FRAME_CP
507 | add DISPATCH, DISPATCH, #GG_G2DISP
508 | bne <3 // Else continue with the call. 523 | bne <3 // Else continue with the call.
509 | b ->vm_leave_cp // No base? Just remove C frame. 524 | b ->vm_leave_cp // No base? Just remove C frame.
510 | 525 |
@@ -614,6 +629,16 @@ static void build_subroutines(BuildCtx *ctx)
614 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. 629 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
615 | b ->vm_call_dispatch_f 630 | b ->vm_call_dispatch_f
616 | 631 |
632 |->vmeta_tgetr:
633 | .IOS mov RC, BASE
634 | bl extern lj_tab_getinth // (GCtab *t, int32_t key)
635 | // Returns cTValue * or NULL.
636 | .IOS mov BASE, RC
637 | cmp CRET1, #0
638 | ldrdne CARG12, [CRET1]
639 | mvneq CARG2, #~LJ_TNIL
640 | b ->BC_TGETR_Z
641 |
617 |//----------------------------------------------------------------------- 642 |//-----------------------------------------------------------------------
618 | 643 |
619 |->vmeta_tsets1: 644 |->vmeta_tsets1:
@@ -671,6 +696,16 @@ static void build_subroutines(BuildCtx *ctx)
671 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here. 696 | ldr LFUNC:CARG3, [BASE, FRAME_FUNC] // Guaranteed to be a function here.
672 | b ->vm_call_dispatch_f 697 | b ->vm_call_dispatch_f
673 | 698 |
699 |->vmeta_tsetr:
700 | str BASE, L->base
701 | .IOS mov RC, BASE
702 | mov CARG1, L
703 | str PC, SAVE_PC
704 | bl extern lj_tab_setinth // (lua_State *L, GCtab *t, int32_t key)
705 | // Returns TValue *.
706 | .IOS mov BASE, RC
707 | b ->BC_TSETR_Z
708 |
674 |//-- Comparison metamethods --------------------------------------------- 709 |//-- Comparison metamethods ---------------------------------------------
675 | 710 |
676 |->vmeta_comp: 711 |->vmeta_comp:
@@ -735,6 +770,17 @@ static void build_subroutines(BuildCtx *ctx)
735 | b <3 770 | b <3
736 |.endif 771 |.endif
737 | 772 |
773 |->vmeta_istype:
774 | sub PC, PC, #4
775 | str BASE, L->base
776 | mov CARG1, L
777 | lsr CARG2, RA, #3
778 | mov CARG3, RC
779 | str PC, SAVE_PC
780 | bl extern lj_meta_istype // (lua_State *L, BCReg ra, BCReg tp)
781 | .IOS ldr BASE, L->base
782 | b ->cont_nop
783 |
738 |//-- Arithmetic metamethods --------------------------------------------- 784 |//-- Arithmetic metamethods ---------------------------------------------
739 | 785 |
740 |->vmeta_arith_vn: 786 |->vmeta_arith_vn:
@@ -966,9 +1012,9 @@ static void build_subroutines(BuildCtx *ctx)
966 | cmp TAB:RB, #0 1012 | cmp TAB:RB, #0
967 | beq ->fff_restv 1013 | beq ->fff_restv
968 | ldr CARG3, TAB:RB->hmask 1014 | ldr CARG3, TAB:RB->hmask
969 | ldr CARG4, STR:RC->hash 1015 | ldr CARG4, STR:RC->sid
970 | ldr NODE:INS, TAB:RB->node 1016 | ldr NODE:INS, TAB:RB->node
971 | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask 1017 | and CARG3, CARG3, CARG4 // idx = str->sid & tab->hmask
972 | add CARG3, CARG3, CARG3, lsl #1 1018 | add CARG3, CARG3, CARG3, lsl #1
973 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 1019 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8
974 |3: // Rearranged logic, because we expect _not_ to find the key. 1020 |3: // Rearranged logic, because we expect _not_ to find the key.
@@ -1052,7 +1098,7 @@ static void build_subroutines(BuildCtx *ctx)
1052 | ffgccheck 1098 | ffgccheck
1053 | mov CARG1, L 1099 | mov CARG1, L
1054 | mov CARG2, BASE 1100 | mov CARG2, BASE
1055 | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o) 1101 | bl extern lj_strfmt_number // (lua_State *L, cTValue *o)
1056 | // Returns GCstr *. 1102 | // Returns GCstr *.
1057 | ldr BASE, L->base 1103 | ldr BASE, L->base
1058 | mvn CARG2, #~LJ_TSTR 1104 | mvn CARG2, #~LJ_TSTR
@@ -1065,24 +1111,18 @@ static void build_subroutines(BuildCtx *ctx)
1065 | checktab CARG2, ->fff_fallback 1111 | checktab CARG2, ->fff_fallback
1066 | strd CARG34, [BASE, NARGS8:RC] // Set missing 2nd arg to nil. 1112 | strd CARG34, [BASE, NARGS8:RC] // Set missing 2nd arg to nil.
1067 | ldr PC, [BASE, FRAME_PC] 1113 | ldr PC, [BASE, FRAME_PC]
1068 | mov CARG2, CARG1 1114 | add CARG2, BASE, #8
1069 | str BASE, L->base // Add frame since C call can throw. 1115 | sub CARG3, BASE, #8
1070 | mov CARG1, L 1116 | bl extern lj_tab_next // (GCtab *t, cTValue *key, TValue *o)
1071 | str BASE, L->top // Dummy frame length is ok. 1117 | // Returns 1=found, 0=end, -1=error.
1072 | add CARG3, BASE, #8
1073 | str PC, SAVE_PC
1074 | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
1075 | // Returns 0 at end of traversal.
1076 | .IOS ldr BASE, L->base 1118 | .IOS ldr BASE, L->base
1077 | cmp CRET1, #0 1119 | cmp CRET1, #0
1078 | mvneq CRET2, #~LJ_TNIL 1120 | mov RC, #(2+1)*8
1079 | beq ->fff_restv // End of traversal: return nil. 1121 | bgt ->fff_res // Found key/value.
1080 | ldrd CARG12, [BASE, #8] // Copy key and value to results. 1122 | bmi ->fff_fallback // Invalid key.
1081 | ldrd CARG34, [BASE, #16] 1123 | // End of traversal: return nil.
1082 | mov RC, #(2+1)*8 1124 | mvn CRET2, #~LJ_TNIL
1083 | strd CARG12, [BASE, #-8] 1125 | b ->fff_restv
1084 | strd CARG34, [BASE]
1085 | b ->fff_res
1086 | 1126 |
1087 |.ffunc_1 pairs 1127 |.ffunc_1 pairs
1088 | checktab CARG2, ->fff_fallback 1128 | checktab CARG2, ->fff_fallback
@@ -1230,9 +1270,10 @@ static void build_subroutines(BuildCtx *ctx)
1230 | ldr CARG3, L:RA->base 1270 | ldr CARG3, L:RA->base
1231 | mv_vmstate CARG2, INTERP 1271 | mv_vmstate CARG2, INTERP
1232 | ldr CARG4, L:RA->top 1272 | ldr CARG4, L:RA->top
1233 | st_vmstate CARG2
1234 | cmp CRET1, #LUA_YIELD 1273 | cmp CRET1, #LUA_YIELD
1235 | ldr BASE, L->base 1274 | ldr BASE, L->base
1275 | str L, [DISPATCH, #DISPATCH_GL(cur_L)]
1276 | st_vmstate CARG2
1236 | bhi >8 1277 | bhi >8
1237 | subs RC, CARG4, CARG3 1278 | subs RC, CARG4, CARG3
1238 | ldr CARG1, L->maxstack 1279 | ldr CARG1, L->maxstack
@@ -1500,19 +1541,6 @@ static void build_subroutines(BuildCtx *ctx)
1500 | math_extern2 atan2 1541 | math_extern2 atan2
1501 | math_extern2 fmod 1542 | math_extern2 fmod
1502 | 1543 |
1503 |->ff_math_deg:
1504 |.if FPU
1505 | .ffunc_d math_rad
1506 | vldr d1, CFUNC:CARG3->upvalue[0]
1507 | vmul.f64 d0, d0, d1
1508 | b ->fff_resd
1509 |.else
1510 | .ffunc_n math_rad
1511 | ldrd CARG34, CFUNC:CARG3->upvalue[0]
1512 | bl extern __aeabi_dmul
1513 | b ->fff_restv
1514 |.endif
1515 |
1516 |.if HFABI 1544 |.if HFABI
1517 | .ffunc math_ldexp 1545 | .ffunc math_ldexp
1518 | ldr CARG4, [BASE, #4] 1546 | ldr CARG4, [BASE, #4]
@@ -1682,17 +1710,11 @@ static void build_subroutines(BuildCtx *ctx)
1682 |.endif 1710 |.endif
1683 |.endmacro 1711 |.endmacro
1684 | 1712 |
1685 | math_minmax math_min, gt, hi 1713 | math_minmax math_min, gt, pl
1686 | math_minmax math_max, lt, lo 1714 | math_minmax math_max, lt, le
1687 | 1715 |
1688 |//-- String library ----------------------------------------------------- 1716 |//-- String library -----------------------------------------------------
1689 | 1717 |
1690 |.ffunc_1 string_len
1691 | checkstr CARG2, ->fff_fallback
1692 | ldr CARG1, STR:CARG1->len
1693 | mvn CARG2, #~LJ_TISNUM
1694 | b ->fff_restv
1695 |
1696 |.ffunc string_byte // Only handle the 1-arg case here. 1718 |.ffunc string_byte // Only handle the 1-arg case here.
1697 | ldrd CARG12, [BASE] 1719 | ldrd CARG12, [BASE]
1698 | ldr PC, [BASE, FRAME_PC] 1720 | ldr PC, [BASE, FRAME_PC]
@@ -1725,6 +1747,7 @@ static void build_subroutines(BuildCtx *ctx)
1725 | mov CARG1, L 1747 | mov CARG1, L
1726 | str PC, SAVE_PC 1748 | str PC, SAVE_PC
1727 | bl extern lj_str_new // (lua_State *L, char *str, size_t l) 1749 | bl extern lj_str_new // (lua_State *L, char *str, size_t l)
1750 |->fff_resstr:
1728 | // Returns GCstr *. 1751 | // Returns GCstr *.
1729 | ldr BASE, L->base 1752 | ldr BASE, L->base
1730 | mvn CARG2, #~LJ_TSTR 1753 | mvn CARG2, #~LJ_TSTR
@@ -1768,91 +1791,28 @@ static void build_subroutines(BuildCtx *ctx)
1768 | mvn CARG2, #~LJ_TSTR 1791 | mvn CARG2, #~LJ_TSTR
1769 | b ->fff_restv 1792 | b ->fff_restv
1770 | 1793 |
1771 |.ffunc string_rep // Only handle the 1-char case inline. 1794 |.macro ffstring_op, name
1795 | .ffunc string_ .. name
1772 | ffgccheck 1796 | ffgccheck
1773 | ldrd CARG12, [BASE] 1797 | ldr CARG3, [BASE, #4]
1774 | ldrd CARG34, [BASE, #8]
1775 | cmp NARGS8:RC, #16
1776 | bne ->fff_fallback // Exactly 2 arguments
1777 | checktp CARG2, LJ_TSTR
1778 | checktpeq CARG4, LJ_TISNUM
1779 | bne ->fff_fallback
1780 | subs CARG4, CARG3, #1
1781 | ldr CARG2, STR:CARG1->len
1782 | blt ->fff_emptystr // Count <= 0?
1783 | cmp CARG2, #1
1784 | blo ->fff_emptystr // Zero-length string?
1785 | bne ->fff_fallback // Fallback for > 1-char strings.
1786 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)]
1787 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)]
1788 | ldr CARG1, STR:CARG1[1]
1789 | cmp RB, CARG3
1790 | blo ->fff_fallback
1791 |1: // Fill buffer with char.
1792 | strb CARG1, [CARG2, CARG4]
1793 | subs CARG4, CARG4, #1
1794 | bge <1
1795 | b ->fff_newstr
1796 |
1797 |.ffunc string_reverse
1798 | ffgccheck
1799 | ldrd CARG12, [BASE]
1800 | cmp NARGS8:RC, #8
1801 | blo ->fff_fallback
1802 | checkstr CARG2, ->fff_fallback
1803 | ldr CARG3, STR:CARG1->len
1804 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)]
1805 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)]
1806 | mov CARG4, CARG3
1807 | add CARG1, STR:CARG1, #sizeof(GCstr)
1808 | cmp RB, CARG3
1809 | blo ->fff_fallback
1810 |1: // Reverse string copy.
1811 | ldrb RB, [CARG1], #1
1812 | subs CARG4, CARG4, #1
1813 | blt ->fff_newstr
1814 | strb RB, [CARG2, CARG4]
1815 | b <1
1816 |
1817 |.macro ffstring_case, name, lo
1818 | .ffunc name
1819 | ffgccheck
1820 | ldrd CARG12, [BASE]
1821 | cmp NARGS8:RC, #8 1798 | cmp NARGS8:RC, #8
1799 | ldr STR:CARG2, [BASE]
1822 | blo ->fff_fallback 1800 | blo ->fff_fallback
1823 | checkstr CARG2, ->fff_fallback 1801 | sub SBUF:CARG1, DISPATCH, #-DISPATCH_GL(tmpbuf)
1824 | ldr CARG3, STR:CARG1->len 1802 | checkstr CARG3, ->fff_fallback
1825 | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.sz)] 1803 | ldr CARG4, SBUF:CARG1->b
1826 | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.buf)] 1804 | str BASE, L->base
1827 | mov CARG4, #0 1805 | str PC, SAVE_PC
1828 | add CARG1, STR:CARG1, #sizeof(GCstr) 1806 | str L, SBUF:CARG1->L
1829 | cmp RB, CARG3 1807 | str CARG4, SBUF:CARG1->w
1830 | blo ->fff_fallback 1808 | bl extern lj_buf_putstr_ .. name
1831 |1: // ASCII case conversion. 1809 | bl extern lj_buf_tostr
1832 | ldrb RB, [CARG1, CARG4] 1810 | b ->fff_resstr
1833 | cmp CARG4, CARG3
1834 | bhs ->fff_newstr
1835 | sub RC, RB, #lo
1836 | cmp RC, #26
1837 | eorlo RB, RB, #0x20
1838 | strb RB, [CARG2, CARG4]
1839 | add CARG4, CARG4, #1
1840 | b <1
1841 |.endmacro 1811 |.endmacro
1842 | 1812 |
1843 |ffstring_case string_lower, 65 1813 |ffstring_op reverse
1844 |ffstring_case string_upper, 97 1814 |ffstring_op lower
1845 | 1815 |ffstring_op upper
1846 |//-- Table library ------------------------------------------------------
1847 |
1848 |.ffunc_1 table_getn
1849 | checktab CARG2, ->fff_fallback
1850 | .IOS mov RA, BASE
1851 | bl extern lj_tab_len // (GCtab *t)
1852 | // Returns uint32_t (but less than 2^31).
1853 | .IOS mov BASE, RA
1854 | mvn CARG2, #~LJ_TISNUM
1855 | b ->fff_restv
1856 | 1816 |
1857 |//-- Bit library -------------------------------------------------------- 1817 |//-- Bit library --------------------------------------------------------
1858 | 1818 |
@@ -2127,6 +2087,66 @@ static void build_subroutines(BuildCtx *ctx)
2127 | ldr INS, [PC, #-4] 2087 | ldr INS, [PC, #-4]
2128 | bx CRET1 2088 | bx CRET1
2129 | 2089 |
2090 |->cont_stitch: // Trace stitching.
2091 |.if JIT
2092 | // RA = resultptr, CARG4 = meta base
2093 | ldr RB, SAVE_MULTRES
2094 | ldr INS, [PC, #-4]
2095 | ldr TRACE:CARG3, [CARG4, #-24] // Save previous trace.
2096 | subs RB, RB, #8
2097 | decode_RA8 RC, INS // Call base.
2098 | beq >2
2099 |1: // Move results down.
2100 | ldrd CARG12, [RA]
2101 | add RA, RA, #8
2102 | subs RB, RB, #8
2103 | strd CARG12, [BASE, RC]
2104 | add RC, RC, #8
2105 | bne <1
2106 |2:
2107 | decode_RA8 RA, INS
2108 | decode_RB8 RB, INS
2109 | add RA, RA, RB
2110 |3:
2111 | cmp RA, RC
2112 | mvn CARG2, #~LJ_TNIL
2113 | bhi >9 // More results wanted?
2114 |
2115 | ldrh RA, TRACE:CARG3->traceno
2116 | ldrh RC, TRACE:CARG3->link
2117 | cmp RC, RA
2118 | beq ->cont_nop // Blacklisted.
2119 | cmp RC, #0
2120 | bne =>BC_JLOOP // Jump to stitched trace.
2121 |
2122 | // Stitch a new trace to the previous trace.
2123 | str RA, [DISPATCH, #DISPATCH_J(exitno)]
2124 | str L, [DISPATCH, #DISPATCH_J(L)]
2125 | str BASE, L->base
2126 | sub CARG1, DISPATCH, #-GG_DISP2J
2127 | mov CARG2, PC
2128 | bl extern lj_dispatch_stitch // (jit_State *J, const BCIns *pc)
2129 | ldr BASE, L->base
2130 | b ->cont_nop
2131 |
2132 |9: // Fill up results with nil.
2133 | strd CARG12, [BASE, RC]
2134 | add RC, RC, #8
2135 | b <3
2136 |.endif
2137 |
2138 |->vm_profhook: // Dispatch target for profiler hook.
2139#if LJ_HASPROFILE
2140 | mov CARG1, L
2141 | str BASE, L->base
2142 | mov CARG2, PC
2143 | bl extern lj_dispatch_profile // (lua_State *L, const BCIns *pc)
2144 | // HOOK_PROFILE is off again, so re-dispatch to dynamic instruction.
2145 | ldr BASE, L->base
2146 | sub PC, PC, #4
2147 | b ->cont_nop
2148#endif
2149 |
2130 |//----------------------------------------------------------------------- 2150 |//-----------------------------------------------------------------------
2131 |//-- Trace exit handler ------------------------------------------------- 2151 |//-- Trace exit handler -------------------------------------------------
2132 |//----------------------------------------------------------------------- 2152 |//-----------------------------------------------------------------------
@@ -2151,14 +2171,14 @@ static void build_subroutines(BuildCtx *ctx)
2151 | add CARG1, CARG1, CARG2, asr #6 2171 | add CARG1, CARG1, CARG2, asr #6
2152 | ldr CARG2, [lr, #4] // Load exit stub group offset. 2172 | ldr CARG2, [lr, #4] // Load exit stub group offset.
2153 | sub CARG1, CARG1, lr 2173 | sub CARG1, CARG1, lr
2154 | ldr L, [DISPATCH, #DISPATCH_GL(jit_L)] 2174 | ldr L, [DISPATCH, #DISPATCH_GL(cur_L)]
2155 | add CARG1, CARG2, CARG1, lsr #2 // Compute exit number. 2175 | add CARG1, CARG2, CARG1, lsr #2 // Compute exit number.
2156 | ldr BASE, [DISPATCH, #DISPATCH_GL(jit_base)] 2176 | ldr BASE, [DISPATCH, #DISPATCH_GL(jit_base)]
2157 | str CARG1, [DISPATCH, #DISPATCH_J(exitno)] 2177 | str CARG1, [DISPATCH, #DISPATCH_J(exitno)]
2158 | mov CARG4, #0 2178 | mov CARG4, #0
2159 | str L, [DISPATCH, #DISPATCH_J(L)]
2160 | str BASE, L->base 2179 | str BASE, L->base
2161 | str CARG4, [DISPATCH, #DISPATCH_GL(jit_L)] 2180 | str L, [DISPATCH, #DISPATCH_J(L)]
2181 | str CARG4, [DISPATCH, #DISPATCH_GL(jit_base)]
2162 | sub CARG1, DISPATCH, #-GG_DISP2J 2182 | sub CARG1, DISPATCH, #-GG_DISP2J
2163 | mov CARG2, sp 2183 | mov CARG2, sp
2164 | bl extern lj_trace_exit // (jit_State *J, ExitState *ex) 2184 | bl extern lj_trace_exit // (jit_State *J, ExitState *ex)
@@ -2176,14 +2196,15 @@ static void build_subroutines(BuildCtx *ctx)
2176 |.if JIT 2196 |.if JIT
2177 | ldr L, SAVE_L 2197 | ldr L, SAVE_L
2178 |1: 2198 |1:
2179 | cmp CARG1, #0 2199 | cmn CARG1, #LUA_ERRERR
2180 | blt >3 // Check for error from exit. 2200 | bhs >9 // Check for error from exit.
2181 | lsl RC, CARG1, #3 2201 | lsl RC, CARG1, #3
2182 | ldr LFUNC:CARG2, [BASE, FRAME_FUNC] 2202 | ldr LFUNC:CARG2, [BASE, FRAME_FUNC]
2183 | str RC, SAVE_MULTRES 2203 | str RC, SAVE_MULTRES
2184 | mov CARG3, #0 2204 | mov CARG3, #0
2205 | str BASE, L->base
2185 | ldr CARG2, LFUNC:CARG2->field_pc 2206 | ldr CARG2, LFUNC:CARG2->field_pc
2186 | str CARG3, [DISPATCH, #DISPATCH_GL(jit_L)] 2207 | str CARG3, [DISPATCH, #DISPATCH_GL(jit_base)]
2187 | mv_vmstate CARG4, INTERP 2208 | mv_vmstate CARG4, INTERP
2188 | ldr KBASE, [CARG2, #PC2PROTO(k)] 2209 | ldr KBASE, [CARG2, #PC2PROTO(k)]
2189 | // Modified copy of ins_next which handles function header dispatch, too. 2210 | // Modified copy of ins_next which handles function header dispatch, too.
@@ -2192,17 +2213,48 @@ static void build_subroutines(BuildCtx *ctx)
2192 | ldr INS, [PC], #4 2213 | ldr INS, [PC], #4
2193 | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8. 2214 | lsl MASKR8, MASKR8, #3 // MASKR8 = 255*8.
2194 | st_vmstate CARG4 2215 | st_vmstate CARG4
2216 | cmn CARG1, #17 // Static dispatch?
2217 | beq >5
2218 | cmp OP, #BC_FUNCC+2 // Fast function?
2219 | bhs >4
2220 |2:
2195 | cmp OP, #BC_FUNCF // Function header? 2221 | cmp OP, #BC_FUNCF // Function header?
2196 | ldr OP, [DISPATCH, OP, lsl #2] 2222 | ldr OP, [DISPATCH, OP, lsl #2]
2197 | decode_RA8 RA, INS 2223 | decode_RA8 RA, INS
2198 | lsrlo RC, INS, #16 // No: Decode operands A*8 and D. 2224 | lsrlo RC, INS, #16 // No: Decode operands A*8 and D.
2199 | subhs RC, RC, #8 2225 | subhs RC, RC, #8
2200 | addhs RA, RA, BASE // Yes: RA = BASE+framesize*8, RC = nargs*8 2226 | addhs RA, RA, BASE // Yes: RA = BASE+framesize*8, RC = nargs*8
2227 | ldrhs CARG3, [BASE, FRAME_FUNC]
2201 | bx OP 2228 | bx OP
2202 | 2229 |
2203 |3: // Rethrow error from the right C frame. 2230 |4: // Check frame below fast function.
2231 | ldr CARG1, [BASE, FRAME_PC]
2232 | ands CARG2, CARG1, #FRAME_TYPE
2233 | bne <2 // Trace stitching continuation?
2234 | // Otherwise set KBASE for Lua function below fast function.
2235 | ldr CARG3, [CARG1, #-4]
2236 | decode_RA8 CARG1, CARG3
2237 | sub CARG2, BASE, CARG1
2238 | ldr LFUNC:CARG3, [CARG2, #-16]
2239 | ldr CARG3, LFUNC:CARG3->field_pc
2240 | ldr KBASE, [CARG3, #PC2PROTO(k)]
2241 | b <2
2242 |
2243 |5: // Dispatch to static entry of original ins replaced by BC_JLOOP.
2244 | ldr CARG1, [DISPATCH, #DISPATCH_J(trace)]
2245 | decode_RD RC, INS
2246 | ldr TRACE:CARG1, [CARG1, RC, lsl #2]
2247 | ldr INS, TRACE:CARG1->startins
2248 | decode_OP OP, INS
2249 | decode_RA8 RA, INS
2250 | add OP, DISPATCH, OP, lsl #2
2251 | decode_RD RC, INS
2252 | ldr pc, [OP, #GG_DISP2STATIC]
2253 |
2254 |9: // Rethrow error from the right C frame.
2255 | rsb CARG2, CARG1, #0
2204 | mov CARG1, L 2256 | mov CARG1, L
2205 | bl extern lj_err_run // (lua_State *L) 2257 | bl extern lj_err_trace // (lua_State *L, int errcode)
2206 |.endif 2258 |.endif
2207 | 2259 |
2208 |//----------------------------------------------------------------------- 2260 |//-----------------------------------------------------------------------
@@ -2385,6 +2437,64 @@ static void build_subroutines(BuildCtx *ctx)
2385 |//-- Miscellaneous functions -------------------------------------------- 2437 |//-- Miscellaneous functions --------------------------------------------
2386 |//----------------------------------------------------------------------- 2438 |//-----------------------------------------------------------------------
2387 | 2439 |
2440 |.define NEXT_TAB, TAB:CARG1
2441 |.define NEXT_RES, CARG1
2442 |.define NEXT_IDX, CARG2
2443 |.define NEXT_TMP0, CARG3
2444 |.define NEXT_TMP1, CARG4
2445 |.define NEXT_LIM, r12
2446 |.define NEXT_RES_PTR, sp
2447 |.define NEXT_RES_VAL, [sp]
2448 |.define NEXT_RES_KEY_I, [sp, #8]
2449 |.define NEXT_RES_KEY_IT, [sp, #12]
2450 |
2451 |// TValue *lj_vm_next(GCtab *t, uint32_t idx)
2452 |// Next idx returned in CRET2.
2453 |->vm_next:
2454 |.if JIT
2455 | ldr NEXT_TMP0, NEXT_TAB->array
2456 | ldr NEXT_LIM, NEXT_TAB->asize
2457 | add NEXT_TMP0, NEXT_TMP0, NEXT_IDX, lsl #3
2458 |1: // Traverse array part.
2459 | subs NEXT_TMP1, NEXT_IDX, NEXT_LIM
2460 | bhs >5
2461 | ldr NEXT_TMP1, [NEXT_TMP0, #4]
2462 | str NEXT_IDX, NEXT_RES_KEY_I
2463 | add NEXT_TMP0, NEXT_TMP0, #8
2464 | add NEXT_IDX, NEXT_IDX, #1
2465 | checktp NEXT_TMP1, LJ_TNIL
2466 | beq <1 // Skip holes in array part.
2467 | ldr NEXT_TMP0, [NEXT_TMP0, #-8]
2468 | mov NEXT_RES, NEXT_RES_PTR
2469 | strd NEXT_TMP0, NEXT_RES_VAL // Stores NEXT_TMP1, too.
2470 | mvn NEXT_TMP0, #~LJ_TISNUM
2471 | str NEXT_TMP0, NEXT_RES_KEY_IT
2472 | bx lr
2473 |
2474 |5: // Traverse hash part.
2475 | ldr NEXT_TMP0, NEXT_TAB->hmask
2476 | ldr NODE:NEXT_RES, NEXT_TAB->node
2477 | add NEXT_TMP1, NEXT_TMP1, NEXT_TMP1, lsl #1
2478 | add NEXT_LIM, NEXT_LIM, NEXT_TMP0
2479 | add NODE:NEXT_RES, NODE:NEXT_RES, NEXT_TMP1, lsl #3
2480 |6:
2481 | cmp NEXT_IDX, NEXT_LIM
2482 | bhi >9
2483 | ldr NEXT_TMP1, NODE:NEXT_RES->val.it
2484 | checktp NEXT_TMP1, LJ_TNIL
2485 | add NEXT_IDX, NEXT_IDX, #1
2486 | bxne lr
2487 | // Skip holes in hash part.
2488 | add NEXT_RES, NEXT_RES, #sizeof(Node)
2489 | b <6
2490 |
2491 |9: // End of iteration. Set the key to nil (not the value).
2492 | mvn NEXT_TMP0, #0
2493 | mov NEXT_RES, NEXT_RES_PTR
2494 | str NEXT_TMP0, NEXT_RES_KEY_IT
2495 | bx lr
2496 |.endif
2497 |
2388 |//----------------------------------------------------------------------- 2498 |//-----------------------------------------------------------------------
2389 |//-- FFI helper functions ----------------------------------------------- 2499 |//-- FFI helper functions -----------------------------------------------
2390 |//----------------------------------------------------------------------- 2500 |//-----------------------------------------------------------------------
@@ -2832,6 +2942,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
2832 | ins_next 2942 | ins_next
2833 break; 2943 break;
2834 2944
2945 case BC_ISTYPE:
2946 | // RA = src*8, RC = -type
2947 | ldrd CARG12, [BASE, RA]
2948 | ins_next1
2949 | cmn CARG2, RC
2950 | ins_next2
2951 | bne ->vmeta_istype
2952 | ins_next3
2953 break;
2954 case BC_ISNUM:
2955 | // RA = src*8, RC = -(TISNUM-1)
2956 | ldrd CARG12, [BASE, RA]
2957 | ins_next1
2958 | checktp CARG2, LJ_TISNUM
2959 | ins_next2
2960 | bhs ->vmeta_istype
2961 | ins_next3
2962 break;
2963
2835 /* -- Unary ops --------------------------------------------------------- */ 2964 /* -- Unary ops --------------------------------------------------------- */
2836 2965
2837 case BC_MOV: 2966 case BC_MOV:
@@ -3436,10 +3565,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3436 |->BC_TGETS_Z: 3565 |->BC_TGETS_Z:
3437 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 3566 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8
3438 | ldr CARG3, TAB:CARG1->hmask 3567 | ldr CARG3, TAB:CARG1->hmask
3439 | ldr CARG4, STR:RC->hash 3568 | ldr CARG4, STR:RC->sid
3440 | ldr NODE:INS, TAB:CARG1->node 3569 | ldr NODE:INS, TAB:CARG1->node
3441 | mov TAB:RB, TAB:CARG1 3570 | mov TAB:RB, TAB:CARG1
3442 | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask 3571 | and CARG3, CARG3, CARG4 // idx = str->sid & tab->hmask
3443 | add CARG3, CARG3, CARG3, lsl #1 3572 | add CARG3, CARG3, CARG3, lsl #1
3444 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 3573 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8
3445 |1: 3574 |1:
@@ -3502,6 +3631,24 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3502 | bne <1 // 'no __index' flag set: done. 3631 | bne <1 // 'no __index' flag set: done.
3503 | b ->vmeta_tgetb 3632 | b ->vmeta_tgetb
3504 break; 3633 break;
3634 case BC_TGETR:
3635 | decode_RB8 RB, INS
3636 | decode_RC8 RC, INS
3637 | // RA = dst*8, RB = table*8, RC = key*8
3638 | ldr TAB:CARG1, [BASE, RB]
3639 | ldr CARG2, [BASE, RC]
3640 | ldr CARG4, TAB:CARG1->array
3641 | ldr CARG3, TAB:CARG1->asize
3642 | add CARG4, CARG4, CARG2, lsl #3
3643 | cmp CARG2, CARG3 // In array part?
3644 | bhs ->vmeta_tgetr
3645 | ldrd CARG12, [CARG4]
3646 |->BC_TGETR_Z:
3647 | ins_next1
3648 | ins_next2
3649 | strd CARG12, [BASE, RA]
3650 | ins_next3
3651 break;
3505 3652
3506 case BC_TSETV: 3653 case BC_TSETV:
3507 | decode_RB8 RB, INS 3654 | decode_RB8 RB, INS
@@ -3565,10 +3712,10 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3565 |->BC_TSETS_Z: 3712 |->BC_TSETS_Z:
3566 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8 3713 | // (TAB:RB =) TAB:CARG1 = GCtab *, STR:RC = GCstr *, RA = dst*8
3567 | ldr CARG3, TAB:CARG1->hmask 3714 | ldr CARG3, TAB:CARG1->hmask
3568 | ldr CARG4, STR:RC->hash 3715 | ldr CARG4, STR:RC->sid
3569 | ldr NODE:INS, TAB:CARG1->node 3716 | ldr NODE:INS, TAB:CARG1->node
3570 | mov TAB:RB, TAB:CARG1 3717 | mov TAB:RB, TAB:CARG1
3571 | and CARG3, CARG3, CARG4 // idx = str->hash & tab->hmask 3718 | and CARG3, CARG3, CARG4 // idx = str->sid & tab->hmask
3572 | add CARG3, CARG3, CARG3, lsl #1 3719 | add CARG3, CARG3, CARG3, lsl #1
3573 | mov CARG4, #0 3720 | mov CARG4, #0
3574 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8 3721 | add NODE:INS, NODE:INS, CARG3, lsl #3 // node = tab->node + idx*3*8
@@ -3672,6 +3819,32 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3672 | barrierback TAB:CARG1, INS, CARG3 3819 | barrierback TAB:CARG1, INS, CARG3
3673 | b <2 3820 | b <2
3674 break; 3821 break;
3822 case BC_TSETR:
3823 | decode_RB8 RB, INS
3824 | decode_RC8 RC, INS
3825 | // RA = src*8, RB = table*8, RC = key*8
3826 | ldr TAB:CARG2, [BASE, RB]
3827 | ldr CARG3, [BASE, RC]
3828 | ldrb INS, TAB:CARG2->marked
3829 | ldr CARG1, TAB:CARG2->array
3830 | ldr CARG4, TAB:CARG2->asize
3831 | tst INS, #LJ_GC_BLACK // isblack(table)
3832 | add CARG1, CARG1, CARG3, lsl #3
3833 | bne >7
3834 |2:
3835 | cmp CARG3, CARG4 // In array part?
3836 | bhs ->vmeta_tsetr
3837 |->BC_TSETR_Z:
3838 | ldrd CARG34, [BASE, RA]
3839 | ins_next1
3840 | ins_next2
3841 | strd CARG34, [CARG1]
3842 | ins_next3
3843 |
3844 |7: // Possible table write barrier for the value. Skip valiswhite check.
3845 | barrierback TAB:CARG2, INS, RB
3846 | b <2
3847 break;
3675 3848
3676 case BC_TSETM: 3849 case BC_TSETM:
3677 | // RA = base*8 (table at base-1), RC = num_const (start index) 3850 | // RA = base*8 (table at base-1), RC = num_const (start index)
@@ -3812,10 +3985,11 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3812 break; 3985 break;
3813 3986
3814 case BC_ITERN: 3987 case BC_ITERN:
3815 | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1))
3816 |.if JIT 3988 |.if JIT
3817 | // NYI: add hotloop, record BC_ITERN. 3989 | hotloop
3818 |.endif 3990 |.endif
3991 |->vm_IITERN:
3992 | // RA = base*8, (RB = nresults+1, RC = nargs+1 (2+1))
3819 | add RA, BASE, RA 3993 | add RA, BASE, RA
3820 | ldr TAB:RB, [RA, #-16] 3994 | ldr TAB:RB, [RA, #-16]
3821 | ldr CARG1, [RA, #-8] // Get index from control var. 3995 | ldr CARG1, [RA, #-8] // Get index from control var.
@@ -3881,7 +4055,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3881 | ins_next1 4055 | ins_next1
3882 | ins_next2 4056 | ins_next2
3883 | mov CARG1, #0 4057 | mov CARG1, #0
3884 | mvn CARG2, #0x00018000 4058 | mvn CARG2, #~LJ_KEYINDEX
3885 | strd CARG1, [RA, #-8] // Initialize control var. 4059 | strd CARG1, [RA, #-8] // Initialize control var.
3886 |1: 4060 |1:
3887 | ins_next3 4061 | ins_next3
@@ -3890,9 +4064,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
3890 | mov OP, #BC_ITERC 4064 | mov OP, #BC_ITERC
3891 | strb CARG1, [PC, #-4] 4065 | strb CARG1, [PC, #-4]
3892 | sub PC, RC, #0x20000 4066 | sub PC, RC, #0x20000
4067 |.if JIT
4068 | ldrb CARG1, [PC]
4069 | cmp CARG1, #BC_ITERN
4070 | bne >6
4071 |.endif
3893 | strb OP, [PC] // Subsumes ins_next1. 4072 | strb OP, [PC] // Subsumes ins_next1.
3894 | ins_next2 4073 | ins_next2
3895 | b <1 4074 | b <1
4075 |.if JIT
4076 |6: // Unpatch JLOOP.
4077 | ldr CARG1, [DISPATCH, #DISPATCH_J(trace)]
4078 | ldrh CARG2, [PC, #2]
4079 | ldr TRACE:CARG1, [CARG1, CARG2, lsl #2]
4080 | // Subsumes ins_next1 and ins_next2.
4081 | ldr INS, TRACE:CARG1->startins
4082 | bfi INS, OP, #0, #8
4083 | str INS, [PC], #4
4084 | b <1
4085 |.endif
3896 break; 4086 break;
3897 4087
3898 case BC_VARG: 4088 case BC_VARG:
@@ -4269,7 +4459,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
4269 | st_vmstate CARG2 4459 | st_vmstate CARG2
4270 | ldr RA, TRACE:RC->mcode 4460 | ldr RA, TRACE:RC->mcode
4271 | str BASE, [DISPATCH, #DISPATCH_GL(jit_base)] 4461 | str BASE, [DISPATCH, #DISPATCH_GL(jit_base)]
4272 | str L, [DISPATCH, #DISPATCH_GL(jit_L)] 4462 | str L, [DISPATCH, #DISPATCH_GL(tmpbuf.L)]
4273 | bx RA 4463 | bx RA
4274 |.endif 4464 |.endif
4275 break; 4465 break;
@@ -4387,6 +4577,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
4387 | ldr BASE, L->base 4577 | ldr BASE, L->base
4388 | mv_vmstate CARG3, INTERP 4578 | mv_vmstate CARG3, INTERP
4389 | ldr CRET2, L->top 4579 | ldr CRET2, L->top
4580 | str L, [DISPATCH, #DISPATCH_GL(cur_L)]
4390 | lsl RC, CRET1, #3 4581 | lsl RC, CRET1, #3
4391 | st_vmstate CARG3 4582 | st_vmstate CARG3
4392 | ldr PC, [BASE, FRAME_PC] 4583 | ldr PC, [BASE, FRAME_PC]