#include <stdio.h>
typedef unsigned long long int ULong;
typedef unsigned int UInt;
__attribute__((noinline))
void do_lzcnt32 ( /*OUT*/UInt* flags, /*OUT*/UInt* res, UInt arg )
{
UInt block[3] = { arg, 0, 0 };
__asm__ __volatile__(
"movl $0x55555555, %%esi" "\n\t"
"lzcntl 0(%0), %%esi" "\n\t"
"movl %%esi, 4(%0)" "\n\t"
"pushfl" "\n\t"
"popl %%esi" "\n\t"
"movl %%esi, 8(%0)" "\n"
: : "r"(&block[0]) : "esi","cc","memory"
);
*res = block[1];
*flags = block[2] & 0x8d5;
}
__attribute__((noinline))
void do_lzcnt16 ( /*OUT*/UInt* flags, /*OUT*/UInt* res, UInt arg )
{
UInt block[3] = { arg, 0, 0 };
__asm__ __volatile__(
"movl $0x55555555, %%esi" "\n\t"
"lzcntw 0(%0), %%si" "\n\t"
"movl %%esi, 4(%0)" "\n\t"
"pushfl" "\n\t"
"popl %%esi" "\n\t"
"movl %%esi, 8(%0)" "\n"
: : "r"(&block[0]) : "esi","cc","memory"
);
*res = block[1];
*flags = block[2] & 0x8d5;
}
int main ( void )
{
UInt w;
w = 0xFEDC1928;
while (1) {
UInt res;
UInt flags;
do_lzcnt32(&flags, &res, w);
printf("lzcntl %08x -> %08x %04x\n", w, res, flags);
if (w == 0) break;
w = ((w >> 2) | (w >> 1)) + (w / 17);
}
w = 0xFEDC1928;
while (1) {
UInt res;
UInt flags;
do_lzcnt16(&flags, &res, w);
printf("lzcntw %08x -> %08x %04x\n", w, res, flags);
if (w == 0) break;
w = ((w >> 2) | (w >> 1)) + (w / 17);
}
return 0;
}