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