linux/arch/arc/include/asm/bitops.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
   4 */
   5
   6#ifndef _ASM_BITOPS_H
   7#define _ASM_BITOPS_H
   8
   9#ifndef _LINUX_BITOPS_H
  10#error only <linux/bitops.h> can be included directly
  11#endif
  12
  13#ifndef __ASSEMBLY__
  14
  15#include <linux/types.h>
  16#include <linux/compiler.h>
  17
  18#ifdef CONFIG_ISA_ARCOMPACT
  19
  20/*
  21 * Count the number of zeros, starting from MSB
  22 * Helper for fls( ) friends
  23 * This is a pure count, so (1-32) or (0-31) doesn't apply
  24 * It could be 0 to 32, based on num of 0's in there
  25 * clz(0x8000_0000) = 0, clz(0xFFFF_FFFF)=0, clz(0) = 32, clz(1) = 31
  26 */
  27static inline __attribute__ ((const)) int clz(unsigned int x)
  28{
  29        unsigned int res;
  30
  31        __asm__ __volatile__(
  32        "       norm.f  %0, %1          \n"
  33        "       mov.n   %0, 0           \n"
  34        "       add.p   %0, %0, 1       \n"
  35        : "=r"(res)
  36        : "r"(x)
  37        : "cc");
  38
  39        return res;
  40}
  41
  42static inline int constant_fls(unsigned int x)
  43{
  44        int r = 32;
  45
  46        if (!x)
  47                return 0;
  48        if (!(x & 0xffff0000u)) {
  49                x <<= 16;
  50                r -= 16;
  51        }
  52        if (!(x & 0xff000000u)) {
  53                x <<= 8;
  54                r -= 8;
  55        }
  56        if (!(x & 0xf0000000u)) {
  57                x <<= 4;
  58                r -= 4;
  59        }
  60        if (!(x & 0xc0000000u)) {
  61                x <<= 2;
  62                r -= 2;
  63        }
  64        if (!(x & 0x80000000u))
  65                r -= 1;
  66        return r;
  67}
  68
  69/*
  70 * fls = Find Last Set in word
  71 * @result: [1-32]
  72 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
  73 */
  74static inline __attribute__ ((const)) int fls(unsigned int x)
  75{
  76        if (__builtin_constant_p(x))
  77               return constant_fls(x);
  78
  79        return 32 - clz(x);
  80}
  81
  82/*
  83 * __fls: Similar to fls, but zero based (0-31)
  84 */
  85static inline __attribute__ ((const)) int __fls(unsigned long x)
  86{
  87        if (!x)
  88                return 0;
  89        else
  90                return fls(x) - 1;
  91}
  92
  93/*
  94 * ffs = Find First Set in word (LSB to MSB)
  95 * @result: [1-32], 0 if all 0's
  96 */
  97#define ffs(x)  ({ unsigned long __t = (x); fls(__t & -__t); })
  98
  99/*
 100 * __ffs: Similar to ffs, but zero based (0-31)
 101 */
 102static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
 103{
 104        if (!word)
 105                return word;
 106
 107        return ffs(word) - 1;
 108}
 109
 110#else   /* CONFIG_ISA_ARCV2 */
 111
 112/*
 113 * fls = Find Last Set in word
 114 * @result: [1-32]
 115 * fls(1) = 1, fls(0x80000000) = 32, fls(0) = 0
 116 */
 117static inline __attribute__ ((const)) int fls(unsigned int x)
 118{
 119        int n;
 120
 121        asm volatile(
 122        "       fls.f   %0, %1          \n"  /* 0:31; 0(Z) if src 0 */
 123        "       add.nz  %0, %0, 1       \n"  /* 0:31 -> 1:32 */
 124        : "=r"(n)       /* Early clobber not needed */
 125        : "r"(x)
 126        : "cc");
 127
 128        return n;
 129}
 130
 131/*
 132 * __fls: Similar to fls, but zero based (0-31). Also 0 if no bit set
 133 */
 134static inline __attribute__ ((const)) int __fls(unsigned long x)
 135{
 136        /* FLS insn has exactly same semantics as the API */
 137        return  __builtin_arc_fls(x);
 138}
 139
 140/*
 141 * ffs = Find First Set in word (LSB to MSB)
 142 * @result: [1-32], 0 if all 0's
 143 */
 144static inline __attribute__ ((const)) int ffs(unsigned int x)
 145{
 146        int n;
 147
 148        asm volatile(
 149        "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
 150        "       add.nz  %0, %0, 1       \n"  /* 0:31 -> 1:32 */
 151        "       mov.z   %0, 0           \n"  /* 31(Z)-> 0 */
 152        : "=r"(n)       /* Early clobber not needed */
 153        : "r"(x)
 154        : "cc");
 155
 156        return n;
 157}
 158
 159/*
 160 * __ffs: Similar to ffs, but zero based (0-31)
 161 */
 162static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
 163{
 164        unsigned long n;
 165
 166        asm volatile(
 167        "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
 168        "       mov.z   %0, 0           \n"  /* 31(Z)-> 0 */
 169        : "=r"(n)
 170        : "r"(x)
 171        : "cc");
 172
 173        return n;
 174
 175}
 176
 177#endif  /* CONFIG_ISA_ARCOMPACT */
 178
 179/*
 180 * ffz = Find First Zero in word.
 181 * @return:[0-31], 32 if all 1's
 182 */
 183#define ffz(x)  __ffs(~(x))
 184
 185#include <asm-generic/bitops/hweight.h>
 186#include <asm-generic/bitops/fls64.h>
 187#include <asm-generic/bitops/sched.h>
 188#include <asm-generic/bitops/lock.h>
 189#include <asm-generic/bitops/atomic.h>
 190#include <asm-generic/bitops/non-atomic.h>
 191
 192#include <asm-generic/bitops/find.h>
 193#include <asm-generic/bitops/le.h>
 194#include <asm-generic/bitops/ext2-atomic-setbit.h>
 195
 196#endif /* !__ASSEMBLY__ */
 197
 198#endif
 199