/*
- * Copyright (c) 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
static inline void put_unaligned_be32(ovs_be32 *, ovs_be32);
static inline void put_unaligned_be64(ovs_be64 *, ovs_be64);
+/* uint64_t get_unaligned_u64(uint64_t *p);
+ *
+ * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may
+ * actually be any type that points to a 64-bit integer. That is, on Unix-like
+ * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like
+ * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long
+ * long int".
+ *
+ * This is special-cased because on some Linux targets, the kernel __u64 is
+ * unsigned long long int and the userspace uint64_t is unsigned long int, so
+ * that any single function prototype would fail to accept one or the other.
+ *
+ * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since
+ * operands to % must be integers.
+ */
+#define get_unaligned_u64(P) \
+ (BUILD_ASSERT(sizeof *(P) == 8), \
+ BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \
+ (void) sizeof (*(P) % 1), \
+ get_unaligned_u64__((const uint64_t *) (P)))
+
#ifdef __GNUC__
/* GCC implementations. */
#define GCC_UNALIGNED_ACCESSORS(TYPE, ABBREV) \
* accessors. */
#define get_unaligned_be16 get_unaligned_u16
#define get_unaligned_be32 get_unaligned_u32
-#define get_unaligned_be64 get_unaligned_u64
#define put_unaligned_be16 put_unaligned_u16
#define put_unaligned_be32 put_unaligned_u32
#define put_unaligned_be64 put_unaligned_u64
-#endif
-/* uint64_t get_unaligned_u64(uint64_t *p);
- *
- * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may
- * actually be any type that points to a 64-bit integer. That is, on Unix-like
- * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like
- * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long
- * long int".
- *
- * This is special-cased because on some Linux targets, the kernel __u64 is
- * unsigned long long int and the userspace uint64_t is unsigned long int, so
- * that any single function prototype would fail to accept one or the other.
- *
- * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since
- * operands to % must be integers.
- */
-#define get_unaligned_u64(P) \
- (BUILD_ASSERT(sizeof *(P) == 8), \
- BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \
- (void) sizeof (*(P) % 1), \
- get_unaligned_u64__((const uint64_t *) (P)))
+/* We do not #define get_unaligned_be64 as for the other be<N> functions above,
+ * because such a definition would mean that get_unaligned_be64() would have a
+ * different interface in each branch of the #if: with GCC it would take a
+ * "ovs_be64 *", with other compilers any pointer-to-64-bit-type (but not void
+ * *). The latter means code like "get_unaligned_be64(ofpbuf_data(b))" would
+ * work with GCC but not with other compilers, which is surprising and
+ * undesirable. Hence this wrapper function. */
+static inline ovs_be64
+get_unaligned_be64(const ovs_be64 *p)
+{
+ return get_unaligned_u64(p);
+}
+#endif
/* Stores 'x' at possibly misaligned address 'p'.
*
put_unaligned_u64__(p, x);
}
\f
+/* Returns the value in 'x'. */
+static inline uint32_t
+get_16aligned_u32(const ovs_16aligned_u32 *x)
+{
+ return ((uint32_t) x->hi << 16) | x->lo;
+}
+
+/* Stores 'value' in 'x'. */
+static inline void
+put_16aligned_u32(ovs_16aligned_u32 *x, uint32_t value)
+{
+ x->hi = value >> 16;
+ x->lo = value;
+}
+
/* Returns the value in 'x'. */
static inline uint64_t
get_32aligned_u64(const ovs_32aligned_u64 *x)
}
#ifndef __CHECKER__
+/* Returns the value of 'x'. */
+static inline ovs_be32
+get_16aligned_be32(const ovs_16aligned_be32 *x)
+{
+#ifdef WORDS_BIGENDIAN
+ return ((ovs_be32) x->hi << 16) | x->lo;
+#else
+ return ((ovs_be32) x->lo << 16) | x->hi;
+#endif
+}
+
+/* Stores network byte order 'value' into 'x'. */
+static inline void
+put_16aligned_be32(ovs_16aligned_be32 *x, ovs_be32 value)
+{
+#if WORDS_BIGENDIAN
+ x->hi = value >> 16;
+ x->lo = value;
+#else
+ x->hi = value;
+ x->lo = value >> 16;
+#endif
+}
+
/* Returns the value of 'x'. */
static inline ovs_be64
get_32aligned_be64(const ovs_32aligned_be64 *x)
#else /* __CHECKER__ */
/* Making sparse happy with these functions also makes them unreadable, so
* don't bother to show it their implementations. */
+ovs_be32 get_16aligned_be32(const ovs_16aligned_be32 *);
+void put_16aligned_be32(ovs_16aligned_be32 *, ovs_be32);
ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *);
void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64);
#endif