diff options
-rw-r--r-- | src/lj_emit_arm64.h | 32 |
1 files changed, 12 insertions, 20 deletions
diff --git a/src/lj_emit_arm64.h b/src/lj_emit_arm64.h index 6926c71a..7205ce78 100644 --- a/src/lj_emit_arm64.h +++ b/src/lj_emit_arm64.h | |||
@@ -43,26 +43,18 @@ static uint32_t emit_isk12(int64_t n) | |||
43 | /* Encode constant in K13 format for logical data processing instructions. */ | 43 | /* Encode constant in K13 format for logical data processing instructions. */ |
44 | static uint32_t emit_isk13(uint64_t n, int is64) | 44 | static uint32_t emit_isk13(uint64_t n, int is64) |
45 | { | 45 | { |
46 | int inv = 0, w = 128, lz, tz; | 46 | /* Thanks to: https://dougallj.wordpress.com/2021/10/30/ */ |
47 | if (n & 1) { n = ~n; w = 64; inv = 1; } /* Avoid wrap-around of ones. */ | 47 | int rot, ones, size, immr, imms; |
48 | if (!n) return 0; /* Neither all-zero nor all-ones are allowed. */ | 48 | if (!is64) n = ((uint64_t)n << 32) | (uint32_t)n; |
49 | do { /* Find the repeat width. */ | 49 | if ((n+1u) <= 1u) return 0; /* Neither all-zero nor all-ones are allowed. */ |
50 | if (is64 && (uint32_t)(n^(n>>32))) break; | 50 | rot = (n & (n+1u)) ? emit_ctz64(n & (n+1u)) : 64; |
51 | n = (uint32_t)n; | 51 | n = lj_ror(n, rot & 63); |
52 | if (!n) return 0; /* Ditto when passing n=0xffffffff and is64=0. */ | 52 | ones = emit_ctz64(~n); |
53 | w = 32; if ((n^(n>>16)) & 0xffff) break; | 53 | size = emit_clz64(n) + ones; |
54 | n = n & 0xffff; w = 16; if ((n^(n>>8)) & 0xff) break; | 54 | if (lj_ror(n, size & 63) != n) return 0; /* Non-repeating? */ |
55 | n = n & 0xff; w = 8; if ((n^(n>>4)) & 0xf) break; | 55 | immr = -rot & (size - 1); |
56 | n = n & 0xf; w = 4; if ((n^(n>>2)) & 0x3) break; | 56 | imms = (-(size << 1) | (ones - 1)) & 63; |
57 | n = n & 0x3; w = 2; | 57 | return A64I_K13 | A64F_IMMR(immr | (size & 64)) | A64F_IMMS(imms); |
58 | } while (0); | ||
59 | lz = emit_clz64(n); | ||
60 | tz = emit_ctz64(n); | ||
61 | if ((int64_t)(n << lz) >> (lz+tz) != -1ll) return 0; /* Non-contiguous? */ | ||
62 | if (inv) | ||
63 | return A64I_K13 | (((lz-w) & 127) << 16) | (((lz+tz-w-1) & 63) << 10); | ||
64 | else | ||
65 | return A64I_K13 | ((w-tz) << 16) | (((63-lz-tz-w-w) & 63) << 10); | ||
66 | } | 58 | } |
67 | 59 | ||
68 | static uint32_t emit_isfpk64(uint64_t n) | 60 | static uint32_t emit_isfpk64(uint64_t n) |