diff options
| -rw-r--r-- | src/lj_emit_arm64.h | 36 | ||||
| -rw-r--r-- | 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) | |||
| 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. */ | ||
| 204 | static 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 | |||
| 196 | static void emit_loadk(ASMState *as, Reg rd, uint64_t u64) | 222 | static 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 | |||
| 250 | static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); | 272 | static 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, |
