Ideally I'd like to do it without looping. In the code below I certainly loop.
However, is there an assembly instruction that could do this faster? Since arithmetic shifts are done in a barrel shifter (I think), in one cycle, I thought - maybe.
// # sign bit is BIT31, not interesting
// #1111111 11111111 11111111 11111111
// 0 returned
// #0000000 11111111 11111111 11111111
// 1234567 7 returned
// #0000000 00000000 00000000 00000000
// 1234567 89012345 67890123 45678901 31 returned
unsigned Get_Num_High_ZeroBits (const signed unsigned_31bits) { // Only [BIT30..BIT0] are valid
unsigned ibit;
xassert (unsigned_31bits >= 0);
if (unsigned_31bits == 0) { // separate test to avoid looping forever below
ibit = 0; // To return 31 as max
} else {
ibit = 30; // To return 0 as min after the final inc
while ((unsigned_31bits bitand (1<<ibit)) == 0) { // 1 << 30 sets BIT30
ibit--;
}
ibit++; // final inc to avoid doing an (ibit-1) inside the loop
}
return (31-ibit);
}
void Test_Get_Num_High_ZeroBits (void) {
/* Test passed:
zb 0
zb 7
zb 31
*/
signed val;
val = 0x7FFFFFFF; // Sign bit only is zero, so it's still positive
debug_print_special ("zb %u\n", Get_Num_High_ZeroBits (val)); // 0
val = 0x00FFFFFF;
debug_print_special ("zb %u\n", Get_Num_High_ZeroBits (val)); // 7
val = 0x00000000;
debug_print_special ("zb %u\n", Get_Num_High_ZeroBits (val)); // 31
}