Home | History | Annotate | Download | only in amd64
      1 
      2 #include <stdio.h>
      3 
      4 typedef  unsigned long long int  ULong;
      5 typedef  unsigned int            UInt;
      6 
      7 __attribute__((noinline))
      8 void 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))
     25 void 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))
     42 void 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 
     58 int 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