gem5  v22.1.0.0
byteswap.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 //The purpose of this file is to provide endainness conversion utility
30 //functions. Depending on the endianness of the guest system, either
31 //the LittleEndianGuest or BigEndianGuest namespace is used.
32 
33 #ifndef __SIM_BYTE_SWAP_HH__
34 #define __SIM_BYTE_SWAP_HH__
35 
36 // This lets us figure out what the byte order of the host system is
37 #if defined(__linux__)
38 #include <endian.h>
39 // If this is a linux system, lets used the optimized definitions if they exist.
40 // If one doesn't exist, we pretty much get what is listed below, so it all
41 // works out
42 #include <byteswap.h>
43 #elif defined (__sun)
44 #include <sys/isa_defs.h>
45 #else
46 #include <machine/endian.h>
47 #endif
48 
49 #if defined(__APPLE__)
50 #include <libkern/OSByteOrder.h>
51 #endif
52 
53 #include <type_traits>
54 
55 #include "base/types.hh"
56 #include "enums/ByteOrder.hh"
57 
58 struct vring_used_elem;
59 struct vring_desc;
60 
61 namespace gem5
62 {
63 
64 // These functions actually perform the swapping for parameters of various bit
65 // lengths.
66 
67 inline uint64_t
68 swap_byte64(uint64_t x)
69 {
70 #if defined(__linux__)
71  return bswap_64(x);
72 #elif defined(__APPLE__)
73  return OSSwapInt64(x);
74 #else
75  return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
76  ((uint64_t)(x) & 0xff00ULL) << 40 |
77  ((uint64_t)(x) & 0xff0000ULL) << 24 |
78  ((uint64_t)(x) & 0xff000000ULL) << 8 |
79  ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
80  ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
81  ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
82  ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
83 #endif
84 }
85 
86 inline uint32_t
87 swap_byte32(uint32_t x)
88 {
89 #if defined(__linux__)
90  return bswap_32(x);
91 #elif defined(__APPLE__)
92  return OSSwapInt32(x);
93 #else
94  return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
95  ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
96  ((uint32_t)(x) & 0xff000000) >> 24);
97 #endif
98 }
99 
100 inline uint16_t
101 swap_byte16(uint16_t x)
102 {
103 #if defined(__linux__)
104  return bswap_16(x);
105 #elif defined(__APPLE__)
106  return OSSwapInt16(x);
107 #else
108  return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
109  ((uint16_t)(x) & 0xff00) >> 8);
110 #endif
111 }
112 
113 template <typename T>
114 inline std::enable_if_t<
115  sizeof(T) == 8 && std::is_convertible_v<T, uint64_t>, T>
117 {
118  return swap_byte64((uint64_t)x);
119 }
120 
121 template <typename T>
122 inline std::enable_if_t<
123  sizeof(T) == 4 && std::is_convertible_v<T, uint32_t>, T>
125 {
126  return swap_byte32((uint32_t)x);
127 }
128 
129 template <typename T>
130 inline std::enable_if_t<
131  sizeof(T) == 2 && std::is_convertible_v<T, uint16_t>, T>
133 {
134  return swap_byte16((uint16_t)x);
135 }
136 
137 template <typename T>
138 inline std::enable_if_t<
139  sizeof(T) == 1 && std::is_convertible_v<T, uint8_t>, T>
141 {
142  return x;
143 }
144 
145 // Make the function visible in case we need to declare a version of it for
146 // other types
147 template <typename T>
148 std::enable_if_t<std::is_same_v<T, vring_used_elem>, T>
149 swap_byte(T v);
150 template <typename T>
151 std::enable_if_t<std::is_same_v<T, vring_desc>, T>
152 swap_byte(T v);
153 
154 template <typename T, size_t N>
155 inline std::array<T, N>
156 swap_byte(std::array<T, N> a)
157 {
158  for (T &v: a)
159  v = swap_byte(v);
160  return a;
161 }
162 
163 //The conversion functions with fixed endianness on both ends don't need to
164 //be in a namespace
165 template <typename T> inline T betole(T value) {return swap_byte(value);}
166 template <typename T> inline T letobe(T value) {return swap_byte(value);}
167 
168 //For conversions not involving the guest system, we can define the functions
169 //conditionally based on the BYTE_ORDER macro and outside of the namespaces
170 #if (defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN)) && BYTE_ORDER == BIG_ENDIAN
171 const ByteOrder HostByteOrder = ByteOrder::big;
172 template <typename T> inline T htole(T value) {return swap_byte(value);}
173 template <typename T> inline T letoh(T value) {return swap_byte(value);}
174 template <typename T> inline T htobe(T value) {return value;}
175 template <typename T> inline T betoh(T value) {return value;}
176 #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
177 const ByteOrder HostByteOrder = ByteOrder::little;
178 template <typename T> inline T htole(T value) {return value;}
179 template <typename T> inline T letoh(T value) {return value;}
180 template <typename T> inline T htobe(T value) {return swap_byte(value);}
181 template <typename T> inline T betoh(T value) {return swap_byte(value);}
182 #else
183  #error Invalid Endianess
184 #endif
185 
186 template <typename T>
187 inline T htog(T value, ByteOrder guest_byte_order)
188 {
189  return guest_byte_order == ByteOrder::big ?
190  htobe(value) : htole(value);
191 }
192 
193 template <typename T>
194 inline T gtoh(T value, ByteOrder guest_byte_order)
195 {
196  return guest_byte_order == ByteOrder::big ?
197  betoh(value) : letoh(value);
198 }
199 
200 } // namespace gem5
201 
202 #endif // __SIM_BYTE_SWAP_HH__
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
Bitfield< 8 > a
Definition: misc_types.hh:66
Bitfield< 4 > x
Definition: pagetable.hh:61
Bitfield< 0 > v
Definition: pagetable.hh:65
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
T letoh(T value)
Definition: byteswap.hh:173
T betole(T value)
Definition: byteswap.hh:165
uint32_t swap_byte32(uint32_t x)
Definition: byteswap.hh:87
std::enable_if_t< std::is_same_v< T, vring_used_elem >, T > swap_byte(T v)
Definition: base.hh:76
T gtoh(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:194
T betoh(T value)
Definition: byteswap.hh:175
T htole(T value)
Definition: byteswap.hh:172
T htobe(T value)
Definition: byteswap.hh:174
const ByteOrder HostByteOrder
Definition: byteswap.hh:171
uint16_t swap_byte16(uint16_t x)
Definition: byteswap.hh:101
T htog(T value, ByteOrder guest_byte_order)
Definition: byteswap.hh:187
uint64_t swap_byte64(uint64_t x)
Definition: byteswap.hh:68
T letobe(T value)
Definition: byteswap.hh:166

Generated on Wed Dec 21 2022 10:22:39 for gem5 by doxygen 1.9.1