Today I stumbled across a very nice gcc specific builtin:
__builtin_constant_p(x)
This evaluates to 1 if x is known to be a compile time constant. A quick test confirmed that it works on stuff as old 2.95.x. This is great, because it obviates the need for the template versions for constant-sized rotates. For example:
inline uint32 rotLeft32(uint32 bits, uint32 val)
{
if (__builtin_constant_p(bits)) {
// from template version
if (bits&31) {
// only rotate when modulus 32 > 0
if ((bits&31) < 9) {
asm("rol.l %1, %0" : "=d"(val) : "I"(bits&31), "0"(val) : "cc");
}
else if ((bits&31)==16) {
asm("swap %0" : "=d"(val) : "0"(val) : "cc");
}
else if ((bits&31)>23) {
// use opposite rotate for N > 23
asm("ror.l %1, %0" : "=d"(val) : "I"(32-(bits&31)), "0"(val) : "cc");
}
else {
// use register rotate for all intermediate sizes
asm("rol.l %1, %0" : "=d"(val) : "d"(bits&31), "0"(val) : "cc");
}
}
}
else {
asm("rol.l %1, %0" : "=d"(val) : "d"(bits), "0"(val) : "cc");
}
return val;
}
This single inline emits code as efficiently as the template version in all cases where bits evaluates to a constant value at compile time. One thing to note is that __builtin_constant(x) only really works at optimisation levels -O1 and higher.
@Trev
Any progress with the gcc 4 m68k amigaos build?