From d2a5487fd79b0ce9cd303f84eae13ce12d4db4b7 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sun, 8 Oct 2023 22:10:02 +0200 Subject: [PATCH] ARM64: Use ADR and ADRP to form constants. Thanks to Peter Cawley. #1100 --- src/lj_emit_arm64.h | 36 +++++++++++++++++++++++++++++------- src/lj_target_arm64.h | 2 ++ 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) return 0; /* Failed. */ } +#define glofs(as, k) \ + ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g)) +#define mcpofs(as, k) \ + ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1))) +#define checkmcpofs(as, k) \ + (A64F_S_OK(mcpofs(as, k)>>2, 19)) + +/* Try to form a const as ADR or ADRP or ADRP + ADD. */ +static int emit_kadrp(ASMState *as, Reg rd, uint64_t k) +{ + A64Ins ai = A64I_ADR; + int64_t ofs = mcpofs(as, k); + if (!A64F_S_OK((uint64_t)ofs, 21)) { + uint64_t kpage = k & ~0xfffull; + MCode *adrp = as->mcp - 1 - (k != kpage); + ofs = (int64_t)(kpage - ((uint64_t)adrp & ~0xfffull)) >> 12; + if (!A64F_S_OK(ofs, 21)) + return 0; /* Failed. */ + if (k != kpage) + emit_dn(as, (A64I_ADDx^A64I_K12)|A64F_U12(k - kpage), rd, rd); + ai = A64I_ADRP; + } + emit_d(as, ai|(((uint32_t)ofs&3)<<29)|A64F_S19(ofs>>2), rd); + return 1; +} + static void emit_loadk(ASMState *as, Reg rd, uint64_t u64) { int zeros = 0, ones = 0, neg, lshift = 0; @@ -213,6 +239,9 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64) if (emit_kdelta(as, rd, u64, is64)) { return; } + if (emit_kadrp(as, rd, u64)) { /* Either 1 or 2 ins. */ + return; + } } if (neg) { u64 = ~u64; @@ -240,13 +269,6 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64) /* Load a 64 bit constant into a GPR. */ #define emit_loadu64(as, rd, i) emit_loadk(as, rd, i) -#define glofs(as, k) \ - ((intptr_t)((uintptr_t)(k) - (uintptr_t)&J2GG(as->J)->g)) -#define mcpofs(as, k) \ - ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1))) -#define checkmcpofs(as, k) \ - (A64F_S_OK(mcpofs(as, k)>>2, 19)) - static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); /* 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 { A64I_MOVZx = 0xd2800000, A64I_MOVNw = 0x12800000, A64I_MOVNx = 0x92800000, + A64I_ADR = 0x10000000, + A64I_ADRP = 0x90000000, A64I_LDRB = 0x39400000, A64I_LDRH = 0x79400000,