zoukankan      html  css  js  c++  java
  • linux内核中的宏ffs(x)

    linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在

    arch/arm/include/asm/bitops.h

    #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
    static inline int fls(int x)
    {
        int ret;
    
        if (__builtin_constant_p(x))
               return constant_fls(x);
    
        asm("clz	%0, %1" : "=r" (ret) : "r" (x) : "cc");
               ret = 32 - ret;
        return ret;
    }

    __t & -__t   等于找到__t 第一个为1的位(从低位开始),并把该位保留为1其余位清0. 

    例如 一32位整形数 6,用二进制表示它的低8位:00000110,  都知道负数为最高为1其余位取反加1.-6即 11111010

    相与得 00000010,即6&-6. 把该值传递给函数fls().

    再看fls函数.

    if (__builtin_constant_p(x))
              
    return constant_fls(x);

    __builtin_constant_p 是Gcc的内建函数 ,用于判断一个值是否为编译时常数,如果参数的值是常数,函数返回 1,否则返回 0。

    如果是常数就用下面函数计算00000010中1的位置

    static inline int constant_fls(int x)
    {
        int r = 32;
    
        if (!x)
            return 0;
        if (!(x & 0xffff0000u)) {
            x <<= 16;
            r -= 16;
        }
        if (!(x & 0xff000000u)) {
            x <<= 8;
            r -= 8;
        }
        if (!(x & 0xf0000000u)) {
            x <<= 4;
            r -= 4;
        }
        if (!(x & 0xc0000000u)) {
            x <<= 2;
            r -= 2;
        }
        if (!(x & 0x80000000u)) {
            x <<= 1;
            r -= 1;
        }
        return r;
    }

    算法就是折半法,这个函数计算的是从高位起第一个1位的位置.00000010, r=2.  由于__t&-__t只有一个1,所以就是找到该1的位置.

    如果输入参数是00001010 那么 r=4.

    如果参数是变量,直接使用arm指令运算.

    执行   asm("clz %0, %1" : "=r" (ret) : "r" (x) : "cc");
               ret
    = 32 - ret;
    CLZ(Count Leading Zeros)指令对Rm中值的高位(leading zeros)个数进行计数,结果放到Rd中。若源寄存器全为0,则结果为32。若[31]为1,则结果为0。

    clz指令计算高位0的个数, 然后拿32-ret 算出1的位置.

    所以,ffs(x)这个宏的值就是x的第一个1的位置(从低位开始,数值从1开始,0代表x全0).

    另外,该文件中还有很多linux关于位操作的函数,可以作为自己写应用程序时的有用参考.

  • 相关阅读:
    2019-05-11 java学习日记
    2019-05-14 Java学习日记 day4
    2019-05-13 Java学习日记 day3
    2019-05-12 Java学习日记day2
    2019-05-11 java学习日记day1
    数据库的比较
    函数调用
    求平均数,排列顺序为降序
    遍历三维数组
    由大到小排列
  • 原文地址:https://www.cnblogs.com/fengeryi/p/3449720.html
Copyright © 2011-2022 走看看