1
2#include <stdio.h>
3
4typedef  unsigned long long int  ULong;
5typedef  unsigned int            UInt;
6
7__attribute__((noinline))
8void do_lzcnt64 ( /*OUT*/UInt* flags, /*OUT*/ULong* res, ULong arg )
9{
10  ULong block[3] = { arg, 0ULL, 0ULL };
11  __asm__ __volatile__(
12    "movabsq $0x5555555555555555, %%r11" "\n\t"
13    "lzcntq 0(%0), %%r11"     "\n\t"
14    "movq %%r11, 8(%0)"       "\n\t"
15    "pushfq"                  "\n\t"
16    "popq %%r11"              "\n\t"
17    "movq %%r11, 16(%0)"      "\n"
18    : : "r"(&block[0]) : "r11","cc","memory"
19  );
20  *res = block[1];
21  *flags = block[2] & 0x8d5;
22}
23
24__attribute__((noinline))
25void do_lzcnt32 ( /*OUT*/UInt* flags, /*OUT*/ULong* res, ULong arg )
26{
27  ULong block[3] = { arg, 0ULL, 0ULL };
28  __asm__ __volatile__(
29    "movabsq $0x5555555555555555, %%r11" "\n\t"
30    "lzcntl 0(%0), %%r11d"    "\n\t"
31    "movq %%r11, 8(%0)"       "\n\t"
32    "pushfq"                  "\n\t"
33    "popq %%r11"              "\n\t"
34    "movq %%r11, 16(%0)"      "\n"
35    : : "r"(&block[0]) : "r11","cc","memory"
36  );
37  *res = block[1];
38  *flags = block[2] & 0x8d5;
39}
40
41__attribute__((noinline))
42void do_lzcnt16 ( /*OUT*/UInt* flags, /*OUT*/ULong* res, ULong arg )
43{
44  ULong block[3] = { arg, 0ULL, 0ULL };
45  __asm__ __volatile__(
46    "movabsq $0x5555555555555555, %%r11" "\n\t"
47    "lzcntw 0(%0), %%r11w"    "\n\t"
48    "movq %%r11, 8(%0)"       "\n\t"
49    "pushfq"                  "\n\t"
50    "popq %%r11"              "\n\t"
51    "movq %%r11, 16(%0)"      "\n"
52    : : "r"(&block[0]) : "r11","cc","memory"
53  );
54  *res = block[1];
55  *flags = block[2] & 0x8d5;
56}
57
58int main ( void )
59{
60   ULong w;
61
62   w = 0xFEDC192837475675ULL;
63   while (1) {
64      ULong res;
65      UInt  flags;
66      do_lzcnt64(&flags, &res, w);
67      printf("lzcntq %016llx -> %016llx %04x\n", w, res, flags);
68      if (w == 0) break;
69      w = ((w >> 2) | (w >> 1)) + (w / 17ULL);
70   }
71
72   w = 0xFEDC192837475675ULL;
73   while (1) {
74      ULong res;
75      UInt  flags;
76      do_lzcnt32(&flags, &res, w);
77      printf("lzcntl %016llx -> %016llx %04x\n", w, res, flags);
78      if (w == 0) break;
79      w = ((w >> 2) | (w >> 1)) + (w / 17ULL);
80   }
81
82   w = 0xFEDC192837475675ULL;
83   while (1) {
84      ULong res;
85      UInt  flags;
86      do_lzcnt16(&flags, &res, w);
87      printf("lzcntw %016llx -> %016llx %04x\n", w, res, flags);
88      if (w == 0) break;
89      w = ((w >> 2) | (w >> 1)) + (w / 17ULL);
90   }
91
92   return 0;
93}
94