aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-09-08 09:37:50 -0700
committerGarrett D'Amore <garrett@damore.org>2024-10-05 17:49:45 -0700
commitf1cb2402734567b84e2b55129f98f9764167e13e (patch)
treed65f9b676ec8e4f17ba7f0b5f5d952364e462a20
parent94c88335f9de5090846504dfa5fc1656092efacf (diff)
downloadnng-f1cb2402734567b84e2b55129f98f9764167e13e.tar.gz
nng-f1cb2402734567b84e2b55129f98f9764167e13e.tar.bz2
nng-f1cb2402734567b84e2b55129f98f9764167e13e.zip
Endianness improvements.
This adds endian awareness at compile time, and defines some little endian versions of some macros. We antiicpate making more use of little endian in new protocols to reduce the "endian tax", as nearly every modern system is little endian these days.
-rw-r--r--CMakeLists.txt18
-rw-r--r--src/core/defs.h63
2 files changed, 81 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1dca028c..f859a7d0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -207,6 +207,24 @@ if (NOT WIN32 AND NOT CYGWIN)
endif ()
endif ()
+# Detect endianness -- this only handles little and big endian.
+# PDP users, sorry, but you're out of luck.'
+if (DEFINED CMAKE_LANG_C_BYTE_ORDER)
+ if (CMAKE_LANG_BYTE_ORDER EQUAL BIG_ENDIAN)
+ add_definitions(-DNNG_BIG_ENDIAN=1)
+ else()
+ add_definitions(-DNNG_LITTLE_ENDIAN=1)
+ endif()
+else()
+ include(TestBigEndian)
+ test_big_endian(NNG_BIG_ENDIAN)
+ if (NNG_BIG_ENDIAN)
+ add_definitions(-DNNG_BIG_EDNDIAN=1)
+ else()
+ add_definitions(-DNNG_LITTLE_ENDIAN=1)
+ endif()
+endif()
+
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
add_definitions(-DNNG_PLATFORM_POSIX)
add_definitions(-DNNG_PLATFORM_LINUX)
diff --git a/src/core/defs.h b/src/core/defs.h
index f1947fe9..6050782b 100644
--- a/src/core/defs.h
+++ b/src/core/defs.h
@@ -121,6 +121,54 @@ typedef void (*nni_cb)(void *);
(((uint64_t) ((uint8_t) (ptr)[6])) << 8u) + \
(((uint64_t) (uint8_t) (ptr)[7]))
+// Modern CPUs are all little endian. Let's stop paying the endian tax.
+
+#define NNI_PUT16LE(ptr, u) \
+ do { \
+ (ptr)[1] = (uint8_t) (((uint16_t) (u)) >> 8u); \
+ (ptr)[0] = (uint8_t) ((uint16_t) (u)); \
+ } while (0)
+
+#define NNI_PUT32LE(ptr, u) \
+ do { \
+ (ptr)[3] = (uint8_t) (((uint32_t) (u)) >> 24u); \
+ (ptr)[2] = (uint8_t) (((uint32_t) (u)) >> 16u); \
+ (ptr)[1] = (uint8_t) (((uint32_t) (u)) >> 8u); \
+ (ptr)[0] = (uint8_t) ((uint32_t) (u)); \
+ } while (0)
+
+#define NNI_PUT64LE(ptr, u) \
+ do { \
+ (ptr)[7] = (uint8_t) (((uint64_t) (u)) >> 56u); \
+ (ptr)[6] = (uint8_t) (((uint64_t) (u)) >> 48u); \
+ (ptr)[5] = (uint8_t) (((uint64_t) (u)) >> 40u); \
+ (ptr)[4] = (uint8_t) (((uint64_t) (u)) >> 32u); \
+ (ptr)[3] = (uint8_t) (((uint64_t) (u)) >> 24u); \
+ (ptr)[2] = (uint8_t) (((uint64_t) (u)) >> 16u); \
+ (ptr)[1] = (uint8_t) (((uint64_t) (u)) >> 8u); \
+ (ptr)[0] = (uint8_t) ((uint64_t) (u)); \
+ } while (0)
+
+#define NNI_GET16LE(ptr, v) \
+ v = (((uint16_t) ((uint8_t) (ptr)[1])) << 8u) + \
+ (((uint16_t) (uint8_t) (ptr)[0]))
+
+#define NNI_GET32LE(ptr, v) \
+ v = (((uint32_t) ((uint8_t) (ptr)[3])) << 24u) + \
+ (((uint32_t) ((uint8_t) (ptr)[2])) << 16u) + \
+ (((uint32_t) ((uint8_t) (ptr)[1])) << 8u) + \
+ (((uint32_t) (uint8_t) (ptr)[0]))
+
+#define NNI_GET64LE(ptr, v) \
+ v = (((uint64_t) ((uint8_t) (ptr)[7])) << 56u) + \
+ (((uint64_t) ((uint8_t) (ptr)[6])) << 48u) + \
+ (((uint64_t) ((uint8_t) (ptr)[5])) << 40u) + \
+ (((uint64_t) ((uint8_t) (ptr)[4])) << 32u) + \
+ (((uint64_t) ((uint8_t) (ptr)[3])) << 24u) + \
+ (((uint64_t) ((uint8_t) (ptr)[2])) << 16u) + \
+ (((uint64_t) ((uint8_t) (ptr)[1])) << 8u) + \
+ (((uint64_t) (uint8_t) (ptr)[0]))
+
// This increments a pointer a fixed number of byte cells.
#define NNI_INCPTR(ptr, n) ((ptr) = (void *) ((char *) (ptr) + (n)))
@@ -178,4 +226,19 @@ typedef nni_type nni_opt_type;
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
+#if !defined(NNG_BIG_ENDIAN) && !defined(NNG_LITTLE_ENDIAN)
+#if defined(__BYTE_ORDER__)
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define NNG_BIG_ENDIAN 1
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define NNG_LITTLE_ENDIAN 1
+#else // middle-endian? (aka PDP-11)
+#error "Unsupported or unknown endian"
+#endif // __BYTE_ORDER__
+#else // defined(__BYTE_ORDER__)
+#define NNG_LITTLE_ENDIAN 1
+#error "Unknown endian: specify -DNNG_BIG_ENDIAN=1 or -DNNG_LITTLE_ENDIAN=1"
+#endif // defined(__BYTE_ORDER)
+#endif // defined() endianness
+
#endif // CORE_DEFS_H