I have some code that basically needs to use a small expression in an assembly statement, where the expression is fairly trivial like i*4, but GCC doesn't seem to realize that at compile time (tried no -O flag, and -O3). Neither "i" nor "n" constraints work in the following snippet for the third usage.
#include <stdint.h>
#include <stdlib.h>
#define SHIFT(h, l, c) __asm__ volatile ( \
"shld %2, %1, %0\n\t" \
"sal %2, %1\n\t" \
: "+r"(h), "+r"(l) : "i"(c))
void main(void) {
uint64_t a, b;
SHIFT(a, b, 1); /* 1 */
SHIFT(a, b, 2*4); /* 2 */
size_t i;
for(i=0; i<24; i++) {
SHIFT(a, b, (i*4)); /* 3 */
}
}
Giving this error:
temp.c:15: warning: asm operand 2 probably doesn’t match constraints
temp.c:15: error: impossible constraint in ‘asm’
I also tried
"shld $" #c ", %1...
but that has its own issue, because the parens remain when stringified. It's my intention that the entire loop becomes unrolled, but -funroll-all-loops doesn't seem to be happening early enough in the process to cause i*4 to become a constant. Any ideas? The alternative is quite ugly, but if there was a way to automate this in a macro that'd be better than nothing:
SHIFT(a, b, 1);
SHIFT(a, b, 2);
...
SHIFT(a, b, 24);