Linux "yin"才们的奇"yin"小技巧 --请用东北发音夸他们

1. include/linux/bits.h GENMASK(h, l)linux

/*
 * Create a contiguous bitmask starting at bit position @l and ending at
 * position @h. For example
 * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
 */
#define GENMASK(h, l) \
	(((~UL(0)) - (UL(1) << (l)) + 1) & \            ||1
	 (~UL(0) >> (BITS_PER_LONG - 1 - (h))))   ||2

Exp. (6,4) of 0x1111 1111
1-->0x1111 1111 - (0x1<<4) = 0x1110 1111  + 1 = 0x1111 0000
2-->0x1111 1111 >> (8-1-6) = 0x0111 1111
1&2 = 0x0111 0000

 

2. include/linux/bitfield.h   oop

/*
 * Bitfield access macros
 *
 * FIELD_{GET,PREP} macros take as first parameter shifted mask
 * from which they extract the base mask and shift amount.
 * Mask must be a compilation time constant.
 *
 * Example:
 *
 *  #define REG_FIELD_A  GENMASK(6, 0)
 *  #define REG_FIELD_B  BIT(7)
 *  #define REG_FIELD_C  GENMASK(15, 8)
 *  #define REG_FIELD_D  GENMASK(31, 16)
 *
 * Get:
 *  a = FIELD_GET(REG_FIELD_A, reg);
 *  b = FIELD_GET(REG_FIELD_B, reg);
 *
 * Set:
 *  reg = FIELD_PREP(REG_FIELD_A, 1) |
 *	  FIELD_PREP(REG_FIELD_B, 0) |
 *	  FIELD_PREP(REG_FIELD_C, c) |
 *	  FIELD_PREP(REG_FIELD_D, 0x40);
 *
 * Modify:
 *  reg &= ~REG_FIELD_C;
 *  reg |= FIELD_PREP(REG_FIELD_C, c);
 */

#define __bf_shf(x) (__builtin_ffsll(x) - 1)

3. 测试

#include <stdio.h>
#define UL (unsigned long)
#define GENMASK(h, l, H, L)     \
        ({typeof(h) H = (h);    \
        typeof(l) L = (l);      \
        (((~UL(0)) >>(L)<< (L)) & \
        (~UL(0) >> (64 - 1 - (H))));})

#define GENMASK_OLD(h, l)     \
        (((~UL(0)) >>(l)<< (l)) & \
        (~UL(0) >> (64 - 1 - (h))))

void main(){
        int i = 6, j = 4;
        printf("output:%lx\n", GENMASK_OLD(6,4));
        printf("output:%lx\n", GENMASK_OLD(i++,j++));
        printf("output:%lx\n", GENMASK(i++,j++, H, L));
}

4. 完整测试代码,运行效率比原生态高,并且易读懂ui

#include <stdio.h>
#define UL (unsigned long)
#define BITS_PER_LONG sizeof(unsigned long)

#define GENMASK_NEW(h, l, H, L)     \
        ({typeof(h) H = (h);    \
        typeof(l) L = (l);      \
        (((~UL(0)) >>(L)<< (L)) & \
        (~UL(0) >> (64 - 1 - (H))));})

#define GENMASK(h, l) \
    (((~UL(0)) - (UL(1) << (l)) + 1) & \
     (~UL(0) >> (64 - 1 - (h))))

#define GENMASK_YIN(h, l) \
    (((~UL(0))>>(64-1-(h))) & \
     (~UL(0))>>(l)<<(l))

void main(){
        unsigned long loop1 = 1000;
        unsigned long loop2 = 10000000;
        int i = 6, j=4;
#if 0
        printf("output:%lx\n", GENMASK_NEW(i++,j++, H, L));
        i = 6; j = 4;
        printf("output:%lx\n", GENMASK_NEW(++i,++j, H, L));
        //org:
        i = 6; j = 4;
        printf("output:%lx\n", GENMASK(i++,j++));
        i = 6; j = 4;
        printf("output:%lx\n", GENMASK(++i,++j));
        return;
#endif
        //printf("GENMASK(i+1, j+1):%lx\n", GENMASK(i+1, j+1));
        printf("GENMASK_NEW(i+1, j+1):%lx\n", GENMASK_NEW(i+1, j+1,H,L));

        while(loop1--){
                loop2 = 10000000;
                while(loop2--){
                        //printf("%lx\n", GENMASK(6, 4));
                        //GENMASK(i+1, j+1);
                        //GENMASK_YIN(i, j);
                        GENMASK_NEW(i,j, H, L);
                }
        }
        //printf("hello%ld, BITS_PER_LONG:%ld\n", sizeof UL, BITS_PER_LONG);
}

  

  

https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/barrier.h#L130  spa

相关文章
相关标签/搜索