aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2023-10-08 22:10:02 +0200
committerMike Pall <mike>2023-10-08 22:10:02 +0200
commitd2a5487fd79b0ce9cd303f84eae13ce12d4db4b7 (patch)
treeb0b36e2f2414d2780b00696bf10ef7bb42988226 /src
parent14866a6828939d86e716939cfd2921ac5aaeca8e (diff)
downloadluajit-d2a5487fd79b0ce9cd303f84eae13ce12d4db4b7.tar.gz
luajit-d2a5487fd79b0ce9cd303f84eae13ce12d4db4b7.tar.bz2
luajit-d2a5487fd79b0ce9cd303f84eae13ce12d4db4b7.zip
ARM64: Use ADR and ADRP to form constants.
Thanks to Peter Cawley. #1100
Diffstat (limited to 'src')
-rw-r--r--src/lj_emit_arm64.h36
-rw-r--r--src/lj_target_arm64.h2
2 files changed, 31 insertions, 7 deletions
diff --git a/src/lj_emit_arm64.h b/src/lj_emit_arm64.h
index 3c510492..51d0c351 100644
--- a/src/lj_emit_arm64.h
+++ b/src/lj_emit_arm64.h
@@ -193,6 +193,32 @@ static int emit_kdelta(ASMState *as, Reg rd, uint64_t k, int is64)
193 return 0; /* Failed. */ 193 return 0; /* Failed. */
194} 194}
195 195
196#define glofs(as, k) \
197 ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g))
198#define mcpofs(as, k) \
199 ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1)))
200#define checkmcpofs(as, k) \
201 (A64F_S_OK(mcpofs(as, k)>>2, 19))
202
203/* Try to form a const as ADR or ADRP or ADRP + ADD. */
204static int emit_kadrp(ASMState *as, Reg rd, uint64_t k)
205{
206 A64Ins ai = A64I_ADR;
207 int64_t ofs = mcpofs(as, k);
208 if (!A64F_S_OK((uint64_t)ofs, 21)) {
209 uint64_t kpage = k & ~0xfffull;
210 MCode *adrp = as->mcp - 1 - (k != kpage);
211 ofs = (int64_t)(kpage - ((uint64_t)adrp & ~0xfffull)) >> 12;
212 if (!A64F_S_OK(ofs, 21))
213 return 0; /* Failed. */
214 if (k != kpage)
215 emit_dn(as, (A64I_ADDx^A64I_K12)|A64F_U12(k - kpage), rd, rd);
216 ai = A64I_ADRP;
217 }
218 emit_d(as, ai|(((uint32_t)ofs&3)<<29)|A64F_S19(ofs>>2), rd);
219 return 1;
220}
221
196static void emit_loadk(ASMState *as, Reg rd, uint64_t u64) 222static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
197{ 223{
198 int zeros = 0, ones = 0, neg, lshift = 0; 224 int zeros = 0, ones = 0, neg, lshift = 0;
@@ -213,6 +239,9 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
213 if (emit_kdelta(as, rd, u64, is64)) { 239 if (emit_kdelta(as, rd, u64, is64)) {
214 return; 240 return;
215 } 241 }
242 if (emit_kadrp(as, rd, u64)) { /* Either 1 or 2 ins. */
243 return;
244 }
216 } 245 }
217 if (neg) { 246 if (neg) {
218 u64 = ~u64; 247 u64 = ~u64;
@@ -240,13 +269,6 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64)
240/* Load a 64 bit constant into a GPR. */ 269/* Load a 64 bit constant into a GPR. */
241#define emit_loadu64(as, rd, i) emit_loadk(as, rd, i) 270#define emit_loadu64(as, rd, i) emit_loadk(as, rd, i)
242 271
243#define glofs(as, k) \
244 ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g))
245#define mcpofs(as, k) \
246 ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1)))
247#define checkmcpofs(as, k) \
248 (A64F_S_OK(mcpofs(as, k)>>2, 19))
249
250static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); 272static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow);
251 273
252/* Get/set from constant pointer. */ 274/* Get/set from constant pointer. */
diff --git a/src/lj_target_arm64.h b/src/lj_target_arm64.h
index 65a14307..c34f1e59 100644
--- a/src/lj_target_arm64.h
+++ b/src/lj_target_arm64.h
@@ -234,6 +234,8 @@ typedef enum A64Ins {
234 A64I_MOVZx = 0xd2800000, 234 A64I_MOVZx = 0xd2800000,
235 A64I_MOVNw = 0x12800000, 235 A64I_MOVNw = 0x12800000,
236 A64I_MOVNx = 0x92800000, 236 A64I_MOVNx = 0x92800000,
237 A64I_ADR = 0x10000000,
238 A64I_ADRP = 0x90000000,
237 239
238 A64I_LDRB = 0x39400000, 240 A64I_LDRB = 0x39400000,
239 A64I_LDRH = 0x79400000, 241 A64I_LDRH = 0x79400000,