diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_asm_arm64.h | 64 |
1 files changed, 37 insertions, 27 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h index cbb186d3..baafa21a 100644 --- a/src/lj_asm_arm64.h +++ b/src/lj_asm_arm64.h | |||
@@ -56,11 +56,11 @@ static void asm_exitstub_setup(ASMState *as, ExitNo nexits) | |||
56 | asm_mclimit(as); | 56 | asm_mclimit(as); |
57 | /* 1: str lr,[sp]; bl ->vm_exit_handler; movz w0,traceno; bl <1; bl <1; ... */ | 57 | /* 1: str lr,[sp]; bl ->vm_exit_handler; movz w0,traceno; bl <1; bl <1; ... */ |
58 | for (i = nexits-1; (int32_t)i >= 0; i--) | 58 | for (i = nexits-1; (int32_t)i >= 0; i--) |
59 | *--mxp = A64I_LE(A64I_BL|((-3-i)&0x03ffffffu)); | 59 | *--mxp = A64I_LE(A64I_BL | A64F_S26(-3-i)); |
60 | *--mxp = A64I_LE(A64I_MOVZw|A64F_U16(as->T->traceno)); | 60 | *--mxp = A64I_LE(A64I_MOVZw | A64F_U16(as->T->traceno)); |
61 | mxp--; | 61 | mxp--; |
62 | *mxp = A64I_LE(A64I_BL|(((MCode *)(void *)lj_vm_exit_handler-mxp)&0x03ffffffu)); | 62 | *mxp = A64I_LE(A64I_BL | A64F_S26(((MCode *)(void *)lj_vm_exit_handler-mxp))); |
63 | *--mxp = A64I_LE(A64I_STRx|A64F_D(RID_LR)|A64F_N(RID_SP)); | 63 | *--mxp = A64I_LE(A64I_STRx | A64F_D(RID_LR) | A64F_N(RID_SP)); |
64 | as->mctop = mxp; | 64 | as->mctop = mxp; |
65 | } | 65 | } |
66 | 66 | ||
@@ -77,7 +77,7 @@ static void asm_guardcc(ASMState *as, A64CC cc) | |||
77 | MCode *p = as->mcp; | 77 | MCode *p = as->mcp; |
78 | if (LJ_UNLIKELY(p == as->invmcp)) { | 78 | if (LJ_UNLIKELY(p == as->invmcp)) { |
79 | as->loopinv = 1; | 79 | as->loopinv = 1; |
80 | *p = A64I_B | ((target-p) & 0x03ffffffu); | 80 | *p = A64I_B | A64F_S26(target-p); |
81 | emit_cond_branch(as, cc^1, p-1); | 81 | emit_cond_branch(as, cc^1, p-1); |
82 | return; | 82 | return; |
83 | } | 83 | } |
@@ -91,7 +91,7 @@ static void asm_guardtnb(ASMState *as, A64Ins ai, Reg r, uint32_t bit) | |||
91 | MCode *p = as->mcp; | 91 | MCode *p = as->mcp; |
92 | if (LJ_UNLIKELY(p == as->invmcp)) { | 92 | if (LJ_UNLIKELY(p == as->invmcp)) { |
93 | as->loopinv = 1; | 93 | as->loopinv = 1; |
94 | *p = A64I_B | ((target-p) & 0x03ffffffu); | 94 | *p = A64I_B | A64F_S26(target-p); |
95 | emit_tnb(as, ai^0x01000000u, r, bit, p-1); | 95 | emit_tnb(as, ai^0x01000000u, r, bit, p-1); |
96 | return; | 96 | return; |
97 | } | 97 | } |
@@ -105,7 +105,7 @@ static void asm_guardcnb(ASMState *as, A64Ins ai, Reg r) | |||
105 | MCode *p = as->mcp; | 105 | MCode *p = as->mcp; |
106 | if (LJ_UNLIKELY(p == as->invmcp)) { | 106 | if (LJ_UNLIKELY(p == as->invmcp)) { |
107 | as->loopinv = 1; | 107 | as->loopinv = 1; |
108 | *p = A64I_B | ((target-p) & 0x03ffffffu); | 108 | *p = A64I_B | A64F_S26(target-p); |
109 | emit_cnb(as, ai^0x01000000u, r, p-1); | 109 | emit_cnb(as, ai^0x01000000u, r, p-1); |
110 | return; | 110 | return; |
111 | } | 111 | } |
@@ -1850,7 +1850,7 @@ static void asm_loop_fixup(ASMState *as) | |||
1850 | p[-2] |= ((uint32_t)delta & mask) << 5; | 1850 | p[-2] |= ((uint32_t)delta & mask) << 5; |
1851 | } else { | 1851 | } else { |
1852 | ptrdiff_t delta = target - (p - 1); | 1852 | ptrdiff_t delta = target - (p - 1); |
1853 | p[-1] = A64I_B | ((uint32_t)(delta) & 0x03ffffffu); | 1853 | p[-1] = A64I_B | A64F_S26(delta); |
1854 | } | 1854 | } |
1855 | } | 1855 | } |
1856 | 1856 | ||
@@ -1919,7 +1919,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk) | |||
1919 | } | 1919 | } |
1920 | /* Patch exit branch. */ | 1920 | /* Patch exit branch. */ |
1921 | target = lnk ? traceref(as->J, lnk)->mcode : (MCode *)lj_vm_exit_interp; | 1921 | target = lnk ? traceref(as->J, lnk)->mcode : (MCode *)lj_vm_exit_interp; |
1922 | p[-1] = A64I_B | (((target-p)+1)&0x03ffffffu); | 1922 | p[-1] = A64I_B | A64F_S26((target-p)+1); |
1923 | } | 1923 | } |
1924 | 1924 | ||
1925 | /* Prepare tail of code. */ | 1925 | /* Prepare tail of code. */ |
@@ -1982,40 +1982,50 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) | |||
1982 | { | 1982 | { |
1983 | MCode *p = T->mcode; | 1983 | MCode *p = T->mcode; |
1984 | MCode *pe = (MCode *)((char *)p + T->szmcode); | 1984 | MCode *pe = (MCode *)((char *)p + T->szmcode); |
1985 | MCode *cstart = NULL, *cend = p; | 1985 | MCode *cstart = NULL; |
1986 | MCode *mcarea = lj_mcode_patch(J, p, 0); | 1986 | MCode *mcarea = lj_mcode_patch(J, p, 0); |
1987 | MCode *px = exitstub_trace_addr(T, exitno); | 1987 | MCode *px = exitstub_trace_addr(T, exitno); |
1988 | /* Note: this assumes a trace exit is only ever patched once. */ | ||
1988 | for (; p < pe; p++) { | 1989 | for (; p < pe; p++) { |
1989 | /* Look for exitstub branch, replace with branch to target. */ | 1990 | /* Look for exitstub branch, replace with branch to target. */ |
1991 | ptrdiff_t delta = target - p; | ||
1990 | MCode ins = A64I_LE(*p); | 1992 | MCode ins = A64I_LE(*p); |
1991 | if ((ins & 0xff000000u) == 0x54000000u && | 1993 | if ((ins & 0xff000000u) == 0x54000000u && |
1992 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { | 1994 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { |
1993 | /* Patch bcc exitstub. */ | 1995 | /* Patch bcc, if within range. */ |
1994 | *p = A64I_LE((ins & 0xff00001fu) | (((target-p)<<5) & 0x00ffffe0u)); | 1996 | if (A64F_S_OK(delta, 19)) { |
1995 | cend = p+1; | 1997 | *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); |
1996 | if (!cstart) cstart = p; | 1998 | if (!cstart) cstart = p; |
1999 | } | ||
1997 | } else if ((ins & 0xfc000000u) == 0x14000000u && | 2000 | } else if ((ins & 0xfc000000u) == 0x14000000u && |
1998 | ((ins ^ (px-p)) & 0x03ffffffu) == 0) { | 2001 | ((ins ^ (px-p)) & 0x03ffffffu) == 0) { |
1999 | /* Patch b exitstub. */ | 2002 | /* Patch b. */ |
2000 | *p = A64I_LE((ins & 0xfc000000u) | ((target-p) & 0x03ffffffu)); | 2003 | lua_assert(A64F_S_OK(delta, 26)); |
2001 | cend = p+1; | 2004 | *p = A64I_LE((ins & 0xfc000000u) | A64F_S26(delta)); |
2002 | if (!cstart) cstart = p; | 2005 | if (!cstart) cstart = p; |
2003 | } else if ((ins & 0x7e000000u) == 0x34000000u && | 2006 | } else if ((ins & 0x7e000000u) == 0x34000000u && |
2004 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { | 2007 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { |
2005 | /* Patch cbz/cbnz exitstub. */ | 2008 | /* Patch cbz/cbnz, if within range. */ |
2006 | *p = A64I_LE((ins & 0xff00001f) | (((target-p)<<5) & 0x00ffffe0u)); | 2009 | if (A64F_S_OK(delta, 19)) { |
2007 | cend = p+1; | 2010 | *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); |
2008 | if (!cstart) cstart = p; | 2011 | if (!cstart) cstart = p; |
2012 | } | ||
2009 | } else if ((ins & 0x7e000000u) == 0x36000000u && | 2013 | } else if ((ins & 0x7e000000u) == 0x36000000u && |
2010 | ((ins ^ ((px-p)<<5)) & 0x0007ffe0u) == 0) { | 2014 | ((ins ^ ((px-p)<<5)) & 0x0007ffe0u) == 0) { |
2011 | /* Patch tbz/tbnz exitstub. */ | 2015 | /* Patch tbz/tbnz, if within range. */ |
2012 | *p = A64I_LE((ins & 0xfff8001fu) | (((target-p)<<5) & 0x0007ffe0u)); | 2016 | if (A64F_S_OK(delta, 14)) { |
2013 | cend = p+1; | 2017 | *p = A64I_LE((ins & 0xfff8001fu) | A64F_S14(delta)); |
2014 | if (!cstart) cstart = p; | 2018 | if (!cstart) cstart = p; |
2019 | } | ||
2015 | } | 2020 | } |
2016 | } | 2021 | } |
2017 | lua_assert(cstart != NULL); | 2022 | { /* Always patch long-range branch in exit stub itself. */ |
2018 | lj_mcode_sync(cstart, cend); | 2023 | ptrdiff_t delta = target - px; |
2024 | lua_assert(A64F_S_OK(delta, 26)); | ||
2025 | *px = A64I_B | A64F_S26(delta); | ||
2026 | if (!cstart) cstart = px; | ||
2027 | } | ||
2028 | lj_mcode_sync(cstart, px+1); | ||
2019 | lj_mcode_patch(J, mcarea, 1); | 2029 | lj_mcode_patch(J, mcarea, 1); |
2020 | } | 2030 | } |
2021 | 2031 | ||