I've been puzzling over your assembly code for a while. Assuming you just had the useful bits in eax and had just executed bswap:
MSB .... byte1... byte2... LSB
00000xxx 00xxxxxx 00xxxxxx 00xxxxxx
How does multiplying (byte1 | LSB) * 3 help? I'm asking about lea ebx, [ebx + ebx*2], which is a shortcut for multiplying by 3.
Genuinely lost here, the 6 bits of byte1 and the 6 bits of LSB are separated by enough 0 bits that a multiplication by 3 won't mix them up. But within the 6 bits of byte1 and within the 6 bits of LSB, the multiplication will mean each bit is the sum of itself, the lower order bit, and any carried bits. What is that for?
The nullprogram.com version is 0x185 bytes (gcc 4.8.4 x86_64 -O3; objdump -s -j .text -j .rodata)
I switched to __builtin_clz (with cross platform support). I hesitate to put in your assembly code, though it would work great! My version still sticks to C and not inline assembly.
My version takes 0xeb bytes.
Benchmarking with clang-802.0.42 -O3 -march=native on a Core i7-4770HQ @ 2.20GHz:
MSB .... byte1... byte2... LSB
00000xxx 00xxxxxx 00xxxxxx 00xxxxxx
How does multiplying (byte1 | LSB) * 3 help? I'm asking about lea ebx, [ebx + ebx*2], which is a shortcut for multiplying by 3.
Genuinely lost here, the 6 bits of byte1 and the 6 bits of LSB are separated by enough 0 bits that a multiplication by 3 won't mix them up. But within the 6 bits of byte1 and within the 6 bits of LSB, the multiplication will mean each bit is the sum of itself, the lower order bit, and any carried bits. What is that for?
Thanks for any tips!