From a9981441d95532fcfcb715c59dcc79f0d32df902 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 13 Oct 2026 11:56:49 +0200 Subject: [PATCH] DynASM/ARM64: Prevent sanitizer warning in dasm_imm13(). Thanks to Jorg Adam Sowa and Peter Cawley. #1522 --- dynasm/dasm_arm64.h | 64 +++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/dynasm/dasm_arm64.h b/dynasm/dasm_arm64.h index a38613c9..be2514e3 100644 --- a/dynasm/dasm_arm64.h +++ b/dynasm/dasm_arm64.h @@ -172,44 +172,46 @@ static int dasm_imm12(unsigned int n) return -1; } -static int dasm_ffs(unsigned long long x) +#if defined(__GNUC__) || defined(__clang__) +#define dasm_ctz(x) __builtin_ctzll(x) +#define dasm_clz(x) __builtin_clzll(x) +#else +static int dasm_ctz(unsigned long long x) { - int n = -1; - while (x) { x >>= 1; n++; } + int n = 0; + x = ~x; + while (x & 1) { x >>= 1; n++; } return n; } +static int dasm_clz(unsigned long long x) +{ + int n = 0; + x = ~x; + while ((long long)x < 0) { x <<= 1; n++; } + return n; +} +#endif + +static unsigned long long dasm_ror(unsigned long long x, int n) +{ + return (x << (-n & 63)) | (x >> n); +} + static int dasm_imm13(int lo, int hi) { - int inv = 0, w = 64, s = 0xfff, xa, xb; + /* Thanks to: https://dougallj.wordpress.com/2021/10/30/ */ + int rot, ones, size, immr, imms; unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo; - unsigned long long m = 1ULL, a, b, c; - if (n & 1) { n = ~n; inv = 1; } - a = n & (unsigned long long)-(long long)n; - b = (n+a)&(unsigned long long)-(long long)(n+a); - c = (n+a-b)&(unsigned long long)-(long long)(n+a-b); - xa = dasm_ffs(a); xb = dasm_ffs(b); - if (c) { - w = dasm_ffs(c) - xa; - if (w == 32) m = 0x0000000100000001UL; - else if (w == 16) m = 0x0001000100010001UL; - else if (w == 8) m = 0x0101010101010101UL; - else if (w == 4) m = 0x1111111111111111UL; - else if (w == 2) m = 0x5555555555555555UL; - else return -1; - s = (-2*w & 0x3f) - 1; - } else if (!a) { - return -1; - } else if (xb == -1) { - xb = 64; - } - if ((b-a) * m != n) return -1; - if (inv) { - return ((w - xb) << 6) | (s+w+xa-xb); - } else { - return ((w - xa) << 6) | (s+xb-xa); - } - return -1; + if ((n+1u) <= 1u) return -1; /* Neither all-zero nor all-ones are allowed. */ + rot = (n & (n+1u)) ? dasm_ctz(n & (n+1u)) : 64; + n = dasm_ror(n, rot & 63); + ones = dasm_ctz(~n); + size = dasm_clz(n) + ones; + if (dasm_ror(n, size & 63) != n) return -1; /* Non-repeating? */ + immr = -rot & (size - 1); + imms = (-(size << 1) | (ones - 1)) & 63; + return ((immr | (size & 64)) << 6) | imms; } /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */