1*94c4a1e1SFrank Piva // SPDX-License-Identifier: GPL-2.0
2*94c4a1e1SFrank Piva #ifndef UBLK_TGT_ENDIAN_H
3*94c4a1e1SFrank Piva #define UBLK_TGT_ENDIAN_H
4*94c4a1e1SFrank Piva
5*94c4a1e1SFrank Piva #include <byteswap.h>
6*94c4a1e1SFrank Piva
7*94c4a1e1SFrank Piva /* ublksrv target code private header, not for libublksrv user */
8*94c4a1e1SFrank Piva
bswap16(uint16_t x)9*94c4a1e1SFrank Piva static inline uint16_t bswap16(uint16_t x)
10*94c4a1e1SFrank Piva {
11*94c4a1e1SFrank Piva return bswap_16(x);
12*94c4a1e1SFrank Piva }
bswap32(uint32_t x)13*94c4a1e1SFrank Piva static inline uint32_t bswap32(uint32_t x)
14*94c4a1e1SFrank Piva {
15*94c4a1e1SFrank Piva return bswap_32(x);
16*94c4a1e1SFrank Piva }
bswap64(uint64_t x)17*94c4a1e1SFrank Piva static inline uint64_t bswap64(uint64_t x)
18*94c4a1e1SFrank Piva {
19*94c4a1e1SFrank Piva return bswap_64(x);
20*94c4a1e1SFrank Piva }
21*94c4a1e1SFrank Piva
bswap16s(uint16_t * s)22*94c4a1e1SFrank Piva static inline void bswap16s(uint16_t *s)
23*94c4a1e1SFrank Piva {
24*94c4a1e1SFrank Piva *s = bswap16(*s);
25*94c4a1e1SFrank Piva }
26*94c4a1e1SFrank Piva
bswap32s(uint32_t * s)27*94c4a1e1SFrank Piva static inline void bswap32s(uint32_t *s)
28*94c4a1e1SFrank Piva {
29*94c4a1e1SFrank Piva *s = bswap32(*s);
30*94c4a1e1SFrank Piva }
31*94c4a1e1SFrank Piva
bswap64s(uint64_t * s)32*94c4a1e1SFrank Piva static inline void bswap64s(uint64_t *s)
33*94c4a1e1SFrank Piva {
34*94c4a1e1SFrank Piva *s = bswap64(*s);
35*94c4a1e1SFrank Piva }
36*94c4a1e1SFrank Piva
37*94c4a1e1SFrank Piva #ifndef glue
38*94c4a1e1SFrank Piva #define xglue(x, y) x ## y
39*94c4a1e1SFrank Piva #define glue(x, y) xglue(x, y)
40*94c4a1e1SFrank Piva #endif
41*94c4a1e1SFrank Piva
42*94c4a1e1SFrank Piva #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
43*94c4a1e1SFrank Piva #define be_bswap(v, size) (v)
44*94c4a1e1SFrank Piva #define le_bswap(v, size) glue(bswap, size)(v)
45*94c4a1e1SFrank Piva #define be_bswaps(v, size)
46*94c4a1e1SFrank Piva #define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
47*94c4a1e1SFrank Piva #else
48*94c4a1e1SFrank Piva #define le_bswap(v, size) (v)
49*94c4a1e1SFrank Piva #define be_bswap(v, size) glue(bswap, size)(v)
50*94c4a1e1SFrank Piva #define le_bswaps(v, size)
51*94c4a1e1SFrank Piva #define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
52*94c4a1e1SFrank Piva #endif
53*94c4a1e1SFrank Piva
54*94c4a1e1SFrank Piva /**
55*94c4a1e1SFrank Piva * Endianness conversion functions between host cpu and specified endianness.
56*94c4a1e1SFrank Piva * (We list the complete set of prototypes produced by the macros below
57*94c4a1e1SFrank Piva * to assist people who search the headers to find their definitions.)
58*94c4a1e1SFrank Piva *
59*94c4a1e1SFrank Piva * uint16_t le16_to_cpu(uint16_t v);
60*94c4a1e1SFrank Piva * uint32_t le32_to_cpu(uint32_t v);
61*94c4a1e1SFrank Piva * uint64_t le64_to_cpu(uint64_t v);
62*94c4a1e1SFrank Piva * uint16_t be16_to_cpu(uint16_t v);
63*94c4a1e1SFrank Piva * uint32_t be32_to_cpu(uint32_t v);
64*94c4a1e1SFrank Piva * uint64_t be64_to_cpu(uint64_t v);
65*94c4a1e1SFrank Piva *
66*94c4a1e1SFrank Piva * Convert the value @v from the specified format to the native
67*94c4a1e1SFrank Piva * endianness of the host CPU by byteswapping if necessary, and
68*94c4a1e1SFrank Piva * return the converted value.
69*94c4a1e1SFrank Piva *
70*94c4a1e1SFrank Piva * uint16_t cpu_to_le16(uint16_t v);
71*94c4a1e1SFrank Piva * uint32_t cpu_to_le32(uint32_t v);
72*94c4a1e1SFrank Piva * uint64_t cpu_to_le64(uint64_t v);
73*94c4a1e1SFrank Piva * uint16_t cpu_to_be16(uint16_t v);
74*94c4a1e1SFrank Piva * uint32_t cpu_to_be32(uint32_t v);
75*94c4a1e1SFrank Piva * uint64_t cpu_to_be64(uint64_t v);
76*94c4a1e1SFrank Piva *
77*94c4a1e1SFrank Piva * Convert the value @v from the native endianness of the host CPU to
78*94c4a1e1SFrank Piva * the specified format by byteswapping if necessary, and return
79*94c4a1e1SFrank Piva * the converted value.
80*94c4a1e1SFrank Piva *
81*94c4a1e1SFrank Piva * void le16_to_cpus(uint16_t *v);
82*94c4a1e1SFrank Piva * void le32_to_cpus(uint32_t *v);
83*94c4a1e1SFrank Piva * void le64_to_cpus(uint64_t *v);
84*94c4a1e1SFrank Piva * void be16_to_cpus(uint16_t *v);
85*94c4a1e1SFrank Piva * void be32_to_cpus(uint32_t *v);
86*94c4a1e1SFrank Piva * void be64_to_cpus(uint64_t *v);
87*94c4a1e1SFrank Piva *
88*94c4a1e1SFrank Piva * Do an in-place conversion of the value pointed to by @v from the
89*94c4a1e1SFrank Piva * specified format to the native endianness of the host CPU.
90*94c4a1e1SFrank Piva *
91*94c4a1e1SFrank Piva * void cpu_to_le16s(uint16_t *v);
92*94c4a1e1SFrank Piva * void cpu_to_le32s(uint32_t *v);
93*94c4a1e1SFrank Piva * void cpu_to_le64s(uint64_t *v);
94*94c4a1e1SFrank Piva * void cpu_to_be16s(uint16_t *v);
95*94c4a1e1SFrank Piva * void cpu_to_be32s(uint32_t *v);
96*94c4a1e1SFrank Piva * void cpu_to_be64s(uint64_t *v);
97*94c4a1e1SFrank Piva *
98*94c4a1e1SFrank Piva * Do an in-place conversion of the value pointed to by @v from the
99*94c4a1e1SFrank Piva * native endianness of the host CPU to the specified format.
100*94c4a1e1SFrank Piva *
101*94c4a1e1SFrank Piva * Both X_to_cpu() and cpu_to_X() perform the same operation; you
102*94c4a1e1SFrank Piva * should use whichever one is better documenting of the function your
103*94c4a1e1SFrank Piva * code is performing.
104*94c4a1e1SFrank Piva *
105*94c4a1e1SFrank Piva * Do not use these functions for conversion of values which are in guest
106*94c4a1e1SFrank Piva * memory, since the data may not be sufficiently aligned for the host CPU's
107*94c4a1e1SFrank Piva * load and store instructions. Instead you should use the ld*_p() and
108*94c4a1e1SFrank Piva * st*_p() functions, which perform loads and stores of data of any
109*94c4a1e1SFrank Piva * required size and endianness and handle possible misalignment.
110*94c4a1e1SFrank Piva */
111*94c4a1e1SFrank Piva
112*94c4a1e1SFrank Piva #define CPU_CONVERT(endian, size, type)\
113*94c4a1e1SFrank Piva static inline type endian ## size ## _to_cpu(type v)\
114*94c4a1e1SFrank Piva {\
115*94c4a1e1SFrank Piva return glue(endian, _bswap)(v, size);\
116*94c4a1e1SFrank Piva }\
117*94c4a1e1SFrank Piva \
118*94c4a1e1SFrank Piva static inline type cpu_to_ ## endian ## size(type v)\
119*94c4a1e1SFrank Piva {\
120*94c4a1e1SFrank Piva return glue(endian, _bswap)(v, size);\
121*94c4a1e1SFrank Piva }\
122*94c4a1e1SFrank Piva \
123*94c4a1e1SFrank Piva static inline void endian ## size ## _to_cpus(type *p)\
124*94c4a1e1SFrank Piva {\
125*94c4a1e1SFrank Piva glue(endian, _bswaps)(p, size);\
126*94c4a1e1SFrank Piva }\
127*94c4a1e1SFrank Piva \
128*94c4a1e1SFrank Piva static inline void cpu_to_ ## endian ## size ## s(type *p)\
129*94c4a1e1SFrank Piva {\
130*94c4a1e1SFrank Piva glue(endian, _bswaps)(p, size);\
131*94c4a1e1SFrank Piva }
132*94c4a1e1SFrank Piva
133*94c4a1e1SFrank Piva CPU_CONVERT(be, 16, uint16_t)
134*94c4a1e1SFrank Piva CPU_CONVERT(be, 32, uint32_t)
135*94c4a1e1SFrank Piva CPU_CONVERT(be, 64, uint64_t)
136*94c4a1e1SFrank Piva
137*94c4a1e1SFrank Piva CPU_CONVERT(le, 16, uint16_t)
138*94c4a1e1SFrank Piva CPU_CONVERT(le, 32, uint32_t)
139*94c4a1e1SFrank Piva CPU_CONVERT(le, 64, uint64_t)
140*94c4a1e1SFrank Piva
141*94c4a1e1SFrank Piva #endif
142