views:

406

answers:

3

I want to use the bts and bt x86 assembly instructions to speed up bit operations in my C++ code on the Mac. On Windows, the _bittestandset and _bittest intrinsics work well, and provide significant performance gains. On the Mac, the gcc compiler doesn't seem to support those, so I'm trying to do it directly in assembler instead.

Here's my C++ code (note that 'bit' can be >= 32):

typedef unsigned long LongWord;
#define DivLongWord(w) ((unsigned)w >> 5)
#define ModLongWord(w) ((unsigned)w & (32-1))

inline void SetBit(LongWord array[], const int bit)
{
   array[DivLongWord(bit)] |= 1 << ModLongWord(bit);
}

inline bool TestBit(const LongWord array[], const int bit)
{
    return (array[DivLongWord(bit)] & (1 << ModLongWord(bit))) != 0;
}

The following assembler code works, but is not optimal, as the compiler can't optimize register allocation:

inline void SetBit(LongWord* array, const int bit)
{
   __asm {
      mov   eax, bit
      mov   ecx, array
      bts   [ecx], eax
   }
}

Question: How do I get the compiler to fully optimize around the bts instruction? And how do I replace TestBit by a bt instruction?

+1  A: 

Not a direct answer, just a link to GCC Extended Asm documentation.

Nikolai N Fetissov
A: 

Another slightly indirect answer, GCC exposes a number of atomic operations starting with version 4.1.

D.Shawley
+1  A: 
inline void SetBit(*array, bit) {
    asm("bts %1,%0" : "+m" (*array) : "r" (bit));
}
ephemient
Perfect, thanks. That helped me figure out my second question:inline bool TestBit(const LongWord array[], const int bit){ bool flag; asm("bt %2,%1; setb %0" : "=q" (flag) : "m" (*array), "r" (bit)); return flag;}
smartgo