Catalli's threaded switch
[sliver-openvswitch.git] / lib / unaligned.h
1 /*
2  * Copyright (c) 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef UNALIGNED_H
18 #define UNALIGNED_H 1
19
20 #include <stdint.h>
21 #include "xtoxll.h"
22
23 /* Public API. */
24 static inline uint16_t get_unaligned_u16(const uint16_t *);
25 static inline uint32_t get_unaligned_u32(const uint32_t *);
26 static inline uint64_t get_unaligned_u64(const uint64_t *);
27 static inline void put_unaligned_u16(uint16_t *, uint16_t);
28 static inline void put_unaligned_u32(uint32_t *, uint32_t);
29 static inline void put_unaligned_u64(uint64_t *, uint64_t);
30
31 #ifdef __GNUC__
32 /* GCC implementations. */
33 #define GCC_UNALIGNED_ACCESSORS(SIZE)                       \
34 struct unaligned_u##SIZE {                                  \
35     uint##SIZE##_t x __attribute__((__packed__));           \
36 };                                                          \
37 static inline struct unaligned_u##SIZE *                    \
38 unaligned_u##SIZE(const uint##SIZE##_t *p)                  \
39 {                                                           \
40     return (struct unaligned_u##SIZE *) p;                  \
41 }                                                           \
42                                                             \
43 static inline uint##SIZE##_t                                \
44 get_unaligned_u##SIZE(const uint##SIZE##_t *p)              \
45 {                                                           \
46     return unaligned_u##SIZE(p)->x;                         \
47 }                                                           \
48                                                             \
49 static inline void                                          \
50 put_unaligned_u##SIZE(uint##SIZE##_t *p, uint##SIZE##_t x)  \
51 {                                                           \
52     unaligned_u##SIZE(p)->x = x;                            \
53 }
54
55 GCC_UNALIGNED_ACCESSORS(16);
56 GCC_UNALIGNED_ACCESSORS(32);
57 GCC_UNALIGNED_ACCESSORS(64);
58 #else
59 /* Generic implementations. */
60
61 static inline uint16_t get_unaligned_u16(const uint16_t *p_)
62 {
63     const uint8_t *p = (const uint8_t *) p_;
64     return ntohs((p[0] << 8) | p[1]);
65 }
66
67 static inline void put_unaligned_u16(uint16_t *p_, uint16_t x_)
68 {
69     uint8_t *p = (uint8_t *) p_;
70     uint16_t x = ntohs(x_);
71
72     p[0] = x >> 8;
73     p[1] = x;
74 }
75
76 static inline uint32_t get_unaligned_u32(const uint32_t *p_)
77 {
78     const uint8_t *p = (const uint8_t *) p_;
79     return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
80 }
81
82 static inline void put_unaligned_u32(uint32_t *p_, uint32_t x_)
83 {
84     uint8_t *p = (uint8_t *) p_;
85     uint32_t x = ntohl(x_);
86
87     p[0] = x >> 24;
88     p[1] = x >> 16;
89     p[2] = x >> 8;
90     p[3] = x;
91 }
92
93 static inline uint64_t get_unaligned_u64(const uint64_t *p_)
94 {
95     const uint8_t *p = (const uint8_t *) p_;
96     return ntohll(((uint64_t) p[0] << 56)
97                   | ((uint64_t) p[1] << 48)
98                   | ((uint64_t) p[2] << 40)
99                   | ((uint64_t) p[3] << 32)
100                   | (p[4] << 24)
101                   | (p[5] << 16)
102                   | (p[6] << 8)
103                   | p[7]);
104 }
105
106 static inline void put_unaligned_u64(uint64_t *p_, uint64_t x_)
107 {
108     uint8_t *p = (uint8_t *) p_;
109     uint64_t x = ntohll(x_);
110
111     p[0] = x >> 56;
112     p[1] = x >> 48;
113     p[2] = x >> 40;
114     p[3] = x >> 32;
115     p[4] = x >> 24;
116     p[5] = x >> 16;
117     p[6] = x >> 8;
118     p[7] = x;
119 }
120 #endif
121
122 #endif /* unaligned.h */