On Thu, Jul 19, 2012, at 12:02 PM, Greg Banks wrote: > Hmm. > > static void test_byteorder(void) > { > const char b64[8] = { 0, 0, 0, 0, 0, 0, 0, 1 }; > const char b32[4] = { 0, 0, 0, 1 }; > > char i64[8]; > char i32[4]; > > Here's your first problem, the alignment of all these variables is > uncontrolled. The code is only working by accident because the C > runtime environment gives you an aligned stack, and also because x86 > doesn't care so much about alignment.
Yeah, OK - I'll fix that first. that's pretty easy. > In the header file lib/byteorder64.h > > /* http://stackoverflow.com/a/4410728/94253 */ > > #if defined(__linux__) > # include <endian.h> > #elif defined(__FreeBSD__) || defined(__NetBSD__) > # include <sys/endian.h> > #elif defined(__OpenBSD__) > # include <sys/types.h> > # define be16toh(x) betoh16(x) > # define be32toh(x) betoh32(x) > # define be64toh(x) betoh64(x) > #elif defined(WORDS_BIGENDIAN) > #define CYRUS_BYTESWAP > #endif > > That could do with some improvement. Looks like stackoverflow might indeed be full of it. I guess we should really test for each of those in configure.in and then #define the right inline instruction. > Solaris also has an optimised ntohll() in libc which uses the 64b bswap > instruction, although it's not inlined. > > http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/amd64/gen/byteorder.s > > and gcc has a builtin which uses the instruction on platforms which have > it > > http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005fbswap64-3333 > > which presumably will work on some platforms where Linux's <endian.h> > (which re-implements the same thing differently) is not available. > > Disassembling cunit/byteorder64.o, I don't see any bswap instructions in > there, but nm shows undefined symbols for libc's htonl and ntohl. > Writing a function that calls ntohll() and nothing else, it seems that > ntohll() expands to a no-op. Running gcc -E confirms this. > > Aha.. > > #ifdef be64toh > #define htonll(x) htobe64(x) > #define ntohll(x) be64toh(x) > #elif defined (CYRUS_BYTESWAP) > /* little-endian 64-bit host/network byte-order swap functions */ > extern unsigned long long _htonll(unsigned long long); > extern unsigned long long _ntohll(unsigned long long); > #define htonll(x) _htonll(x) > #define ntohll(x) _ntohll(x) > #else > #define htonll(x) (x) > #define ntohll(x) (x) > #endif > > The <endian.h> on my desktop defines a be64toh(). The same header on > ci.cyrusimap.org doesn't. Yeah, damn. Is it really ancient, or 32 bit, or something? Bron.