1 
2 #include <stdio.h>
3 
4 typedef  unsigned long long int  ULong;
5 typedef  unsigned int            UInt;
6 
7 __attribute__((noinline))
do_lzcnt32(UInt * flags,UInt * res,UInt arg)8 void do_lzcnt32 ( /*OUT*/UInt* flags, /*OUT*/UInt* res, UInt arg )
9 {
10   UInt block[3] = { arg, 0, 0 };
11   __asm__ __volatile__(
12     "movl $0x55555555, %%esi" "\n\t"
13     "lzcntl 0(%0), %%esi"     "\n\t"
14     "movl %%esi, 4(%0)"       "\n\t"
15     "pushfl"                  "\n\t"
16     "popl %%esi"              "\n\t"
17     "movl %%esi, 8(%0)"       "\n"
18     : : "r"(&block[0]) : "esi","cc","memory"
19   );
20   *res = block[1];
21   *flags = block[2] & 0x8d5;
22 }
23 
24 __attribute__((noinline))
do_lzcnt16(UInt * flags,UInt * res,UInt arg)25 void do_lzcnt16 ( /*OUT*/UInt* flags, /*OUT*/UInt* res, UInt arg )
26 {
27   UInt block[3] = { arg, 0, 0 };
28   __asm__ __volatile__(
29     "movl $0x55555555, %%esi" "\n\t"
30     "lzcntw 0(%0), %%si"      "\n\t"
31     "movl %%esi, 4(%0)"       "\n\t"
32     "pushfl"                  "\n\t"
33     "popl %%esi"              "\n\t"
34     "movl %%esi, 8(%0)"       "\n"
35     : : "r"(&block[0]) : "esi","cc","memory"
36   );
37   *res = block[1];
38   *flags = block[2] & 0x8d5;
39 }
40 
main(void)41 int main ( void )
42 {
43    UInt w;
44 
45    w = 0xFEDC1928;
46    while (1) {
47       UInt res;
48       UInt flags;
49       do_lzcnt32(&flags, &res, w);
50       printf("lzcntl %08x -> %08x %04x\n", w, res, flags);
51       if (w == 0) break;
52       w = ((w >> 2) | (w >> 1)) + (w / 17);
53    }
54 
55    w = 0xFEDC1928;
56    while (1) {
57       UInt res;
58       UInt flags;
59       do_lzcnt16(&flags, &res, w);
60       printf("lzcntw %08x -> %08x %04x\n", w, res, flags);
61       if (w == 0) break;
62       w = ((w >> 2) | (w >> 1)) + (w / 17);
63    }
64 
65    return 0;
66 }
67