1

Can anyone tell me what's the difference between __bswap_constant_XX and __bswap_XX also when to prefer one over another?

I am using GCC 4.8

Arun Pal
  • 687
  • 7
  • 28

1 Answers1

1

First of all, you should not normally use symbols with double underscores as those are reserved.

Symbols you are talking about are not compiler-defined, but a part of your C library. bswap_XX macros can use compiler intrinsic or even inline assembly to make compiler generate cpu-specific instructions, making the result unknown at compilation time.

In contrast, __bswap_constant_XX are supposed to evaluate the value using simple C expressions, making value compile-time constant if the input is a compile-time constant.

Such macros can be defined as:

#define __bswap_constant_16(x)                                  \
  ((__uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))

#define __bswap_constant_32(x)                                  \
  ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) |   \
   (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))

The idea is that you should use __bswap_constant_XX when you need compile-time value, for example when defining enum value:

enum myenum {
    MYVALUE = __bswap_constant_16(0x1234)
};

bswap_XX is supposed to be used in all other cases.

Note that modern compiler are able to recognize simple byte-swap patterns and generate appropriate instructions, so in practice this won't make a difference most of the time.

For example for both functions:

uint16_t bswap16(uint16_t x)
{
    return __bswap_constant_16(x);
}

uint32_t bswap32(uint32_t x)
{
    return __bswap_constant_32(x);
}

GCC 4.8.1 generates:

bswap16:
        mov     eax, edi
        rol     ax, 8
        ret
bswap32:
        mov     eax, edi
        bswap   eax
        ret