Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MPILIB: Provide count_leading/trailing_zeros() based on arch functions

Provide count_leading/trailing_zeros() macros based on extant arch bit scanning
functions rather than reimplementing from scratch in MPILIB.

Whilst we're at it, turn count_foo_zeros(n, x) into n = count_foo_zeros(x).

Also move the definition to asm-generic as other people may be interested in
using it.

Signed-off-by: David Howells <dhowells@redhat.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Dmitry Kasatkin <dmitry.kasatkin@intel.com>
Cc: Arnd Bergmann <arnd@arndb.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

authored by

David Howells and committed by
Rusty Russell
aacf29bf cf7f601c

+62 -139
+57
include/asm-generic/bitops/count_zeros.h
··· 1 + /* Count leading and trailing zeros functions 2 + * 3 + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 + * Written by David Howells (dhowells@redhat.com) 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public Licence 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the Licence, or (at your option) any later version. 10 + */ 11 + 12 + #ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ 13 + #define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ 14 + 15 + #include <asm/bitops.h> 16 + 17 + /** 18 + * count_leading_zeros - Count the number of zeros from the MSB back 19 + * @x: The value 20 + * 21 + * Count the number of leading zeros from the MSB going towards the LSB in @x. 22 + * 23 + * If the MSB of @x is set, the result is 0. 24 + * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. 25 + * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. 26 + */ 27 + static inline int count_leading_zeros(unsigned long x) 28 + { 29 + if (sizeof(x) == 4) 30 + return BITS_PER_LONG - fls(x); 31 + else 32 + return BITS_PER_LONG - fls64(x); 33 + } 34 + 35 + #define COUNT_LEADING_ZEROS_0 BITS_PER_LONG 36 + 37 + /** 38 + * count_trailing_zeros - Count the number of zeros from the LSB forwards 39 + * @x: The value 40 + * 41 + * Count the number of trailing zeros from the LSB going towards the MSB in @x. 42 + * 43 + * If the LSB of @x is set, the result is 0. 44 + * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. 45 + * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. 46 + */ 47 + static inline int count_trailing_zeros(unsigned long x) 48 + { 49 + #define COUNT_TRAILING_ZEROS_0 (-1) 50 + 51 + if (sizeof(x) == 4) 52 + return ffs(x); 53 + else 54 + return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; 55 + } 56 + 57 + #endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */
+2 -136
lib/mpi/longlong.h
··· 19 19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 20 20 * MA 02111-1307, USA. */ 21 21 22 + #include <asm-generic/bitops/count_zeros.h> 23 + 22 24 /* You have to define the following before including this file: 23 25 * 24 26 * UWtype -- An unsigned type, default type for operations (typically a "word") ··· 148 146 : "1" ((USItype)(n1)), \ 149 147 "r" ((USItype)(n0)), \ 150 148 "r" ((USItype)(d))) 151 - 152 - #define count_leading_zeros(count, x) \ 153 - __asm__ ("clz %0,%1" \ 154 - : "=r" ((USItype)(count)) \ 155 - : "r" ((USItype)(x))) 156 - #define COUNT_LEADING_ZEROS_0 32 157 149 #endif /* __a29k__ */ 158 150 159 151 #if defined(__alpha) && W_TYPE_SIZE == 64 ··· 294 298 : "1" ((USItype)(nh)), \ 295 299 "0" ((USItype)(nl)), \ 296 300 "g" ((USItype)(d))) 297 - #define count_leading_zeros(count, x) \ 298 - __asm__ ("bsch/1 %1,%0" \ 299 - : "=g" (count) \ 300 - : "g" ((USItype)(x)), \ 301 - "0" ((USItype)0)) 302 301 #endif 303 302 304 303 /*************************************** ··· 345 354 } while (0) 346 355 extern USItype __udiv_qrnnd(); 347 356 #endif /* LONGLONG_STANDALONE */ 348 - #define count_leading_zeros(count, x) \ 349 - do { \ 350 - USItype __tmp; \ 351 - __asm__ ( \ 352 - "ldi 1,%0\n" \ 353 - "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ 354 - "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ 355 - "ldo 16(%0),%0 ; Yes. Perform add.\n" \ 356 - "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ 357 - "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ 358 - "ldo 8(%0),%0 ; Yes. Perform add.\n" \ 359 - "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ 360 - "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ 361 - "ldo 4(%0),%0 ; Yes. Perform add.\n" \ 362 - "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ 363 - "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ 364 - "ldo 2(%0),%0 ; Yes. Perform add.\n" \ 365 - "extru %1,30,1,%1 ; Extract bit 1.\n" \ 366 - "sub %0,%1,%0 ; Subtract it. " \ 367 - : "=r" (count), "=r" (__tmp) : "1" (x)); \ 368 - } while (0) 369 357 #endif /* hppa */ 370 358 371 359 /*************************************** ··· 427 457 : "0" ((USItype)(n0)), \ 428 458 "1" ((USItype)(n1)), \ 429 459 "rm" ((USItype)(d))) 430 - #define count_leading_zeros(count, x) \ 431 - do { \ 432 - USItype __cbtmp; \ 433 - __asm__ ("bsrl %1,%0" \ 434 - : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ 435 - (count) = __cbtmp ^ 31; \ 436 - } while (0) 437 - #define count_trailing_zeros(count, x) \ 438 - __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) 439 460 #ifndef UMUL_TIME 440 461 #define UMUL_TIME 40 441 462 #endif ··· 497 536 "dI" ((USItype)(d))); \ 498 537 (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ 499 538 } while (0) 500 - #define count_leading_zeros(count, x) \ 501 - do { \ 502 - USItype __cbtmp; \ 503 - __asm__ ("scanbit %1,%0" \ 504 - : "=r" (__cbtmp) \ 505 - : "r" ((USItype)(x))); \ 506 - (count) = __cbtmp ^ 31; \ 507 - } while (0) 508 - #define COUNT_LEADING_ZEROS_0 (-32) /* sic */ 509 539 #if defined(__i960mx) /* what is the proper symbol to test??? */ 510 540 #define rshift_rhlc(r, h, l, c) \ 511 541 do { \ ··· 555 603 : "0" ((USItype)(n0)), \ 556 604 "1" ((USItype)(n1)), \ 557 605 "dmi" ((USItype)(d))) 558 - #define count_leading_zeros(count, x) \ 559 - __asm__ ("bfffo %1{%b2:%b2},%0" \ 560 - : "=d" ((USItype)(count)) \ 561 - : "od" ((USItype)(x)), "n" (0)) 562 - #define COUNT_LEADING_ZEROS_0 32 563 606 #else /* not mc68020 */ 564 607 #define umul_ppmm(xh, xl, a, b) \ 565 608 do { USItype __umul_tmp1, __umul_tmp2; \ ··· 611 664 "rJ" ((USItype)(bh)), \ 612 665 "rJ" ((USItype)(al)), \ 613 666 "rJ" ((USItype)(bl))) 614 - #define count_leading_zeros(count, x) \ 615 - do { \ 616 - USItype __cbtmp; \ 617 - __asm__ ("ff1 %0,%1" \ 618 - : "=r" (__cbtmp) \ 619 - : "r" ((USItype)(x))); \ 620 - (count) = __cbtmp ^ 31; \ 621 - } while (0) 622 - #define COUNT_LEADING_ZEROS_0 63 /* sic */ 623 667 #if defined(__m88110__) 624 668 #define umul_ppmm(wh, wl, u, v) \ 625 669 do { \ ··· 717 779 : "0" (__xx.__ll), \ 718 780 "g" ((USItype)(d))); \ 719 781 (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) 720 - #define count_trailing_zeros(count, x) \ 721 - do { \ 722 - __asm__("ffsd %2,%0" \ 723 - : "=r"((USItype) (count)) \ 724 - : "0"((USItype) 0), "r"((USItype) (x))); \ 725 - } while (0) 726 782 #endif /* __ns32000__ */ 727 783 728 784 /*************************************** ··· 787 855 "rI" ((USItype)(al)), \ 788 856 "r" ((USItype)(bl))); \ 789 857 } while (0) 790 - #define count_leading_zeros(count, x) \ 791 - __asm__ ("{cntlz|cntlzw} %0,%1" \ 792 - : "=r" ((USItype)(count)) \ 793 - : "r" ((USItype)(x))) 794 - #define COUNT_LEADING_ZEROS_0 32 795 858 #if defined(_ARCH_PPC) 796 859 #define umul_ppmm(ph, pl, m0, m1) \ 797 860 do { \ ··· 928 1001 } while (0) 929 1002 #define UMUL_TIME 20 930 1003 #define UDIV_TIME 200 931 - #define count_leading_zeros(count, x) \ 932 - do { \ 933 - if ((x) >= 0x10000) \ 934 - __asm__ ("clz %0,%1" \ 935 - : "=r" ((USItype)(count)) \ 936 - : "r" ((USItype)(x) >> 16)); \ 937 - else { \ 938 - __asm__ ("clz %0,%1" \ 939 - : "=r" ((USItype)(count)) \ 940 - : "r" ((USItype)(x))); \ 941 - (count) += 16; \ 942 - } \ 943 - } while (0) 944 1004 #endif /* RT/ROMP */ 945 1005 946 1006 /*************************************** ··· 1056 1142 "rI" ((USItype)(d)) \ 1057 1143 : "%g1" __AND_CLOBBER_CC) 1058 1144 #define UDIV_TIME 37 1059 - #define count_leading_zeros(count, x) \ 1060 - __asm__ ("scan %1,0,%0" \ 1061 - : "=r" ((USItype)(x)) \ 1062 - : "r" ((USItype)(count))) 1063 - /* Early sparclites return 63 for an argument of 0, but they warn that future 1064 - implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 1065 - undefined. */ 1066 1145 #endif /* __sparclite__ */ 1067 1146 #endif /* __sparc_v8__ */ 1068 1147 /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ ··· 1359 1452 #if !defined(udiv_qrnnd) 1360 1453 #define UDIV_NEEDS_NORMALIZATION 1 1361 1454 #define udiv_qrnnd __udiv_qrnnd_c 1362 - #endif 1363 - 1364 - #undef count_leading_zeros 1365 - #if !defined(count_leading_zeros) 1366 - extern 1367 - #ifdef __STDC__ 1368 - const 1369 - #endif 1370 - unsigned char __clz_tab[]; 1371 - #define count_leading_zeros(count, x) \ 1372 - do { \ 1373 - UWtype __xr = (x); \ 1374 - UWtype __a; \ 1375 - \ 1376 - if (W_TYPE_SIZE <= 32) { \ 1377 - __a = __xr < ((UWtype) 1 << 2*__BITS4) \ 1378 - ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ 1379 - : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ 1380 - } \ 1381 - else { \ 1382 - for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ 1383 - if (((__xr >> __a) & 0xff) != 0) \ 1384 - break; \ 1385 - } \ 1386 - \ 1387 - (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ 1388 - } while (0) 1389 - /* This version gives a well-defined value for zero. */ 1390 - #define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE 1391 - #endif 1392 - 1393 - #if !defined(count_trailing_zeros) 1394 - /* Define count_trailing_zeros using count_leading_zeros. The latter might be 1395 - defined in asm, but if it is not, the C version above is good enough. */ 1396 - #define count_trailing_zeros(count, x) \ 1397 - do { \ 1398 - UWtype __ctz_x = (x); \ 1399 - UWtype __ctz_c; \ 1400 - count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ 1401 - (count) = W_TYPE_SIZE - 1 - __ctz_c; \ 1402 - } while (0) 1403 1455 #endif 1404 1456 1405 1457 #ifndef UDIV_NEEDS_NORMALIZATION
+1 -1
lib/mpi/mpi-bit.c
··· 45 45 if (a->nlimbs) { 46 46 mpi_limb_t alimb = a->d[a->nlimbs - 1]; 47 47 if (alimb) 48 - count_leading_zeros(n, alimb); 48 + n = count_leading_zeros(alimb); 49 49 else 50 50 n = BITS_PER_MPI_LIMB; 51 51 n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB;
+2 -2
lib/mpi/mpi-pow.c
··· 77 77 mp = mp_marker = mpi_alloc_limb_space(msize); 78 78 if (!mp) 79 79 goto enomem; 80 - count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); 80 + mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); 81 81 if (mod_shift_cnt) 82 82 mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); 83 83 else ··· 169 169 170 170 i = esize - 1; 171 171 e = ep[i]; 172 - count_leading_zeros(c, e); 172 + c = count_leading_zeros(e); 173 173 e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ 174 174 c = BITS_PER_MPI_LIMB - 1 - c; 175 175