1 /*
2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4 *
5 * This file is part of lsp-plugins
6 * Created on: 04 мар. 2016 г.
7 *
8 * lsp-plugins is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * any later version.
12 *
13 * lsp-plugins is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #ifndef DSP_ARCH_X86_BSWAP_H_
23 #define DSP_ARCH_X86_BSWAP_H_
24
byte_swap(uint16_t v)25 inline uint16_t __lsp_forced_inline byte_swap(uint16_t v)
26 {
27 ARCH_X86_ASM (
28 __ASM_EMIT("ror $8, %[v]")
29 : [v] "+r"(v)
30 : : "cc"
31 );
32 return v;
33 }
34
byte_swap(uint32_t v)35 inline uint32_t __lsp_forced_inline byte_swap(uint32_t v)
36 {
37 ARCH_X86_ASM (
38 __ASM_EMIT("bswap %[v]")
39 : [v] "+r"(v)
40 : :
41 );
42 return v;
43 }
44
byte_swap(float v)45 inline float __lsp_forced_inline byte_swap(float v)
46 {
47 ARCH_X86_ASM (
48 __ASM_EMIT("bswap %[v]")
49 : [v] "+r"(v)
50 : :
51 );
52 return v;
53 }
54
55 #ifdef ARCH_X86_64
byte_swap(uint64_t v)56 inline uint64_t __lsp_forced_inline byte_swap(uint64_t v)
57 {
58 ARCH_X86_ASM (
59 __ASM_EMIT("bswap %[v]")
60 : [v] "+r"(v)
61 : :
62 );
63 return v;
64 }
65
byte_swap(double v)66 inline double __lsp_forced_inline byte_swap(double v)
67 {
68 ARCH_X86_ASM (
69 __ASM_EMIT("bswap %[v]")
70 : [v] "+r"(v)
71 : :
72 );
73 return v;
74 }
75
76 #else /* ARCH_I386 */
byte_swap(uint64_t v)77 inline uint64_t __lsp_forced_inline byte_swap(uint64_t v)
78 {
79 ARCH_X86_ASM (
80 __ASM_EMIT("bswap %%eax")
81 __ASM_EMIT("bswap %%edx")
82 __ASM_EMIT("xchg %%edx, %%eax")
83 : "+A"(v)
84 : :
85 );
86 return v;
87 }
88
byte_swap(double v)89 inline double __lsp_forced_inline byte_swap(double v)
90 {
91 ARCH_X86_ASM (
92 __ASM_EMIT("bswap %%eax")
93 __ASM_EMIT("bswap %%edx")
94 __ASM_EMIT("xchg %%edx, %%eax")
95 : "+A"(v)
96 : :
97 );
98 return v;
99 }
100
101 #endif /* ARCH_X86_64 */
102
byte_swap(uint16_t * v,size_t n)103 inline void __lsp_forced_inline byte_swap(uint16_t *v, size_t n)
104 {
105 uint16_t tmp;
106 ARCH_X86_ASM (
107 __ASM_EMIT("test %[n], %[n]")
108 __ASM_EMIT("jz 2f")
109 __ASM_EMIT("1:")
110 __ASM_EMIT("lodsw")
111 __ASM_EMIT("ror $8, %[tmp]")
112 __ASM_EMIT("dec %[n]")
113 __ASM_EMIT("mov %[tmp], -2(%[v])")
114 __ASM_EMIT("jnz 1b")
115 __ASM_EMIT("2:")
116 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
117 : : "cc", "memory"
118 );
119 }
120
byte_swap(int16_t * v,size_t n)121 inline void __lsp_forced_inline byte_swap(int16_t *v, size_t n)
122 {
123 uint16_t tmp;
124 ARCH_X86_ASM (
125 __ASM_EMIT("test %[n], %[n]")
126 __ASM_EMIT("jz 2f")
127 __ASM_EMIT("1:")
128 __ASM_EMIT("lodsw")
129 __ASM_EMIT("ror $8, %[tmp]")
130 __ASM_EMIT("dec %[n]")
131 __ASM_EMIT("mov %[tmp], -2(%[v])")
132 __ASM_EMIT("jnz 1b")
133 __ASM_EMIT("2:")
134 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
135 : : "cc", "memory"
136 );
137 }
138
byte_swap(uint32_t * v,size_t n)139 inline void __lsp_forced_inline byte_swap(uint32_t *v, size_t n)
140 {
141 uint32_t tmp;
142 ARCH_X86_ASM (
143 __ASM_EMIT("test %[n], %[n]")
144 __ASM_EMIT("jz 2f")
145 __ASM_EMIT("1:")
146 __ASM_EMIT("lodsl")
147 __ASM_EMIT("bswap %[tmp]")
148 __ASM_EMIT("dec %[n]")
149 __ASM_EMIT("mov %[tmp], -4(%[v])")
150 __ASM_EMIT("jnz 1b")
151 __ASM_EMIT("2:")
152 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
153 : : "cc", "memory"
154 );
155 }
156
byte_swap(int32_t * v,size_t n)157 inline void __lsp_forced_inline byte_swap(int32_t *v, size_t n)
158 {
159 uint32_t tmp;
160 ARCH_X86_ASM (
161 __ASM_EMIT("test %[n], %[n]")
162 __ASM_EMIT("jz 2f")
163 __ASM_EMIT("1:")
164 __ASM_EMIT("lodsl")
165 __ASM_EMIT("bswap %[tmp]")
166 __ASM_EMIT("dec %[n]")
167 __ASM_EMIT("mov %[tmp], -4(%[v])")
168 __ASM_EMIT("jnz 1b")
169 __ASM_EMIT("2:")
170 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
171 : : "cc", "memory"
172 );
173 }
174
byte_swap(float * v,size_t n)175 inline void __lsp_forced_inline byte_swap(float *v, size_t n)
176 {
177 uint32_t tmp;
178 ARCH_X86_ASM (
179 __ASM_EMIT("test %[n], %[n]")
180 __ASM_EMIT("jz 2f")
181 __ASM_EMIT("1:")
182 __ASM_EMIT("lodsl")
183 __ASM_EMIT("bswap %[tmp]")
184 __ASM_EMIT("dec %[n]")
185 __ASM_EMIT("mov %[tmp], -4(%[v])")
186 __ASM_EMIT("jnz 1b")
187 __ASM_EMIT("2:")
188 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
189 : : "cc", "memory"
190 );
191 }
192
193 #ifdef ARCH_X86_64
byte_swap(uint64_t * v,size_t n)194 inline void __lsp_forced_inline byte_swap(uint64_t *v, size_t n)
195 {
196 uint64_t tmp;
197 ARCH_X86_ASM (
198 __ASM_EMIT("test %[n], %[n]")
199 __ASM_EMIT("jz 2f")
200 __ASM_EMIT("1:")
201 __ASM_EMIT("lodsq")
202 __ASM_EMIT("bswap %[tmp]")
203 __ASM_EMIT("dec %[n]")
204 __ASM_EMIT("mov %[tmp], -8(%[v])")
205 __ASM_EMIT("jnz 1b")
206 __ASM_EMIT("2:")
207 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
208 : : "cc", "memory"
209 );
210 }
211
byte_swap(int64_t * v,size_t n)212 inline void __lsp_forced_inline byte_swap(int64_t *v, size_t n)
213 {
214 uint64_t tmp;
215 ARCH_X86_ASM (
216 __ASM_EMIT("test %[n], %[n]")
217 __ASM_EMIT("jz 2f")
218 __ASM_EMIT("1:")
219 __ASM_EMIT("lodsq")
220 __ASM_EMIT("bswap %[tmp]")
221 __ASM_EMIT("dec %[n]")
222 __ASM_EMIT("mov %[tmp], -8(%[v])")
223 __ASM_EMIT("jnz 1b")
224 __ASM_EMIT("2:")
225 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
226 : : "cc", "memory"
227 );
228 }
229
byte_swap(double * v,size_t n)230 inline void __lsp_forced_inline byte_swap(double *v, size_t n)
231 {
232 uint64_t tmp;
233 ARCH_X86_ASM (
234 __ASM_EMIT("test %[n], %[n]")
235 __ASM_EMIT("jz 2f")
236 __ASM_EMIT("1:")
237 __ASM_EMIT("lodsq")
238 __ASM_EMIT("bswap %[tmp]")
239 __ASM_EMIT("dec %[n]")
240 __ASM_EMIT("mov %[tmp], -8(%[v])")
241 __ASM_EMIT("jnz 1b")
242 __ASM_EMIT("2:")
243 : [v] "+S"(v), [n] "+r" (n), [tmp] "=&a"(tmp)
244 : : "cc", "memory"
245 );
246 }
247
248 #else /* ARCH_I386 */
249
byte_swap(uint64_t * v,size_t n)250 inline void __lsp_forced_inline byte_swap(uint64_t *v, size_t n)
251 {
252 uint32_t a, b;
253 ARCH_X86_ASM (
254 __ASM_EMIT("test %[n], %[n]")
255 __ASM_EMIT("jz 2f")
256 __ASM_EMIT("1:")
257 __ASM_EMIT("mov (%[v]), %[a]")
258 __ASM_EMIT("mov 4(%[v]), %[b]")
259 __ASM_EMIT("bswap %[a]")
260 __ASM_EMIT("bswap %[b]")
261 __ASM_EMIT("mov %[b], (%[v])")
262 __ASM_EMIT("mov %[a], 4(%[v])")
263 __ASM_EMIT("add $8, %[v]")
264 __ASM_EMIT("dec %[n]")
265 __ASM_EMIT("jnz 1b")
266 __ASM_EMIT("2:")
267 : [v] "+r"(v), [n] "+r" (n), [a] "=&r" (a), [b] "=&r" (b)
268 : : "cc", "memory"
269 );
270 }
271
byte_swap(int64_t * v,size_t n)272 inline void __lsp_forced_inline byte_swap(int64_t *v, size_t n)
273 {
274 uint32_t a, b;
275 ARCH_X86_ASM (
276 __ASM_EMIT("test %[n], %[n]")
277 __ASM_EMIT("jz 2f")
278 __ASM_EMIT("1:")
279 __ASM_EMIT("mov (%[v]), %[a]")
280 __ASM_EMIT("mov 4(%[v]), %[b]")
281 __ASM_EMIT("bswap %[a]")
282 __ASM_EMIT("bswap %[b]")
283 __ASM_EMIT("mov %[b], (%[v])")
284 __ASM_EMIT("mov %[a], 4(%[v])")
285 __ASM_EMIT("add $8, %[v]")
286 __ASM_EMIT("dec %[n]")
287 __ASM_EMIT("jnz 1b")
288 __ASM_EMIT("2:")
289 : [v] "+r"(v), [n] "+r" (n), [a] "=&r" (a), [b] "=&r" (b)
290 : : "cc", "memory"
291 );
292 }
293
byte_swap(double * v,size_t n)294 inline void __lsp_forced_inline byte_swap(double *v, size_t n)
295 {
296 uint32_t a, b;
297 ARCH_X86_ASM (
298 __ASM_EMIT("test %[n], %[n]")
299 __ASM_EMIT("jz 2f")
300 __ASM_EMIT("1:")
301 __ASM_EMIT("mov (%[v]), %[a]")
302 __ASM_EMIT("mov 4(%[v]), %[b]")
303 __ASM_EMIT("bswap %[a]")
304 __ASM_EMIT("bswap %[b]")
305 __ASM_EMIT("mov %[b], (%[v])")
306 __ASM_EMIT("mov %[a], 4(%[v])")
307 __ASM_EMIT("add $8, %[v]")
308 __ASM_EMIT("dec %[n]")
309 __ASM_EMIT("jnz 1b")
310 __ASM_EMIT("2:")
311 : [v] "+r"(v), [n] "+r" (n), [a] "=&r"(a), [b] "=&r"(b)
312 : : "cc", "memory"
313 );
314 }
315 #endif /* ARCH_X86_64 */
316
317 #if defined(WCHART_16BIT)
byte_swap(wchar_t v)318 inline wchar_t __lsp_forced_inline byte_swap(wchar_t v)
319 {
320 ARCH_X86_ASM (
321 __ASM_EMIT("ror $8, %[v]")
322 : [v] "+r"(v)
323 : : "cc"
324 );
325 return v;
326 }
327 #elif defined(WCHART_32BIT)
byte_swap(wchar_t v)328 inline wchar_t __lsp_forced_inline byte_swap(wchar_t v)
329 {
330 ARCH_X86_ASM (
331 __ASM_EMIT("bswap %[v]")
332 : [v] "+r"(v)
333 : :
334 );
335 return v;
336 }
337 #endif /* PLATFORM_WINDOWS */
338
339 #endif /* DSP_ARCH_X86_BSWAP_H_ */
340