DynASM/ARM64: Prevent sanitizer warning in dasm_imm13().

Thanks to Jorg Adam Sowa and Peter Cawley. #1522
This commit is contained in:
Mike Pall 2026-10-13 11:56:49 +02:00
parent 0218af7e36
commit a9981441d9

View File

@ -172,44 +172,46 @@ static int dasm_imm12(unsigned int n)
return -1; 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; int n = 0;
while (x) { x >>= 1; n++; } x = ~x;
while (x & 1) { x >>= 1; n++; }
return 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) 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 n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
unsigned long long m = 1ULL, a, b, c; if ((n+1u) <= 1u) return -1; /* Neither all-zero nor all-ones are allowed. */
if (n & 1) { n = ~n; inv = 1; } rot = (n & (n+1u)) ? dasm_ctz(n & (n+1u)) : 64;
a = n & (unsigned long long)-(long long)n; n = dasm_ror(n, rot & 63);
b = (n+a)&(unsigned long long)-(long long)(n+a); ones = dasm_ctz(~n);
c = (n+a-b)&(unsigned long long)-(long long)(n+a-b); size = dasm_clz(n) + ones;
xa = dasm_ffs(a); xb = dasm_ffs(b); if (dasm_ror(n, size & 63) != n) return -1; /* Non-repeating? */
if (c) { immr = -rot & (size - 1);
w = dasm_ffs(c) - xa; imms = (-(size << 1) | (ones - 1)) & 63;
if (w == 32) m = 0x0000000100000001UL; return ((immr | (size & 64)) << 6) | imms;
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;
} }
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */ /* Pass 1: Store actions and args, link branches/labels, estimate offsets. */