Home | Info | Research | Blog | Repos | Messages | Contact Me

 


'bitops.h'에 해당되는 글 1건

  1. 2008/09/07 리눅스 커널 비트 연산 함수 Visual C++ 버전

리눅스 커널의 include/asm-x86/bitops.h의 주요 함수를 Visual C++에서 컴파일 할 수 있도록 만들어 보았습니다.

#ifndef _I386_BITOPS_H
#define _I386_BITOPS_H

/*
 * Copyright 1992, Linus Torvalds.
 * Copyright 2008, Lee Jae-Hong (pyrasis)
 */


#include <linux/compiler.h>

#define inline __inline

/**
 * set_bit - Atomically set a bit in memory
 * @nr: the bit to set
 * @addr: the address to start counting from
 *
 * This function is atomic and may not be reordered.  See __set_bit()
 * if you do not require the atomic guarantees.
 *
 * Note: there are no guarantees that this function will not be reordered
 * on non x86 architectures, so if you are writting portable code,
 * make sure not to rely on its reordering guarantees.
 *
 * Note that @nr may be almost arbitrarily large; this function is not
 * restricted to acting on a single-word quantity.
 */

static inline void set_bit(int nr, volatile unsigned long * addr)
{
    __asm
    {
        mov eax, addr
        mov ecx, nr
        lock bts dword ptr [eax], ecx
    }
}

/**
 * clear_bit - Clears a bit in memory
 * @nr: Bit to clear
 * @addr: Address to start counting from
 *
 * clear_bit() is atomic and may not be reordered.  However, it does
 * not contain a memory barrier, so if it is used for locking purposes,
 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
 * in order to ensure changes are visible on other processors.
 */

static inline void clear_bit(int nr, volatile unsigned long * addr)
{
    __asm
    {
        mov eax, addr
        mov ecx, nr
        lock btr dword ptr [eax], ecx
    }
}

/**
 * change_bit - Toggle a bit in memory
 * @nr: Bit to change
 * @addr: Address to start counting from
 *
 * change_bit() is atomic and may not be reordered. It may be
 * reordered on other architectures than x86.
 * Note that @nr may be almost arbitrarily large; this function is not
 * restricted to acting on a single-word quantity.
 */

static inline void change_bit(int nr, volatile unsigned long * addr)
{
    __asm
    {
        mov eax, addr
        mov ecx, nr
        lock btc dword ptr [eax], ecx
    }
}

/**
 * test_and_set_bit - Set a bit and return its old value
 * @nr: Bit to set
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered. 
 * It may be reordered on other architectures than x86.
 * It also implies a memory barrier.
 */

static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
{
    int oldbit;

    __asm
    {
        mov edx, addr
        mov eax, nr
        lock bts dword ptr [edx], eax
        sbb eax, eax
        mov oldbit, eax
    }
    return oldbit;
}

/**
 * test_and_clear_bit - Clear a bit and return its old value
 * @nr: Bit to clear
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered.
 * It can be reorderdered on other architectures other than x86.
 * It also implies a memory barrier.
 */

static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
{
    int oldbit;

    __asm
    {
        mov edx, addr
        mov eax, nr
        lock btr dword ptr [edx], eax
        sbb eax, eax
        mov oldbit, eax
    }
    return oldbit;
}

/**
 * test_and_change_bit - Change a bit and return its old value
 * @nr: Bit to change
 * @addr: Address to count from
 *
 * This operation is atomic and cannot be reordered. 
 * It also implies a memory barrier.
 */

static inline int test_and_change_bit(int nr, volatile unsigned long* addr)
{
    int oldbit;

    __asm
    {
        mov edx, addr
        mov eax, nr
        lock btc dword ptr [edx], eax
        sbb eax, eax
        mov oldbit, eax
    }
    return oldbit;
}

/**
 * __ffs - find first bit in word.
 * @_word: The word to search
 *
 * Undefined if no bit exists, so code should check against 0 first.
 */

static inline unsigned long __ffs(unsigned long _word)
{
    __asm
    {
        bsf eax, [_word]
        mov _word, eax
    }
    return _word;
}

/**
 * find_first_bit - find the first set bit in a memory region
 * @addr: The address to start the search at
 * @size: The maximum size to search
 *
 * Returns the bit-number of the first set bit, not the number of the byte
 * containing a bit.
 */

static inline unsigned find_first_bit(const unsigned long *addr, unsigned size)
{
    unsigned x = 0;

    while (x < size) {
        unsigned long val = *addr++;
        if (val)
            return __ffs(val) + x;
        x += (sizeof(*addr)<<3);
    }
    return x;
}

/**
 * find_next_bit - find the first set bit in a memory region
 * @addr: The address to base the search on
 * @offset: The bitnumber to start searching at
 * @size: The maximum size to search
 */

int find_next_bit(const unsigned long *addr, int size, int offset);

/**
 * ffz - find first zero in word.
 * @word: The word to search
 *
 * Undefined if no zero exists, so code should check against ~0UL first.
 */

static inline unsigned long ffz(unsigned long word)
{
    int x = ~word;

    __asm
    {
        bsf eax, [x]
    }
}

/**
 * ffs - find first bit set
 * @x: the word to search
 *
 * This is defined the same way as
 * the libc and compiler builtin ffs routines, therefore
 * differs in spirit from the above ffz() (man ffs).
 */

static inline int ffs(int x)
{
    __asm
    {
        bsf eax, [x]
        jnz L1
        mov eax, -1
    L1:
        inc eax
    }
}

#endif /* _I386_BITOPS_H */