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: 06 февр. 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_BITS_H_
23 #define DSP_ARCH_X86_BITS_H_
24 
reverse_bits(uint8_t v)25 inline uint8_t __lsp_forced_inline    reverse_bits(uint8_t v)
26 {
27     register size_t tmp;
28 
29     ARCH_X86_ASM (
30         __ASM_EMIT("movzx %[v], %[tmp]")
31         __ASM_EMIT("mov (%[rb], %[tmp]), %[v]")
32         : [v] "+q"(v), [tmp] "=&r"(tmp)
33         : [rb] "r"(__rb)
34         : "cc"
35     );
36 
37     return v;
38 }
39 
reverse_bits(int8_t v)40 inline int8_t __lsp_forced_inline    reverse_bits(int8_t v)
41 {
42     register size_t tmp;
43 
44     ARCH_X86_ASM (
45         __ASM_EMIT("movzx %[v], %[tmp]")
46         __ASM_EMIT("mov (%[rb], %[tmp]), %[v]")
47         : [v] "+q"(v), [tmp] "=&r"(tmp)
48         : [rb] "r"(__rb)
49         : "cc"
50     );
51 
52     return v;
53 }
54 
reverse_bits(uint8_t v,size_t count)55 inline uint8_t __lsp_forced_inline    reverse_bits(uint8_t v, size_t count)
56 {
57     register size_t tmp;
58 
59     ARCH_X86_ASM (
60         __ASM_EMIT("movzx %[v], %[tmp]")
61         __ASM_EMIT("mov (%[rb], %[tmp]), %[v]")
62         __ASM_EMIT("shr %%cl, %[v]")
63         : [v] "+q"(v), [tmp] "=&r"(tmp)
64         : [rb] "r"(__rb), "c"(8-count)
65         : "cc"
66     );
67 
68     return v;
69 }
70 
reverse_bits(int8_t v,size_t count)71 inline int8_t __lsp_forced_inline    reverse_bits(int8_t v, size_t count)
72 {
73     register size_t tmp;
74 
75     ARCH_X86_ASM (
76         __ASM_EMIT("movzx %[v], %[tmp]")
77         __ASM_EMIT("mov (%[rb], %[tmp]), %[v]")
78         __ASM_EMIT("shr %%cl, %[v]")
79         : [v] "+q"(v), [tmp] "=&r"(tmp)
80         : [rb] "r"(__rb), "c"(8-count)
81         : "cc"
82     );
83 
84     return v;
85 }
86 
reverse_bits(uint16_t v)87 inline uint16_t __lsp_forced_inline   reverse_bits(uint16_t v)
88 {
89     #ifdef ARCH_X86_64
90     register size_t tmp;
91 
92     ARCH_X86_ASM (
93         __ASM_EMIT("movzx %%al, %[tmp]")
94         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
95         __ASM_EMIT("ror $8, %%ax")
96         __ASM_EMIT("movzx %%al, %[tmp]")
97         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
98 
99         : [v] "+a"(v), [tmp] "=&r"(tmp)
100         : [rb] "r"(__rb)
101         : "cc"
102     );
103     #else
104     register size_t tmp1, tmp2;
105 
106     ARCH_X86_ASM (
107         __ASM_EMIT("movzx %%al, %[tmp1]")
108         __ASM_EMIT("movzx %%ah, %[tmp2]")
109         __ASM_EMIT("mov (%[rb], %[tmp1]), %%ah")
110         __ASM_EMIT("mov (%[rb], %[tmp2]), %%al")
111         : [v] "+a"(v), [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2)
112         : [rb] "r"(__rb)
113         : "cc"
114     );
115     #endif /* ARCH_X86_64 */
116 
117     return v;
118 }
119 
reverse_bits(int16_t v)120 inline int16_t __lsp_forced_inline   reverse_bits(int16_t v)
121 {
122     #ifdef ARCH_X86_64
123     register size_t tmp;
124 
125     ARCH_X86_ASM (
126         __ASM_EMIT("movzx %%al, %[tmp]")
127         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
128         __ASM_EMIT("ror $8, %%ax")
129         __ASM_EMIT("movzx %%al, %[tmp]")
130         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
131 
132         : [v] "+a"(v), [tmp] "=&r"(tmp)
133         : [rb] "r"(__rb)
134         : "cc"
135     );
136     #else
137     register size_t tmp1, tmp2;
138 
139     ARCH_X86_ASM (
140         __ASM_EMIT("movzx %%al, %[tmp1]")
141         __ASM_EMIT("movzx %%ah, %[tmp2]")
142         __ASM_EMIT("mov (%[rb], %[tmp1]), %%ah")
143         __ASM_EMIT("mov (%[rb], %[tmp2]), %%al")
144         : [v] "+a"(v), [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2)
145         : [rb] "r"(__rb)
146         : "cc"
147     );
148     #endif /* ARCH_X86_64 */
149 
150     return v;
151 }
152 
reverse_bits(uint16_t v,size_t count)153 inline uint16_t __lsp_forced_inline    reverse_bits(uint16_t v, size_t count)
154 {
155     #ifdef ARCH_X86_64
156     register size_t tmp;
157 
158     ARCH_X86_ASM (
159         __ASM_EMIT("movzx %%al, %[tmp]")
160         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
161         __ASM_EMIT("ror $8, %%ax")
162         __ASM_EMIT("movzx %%al, %[tmp]")
163         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
164         __ASM_EMIT("shr %%cl, %[v]")
165 
166         : [v] "+a"(v), [tmp] "=&r"(tmp)
167         : [rb] "r"(__rb), "c"(16 - count)
168         : "cc"
169     );
170     #else
171     register size_t tmp1, tmp2;
172 
173     ARCH_X86_ASM (
174         __ASM_EMIT("movzx %%al, %[tmp1]")
175         __ASM_EMIT("movzx %%ah, %[tmp2]")
176         __ASM_EMIT("mov (%[rb], %[tmp1]), %%ah")
177         __ASM_EMIT("mov (%[rb], %[tmp2]), %%al")
178         __ASM_EMIT("shr %%cl, %[v]")
179         : [v] "+a"(v), [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2)
180         : [rb] "r"(__rb), "c"(16 - count)
181         : "cc"
182     );
183     #endif /* ARCH_X86_64 */
184 
185     return v;
186 }
187 
reverse_bits(int16_t v,size_t count)188 inline int16_t __lsp_forced_inline    reverse_bits(int16_t v, size_t count)
189 {
190     #ifdef ARCH_X86_64
191     register size_t tmp;
192 
193     ARCH_X86_ASM (
194         __ASM_EMIT("movzx %%al, %[tmp]")
195         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
196         __ASM_EMIT("ror $8, %%ax")
197         __ASM_EMIT("movzx %%al, %[tmp]")
198         __ASM_EMIT("mov (%[rb], %[tmp]), %%al")
199         __ASM_EMIT("shr %%cl, %[v]")
200 
201         : [v] "+a"(v), [tmp] "=&r"(tmp)
202         : [rb] "r"(__rb), "c"(16 - count)
203         : "cc"
204     );
205     #else
206     register size_t tmp1, tmp2;
207 
208     ARCH_X86_ASM (
209         __ASM_EMIT("movzx %%al, %[tmp1]")
210         __ASM_EMIT("movzx %%ah, %[tmp2]")
211         __ASM_EMIT("mov (%[rb], %[tmp1]), %%ah")
212         __ASM_EMIT("mov (%[rb], %[tmp2]), %%al")
213         __ASM_EMIT("shr %%cl, %[v]")
214         : [v] "+a"(v), [tmp1] "=&r"(tmp1), [tmp2] "=&r"(tmp2)
215         : [rb] "r"(__rb), "c"(16 - count)
216         : "cc"
217     );
218     #endif /* ARCH_X86_64 */
219 
220     return v;
221 }
222 
reverse_bits(uint32_t v)223 inline uint32_t __lsp_forced_inline    reverse_bits(uint32_t v)
224 {
225     register uint32_t tmp;
226 
227     ARCH_X86_ASM (
228         __ASM_EMIT("bswap %0")
229 
230         __ASM_EMIT("mov %0, %1")
231         __ASM_EMIT("and $0xf0f0f0f0, %0")
232         __ASM_EMIT("and $0x0f0f0f0f, %1")
233         __ASM_EMIT("shr $4, %0")
234         __ASM_EMIT("shl $4, %1")
235         __ASM_EMIT("or  %1, %0")
236 
237         __ASM_EMIT("mov %0, %1")
238         __ASM_EMIT("and $0xcccccccc, %0")
239         __ASM_EMIT("and $0x33333333, %1")
240         __ASM_EMIT("shr $2, %0")
241         __ASM_EMIT("lea (%0, %1, 4), %0")
242 
243         __ASM_EMIT("mov %0, %1")
244         __ASM_EMIT("and $0xaaaaaaaa, %0")
245         __ASM_EMIT("and $0x55555555, %1")
246         __ASM_EMIT("shr $1, %0")
247         __ASM_EMIT("lea (%0, %1, 2), %0")
248 
249         : "+r"(v), "=&r"(tmp)
250         :
251         : "cc"
252     );
253     return v;
254 }
255 
reverse_bits(int32_t v)256 inline int32_t __lsp_forced_inline    reverse_bits(int32_t v)
257 {
258     register uint32_t tmp;
259 
260     ARCH_X86_ASM (
261         __ASM_EMIT("bswap %0")
262 
263         __ASM_EMIT("mov %0, %1")
264         __ASM_EMIT("and $0xf0f0f0f0, %0")
265         __ASM_EMIT("and $0x0f0f0f0f, %1")
266         __ASM_EMIT("shr $4, %0")
267         __ASM_EMIT("shl $4, %1")
268         __ASM_EMIT("or  %1, %0")
269 
270         __ASM_EMIT("mov %0, %1")
271         __ASM_EMIT("and $0xcccccccc, %0")
272         __ASM_EMIT("and $0x33333333, %1")
273         __ASM_EMIT("shr $2, %0")
274         __ASM_EMIT("lea (%0, %1, 4), %0")
275 
276         __ASM_EMIT("mov %0, %1")
277         __ASM_EMIT("and $0xaaaaaaaa, %0")
278         __ASM_EMIT("and $0x55555555, %1")
279         __ASM_EMIT("shr $1, %0")
280         __ASM_EMIT("lea (%0, %1, 2), %0")
281 
282         : "+r"(v), "=&r"(tmp)
283         :
284         : "cc"
285     );
286     return v;
287 }
288 
reverse_bits(uint32_t v,size_t count)289 inline uint32_t __lsp_forced_inline    reverse_bits(uint32_t v, size_t count)
290 {
291     register uint32_t tmp;
292 
293     ARCH_X86_ASM (
294         __ASM_EMIT("bswap %0")
295 
296         __ASM_EMIT("mov %0, %1")
297         __ASM_EMIT("and $0xf0f0f0f0, %0")
298         __ASM_EMIT("and $0x0f0f0f0f, %1")
299         __ASM_EMIT("shr $4, %0")
300         __ASM_EMIT("shl $4, %1")
301         __ASM_EMIT("or  %1, %0")
302 
303         __ASM_EMIT("mov %0, %1")
304         __ASM_EMIT("and $0xcccccccc, %0")
305         __ASM_EMIT("and $0x33333333, %1")
306         __ASM_EMIT("shr $2, %0")
307         __ASM_EMIT("lea (%0, %1, 4), %0")
308 
309         __ASM_EMIT("mov %0, %1")
310         __ASM_EMIT("and $0xaaaaaaaa, %0")
311         __ASM_EMIT("and $0x55555555, %1")
312         __ASM_EMIT("shr $1, %0")
313         __ASM_EMIT("lea (%0, %1, 2), %0")
314 
315         __ASM_EMIT("shr %%cl, %0")
316 
317         : "+r"(v), "=&r"(tmp)
318         : "c"(32-count)
319         : "cc"
320     );
321     return v;
322 }
323 
reverse_bits(int32_t v,size_t count)324 inline int32_t __lsp_forced_inline    reverse_bits(int32_t v, size_t count)
325 {
326     register uint32_t tmp;
327 
328     ARCH_X86_ASM (
329         __ASM_EMIT("bswap %0")
330 
331         __ASM_EMIT("mov %0, %1")
332         __ASM_EMIT("and $0xf0f0f0f0, %0")
333         __ASM_EMIT("and $0x0f0f0f0f, %1")
334         __ASM_EMIT("shr $4, %0")
335         __ASM_EMIT("shl $4, %1")
336         __ASM_EMIT("or  %1, %0")
337 
338         __ASM_EMIT("mov %0, %1")
339         __ASM_EMIT("and $0xcccccccc, %0")
340         __ASM_EMIT("and $0x33333333, %1")
341         __ASM_EMIT("shr $2, %0")
342         __ASM_EMIT("lea (%0, %1, 4), %0")
343 
344         __ASM_EMIT("mov %0, %1")
345         __ASM_EMIT("and $0xaaaaaaaa, %0")
346         __ASM_EMIT("and $0x55555555, %1")
347         __ASM_EMIT("shr $1, %0")
348         __ASM_EMIT("lea (%0, %1, 2), %0")
349 
350         __ASM_EMIT("shr %%cl, %0")
351 
352         : "+r"(v), "=&r"(tmp)
353         : "c"(32-count)
354         : "cc"
355     );
356     return v;
357 }
358 
359 #ifdef ARCH_I386
reverse_bits(uint64_t v)360     inline uint64_t __lsp_forced_inline    reverse_bits(uint64_t v)
361     {
362         register uint32_t tmp1, tmp2;
363 
364         ARCH_X86_ASM
365         (
366             __ASM_EMIT("bswap %%eax")
367             __ASM_EMIT("bswap %%edx")
368             __ASM_EMIT("xchg %%edx, %%eax")
369 
370             __ASM_EMIT("mov %%eax, %1")
371             __ASM_EMIT("mov %%edx, %2")
372             __ASM_EMIT("and $0xf0f0f0f0, %%eax")
373             __ASM_EMIT("and $0xf0f0f0f0, %%edx")
374             __ASM_EMIT("and $0x0f0f0f0f, %1")
375             __ASM_EMIT("and $0x0f0f0f0f, %2")
376             __ASM_EMIT("shr $4, %%eax")
377             __ASM_EMIT("shr $4, %%edx")
378             __ASM_EMIT("shl $4, %1")
379             __ASM_EMIT("shl $4, %2")
380             __ASM_EMIT("or  %1, %%eax")
381             __ASM_EMIT("or  %2, %%edx")
382 
383             __ASM_EMIT("mov %%eax, %1")
384             __ASM_EMIT("mov %%edx, %2")
385             __ASM_EMIT("and $0xcccccccc, %%eax")
386             __ASM_EMIT("and $0xcccccccc, %%edx")
387             __ASM_EMIT("and $0x33333333, %1")
388             __ASM_EMIT("and $0x33333333, %2")
389             __ASM_EMIT("shr $2, %%eax")
390             __ASM_EMIT("shr $2, %%edx")
391             __ASM_EMIT("lea (%%eax, %1, 4), %%eax")
392             __ASM_EMIT("lea (%%edx, %2, 4), %%edx")
393 
394             __ASM_EMIT("mov %%eax, %1")
395             __ASM_EMIT("mov %%edx, %2")
396             __ASM_EMIT("and $0xaaaaaaaa, %%eax")
397             __ASM_EMIT("and $0xaaaaaaaa, %%edx")
398             __ASM_EMIT("and $0x55555555, %1")
399             __ASM_EMIT("and $0x55555555, %2")
400             __ASM_EMIT("shr $1, %%eax")
401             __ASM_EMIT("shr $1, %%edx")
402             __ASM_EMIT("lea (%%eax, %1, 2), %%eax")
403             __ASM_EMIT("lea (%%edx, %2, 2), %%edx")
404 
405             : "+A"(v), "=&r"(tmp1), "=&r"(tmp2)
406             :
407             : "cc"
408         );
409 
410         return v;
411     }
412 
reverse_bits(int64_t v)413     inline int64_t __lsp_forced_inline    reverse_bits(int64_t v)
414     {
415         register uint32_t tmp1, tmp2;
416 
417         ARCH_X86_ASM
418         (
419             __ASM_EMIT("bswap %%eax")
420             __ASM_EMIT("bswap %%edx")
421             __ASM_EMIT("xchg %%edx, %%eax")
422 
423             __ASM_EMIT("mov %%eax, %1")
424             __ASM_EMIT("mov %%edx, %2")
425             __ASM_EMIT("and $0xf0f0f0f0, %%eax")
426             __ASM_EMIT("and $0xf0f0f0f0, %%edx")
427             __ASM_EMIT("and $0x0f0f0f0f, %1")
428             __ASM_EMIT("and $0x0f0f0f0f, %2")
429             __ASM_EMIT("shr $4, %%eax")
430             __ASM_EMIT("shr $4, %%edx")
431             __ASM_EMIT("shl $4, %1")
432             __ASM_EMIT("shl $4, %2")
433             __ASM_EMIT("or  %1, %%eax")
434             __ASM_EMIT("or  %2, %%edx")
435 
436             __ASM_EMIT("mov %%eax, %1")
437             __ASM_EMIT("mov %%edx, %2")
438             __ASM_EMIT("and $0xcccccccc, %%eax")
439             __ASM_EMIT("and $0xcccccccc, %%edx")
440             __ASM_EMIT("and $0x33333333, %1")
441             __ASM_EMIT("and $0x33333333, %2")
442             __ASM_EMIT("shr $2, %%eax")
443             __ASM_EMIT("shr $2, %%edx")
444             __ASM_EMIT("lea (%%eax, %1, 4), %%eax")
445             __ASM_EMIT("lea (%%edx, %2, 4), %%edx")
446 
447             __ASM_EMIT("mov %%eax, %1")
448             __ASM_EMIT("mov %%edx, %2")
449             __ASM_EMIT("and $0xaaaaaaaa, %%eax")
450             __ASM_EMIT("and $0xaaaaaaaa, %%edx")
451             __ASM_EMIT("and $0x55555555, %1")
452             __ASM_EMIT("and $0x55555555, %2")
453             __ASM_EMIT("shr $1, %%eax")
454             __ASM_EMIT("shr $1, %%edx")
455             __ASM_EMIT("lea (%%eax, %1, 2), %%eax")
456             __ASM_EMIT("lea (%%edx, %2, 2), %%edx")
457 
458             : "+A"(v), "=&r"(tmp1), "=&r"(tmp2)
459             :
460             : "cc"
461         );
462 
463         return v;
464     }
465 
reverse_bits(uint64_t v,size_t count)466     inline uint64_t __lsp_forced_inline    reverse_bits(uint64_t v, size_t count)
467     {
468         register uint32_t tmp1, tmp2;
469         count = 64 - count;
470 
471         if (count < 32)
472         {
473             ARCH_X86_ASM
474             (
475                 __ASM_EMIT("bswap %%eax")
476                 __ASM_EMIT("bswap %%edx")
477                 __ASM_EMIT("xchg %%edx, %%eax")
478 
479                 __ASM_EMIT("mov %%eax, %[t1]")
480                 __ASM_EMIT("mov %%edx, %[t2]")
481                 __ASM_EMIT("and $0xf0f0f0f0, %%eax")
482                 __ASM_EMIT("and $0xf0f0f0f0, %%edx")
483                 __ASM_EMIT("and $0x0f0f0f0f, %[t1]")
484                 __ASM_EMIT("and $0x0f0f0f0f, %[t2]")
485                 __ASM_EMIT("shr $4, %%eax")
486                 __ASM_EMIT("shr $4, %%edx")
487                 __ASM_EMIT("shl $4, %[t1]")
488                 __ASM_EMIT("shl $4, %[t2]")
489                 __ASM_EMIT("or  %[t1], %%eax")
490                 __ASM_EMIT("or  %[t2], %%edx")
491 
492                 __ASM_EMIT("mov %%eax, %[t1]")
493                 __ASM_EMIT("mov %%edx, %[t2]")
494                 __ASM_EMIT("and $0xcccccccc, %%eax")
495                 __ASM_EMIT("and $0xcccccccc, %%edx")
496                 __ASM_EMIT("and $0x33333333, %[t1]")
497                 __ASM_EMIT("and $0x33333333, %[t2]")
498                 __ASM_EMIT("shr $2, %%eax")
499                 __ASM_EMIT("shr $2, %%edx")
500                 __ASM_EMIT("lea (%%eax, %[t1], 4), %%eax")
501                 __ASM_EMIT("lea (%%edx, %[t2], 4), %%edx")
502 
503                 __ASM_EMIT("mov %%eax, %[t1]")
504                 __ASM_EMIT("mov %%edx, %[t2]")
505                 __ASM_EMIT("and $0xaaaaaaaa, %%eax")
506                 __ASM_EMIT("and $0xaaaaaaaa, %%edx")
507                 __ASM_EMIT("and $0x55555555, %[t1]")
508                 __ASM_EMIT("and $0x55555555, %[t2]")
509                 __ASM_EMIT("shr $1, %%eax")
510                 __ASM_EMIT("shr $1, %%edx")
511                 __ASM_EMIT("lea (%%eax, %[t1], 2), %%eax")
512                 __ASM_EMIT("lea (%%edx, %[t2], 2), %%edx")
513 
514                 __ASM_EMIT("shrd %%cl, %%edx, %%eax")
515                 __ASM_EMIT("shr %%cl, %%edx")
516 
517                 : [v] "+A"(v), [t1] "=&r"(tmp1), [t2] "=&r"(tmp2)
518                 : [c] "c" (count)
519                 : "cc"
520             );
521         }
522         else
523         {
524             ARCH_X86_ASM
525             (
526                 __ASM_EMIT("bswap %%eax")
527                 __ASM_EMIT("sub $32, %[c]")
528 
529                 __ASM_EMIT("mov %%eax, %%edx")
530                 __ASM_EMIT("and $0xf0f0f0f0, %%eax")
531                 __ASM_EMIT("and $0x0f0f0f0f, %%edx")
532                 __ASM_EMIT("shr $4, %%eax")
533                 __ASM_EMIT("shl $4, %%edx")
534                 __ASM_EMIT("or  %%edx, %%eax")
535 
536                 __ASM_EMIT("mov %%eax, %%edx")
537                 __ASM_EMIT("and $0xcccccccc, %%eax")
538                 __ASM_EMIT("and $0x33333333, %%edx")
539                 __ASM_EMIT("shr $2, %%eax")
540                 __ASM_EMIT("lea (%%eax, %%edx, 4), %%eax")
541 
542                 __ASM_EMIT("mov %%eax, %%edx")
543                 __ASM_EMIT("and $0xaaaaaaaa, %%eax")
544                 __ASM_EMIT("and $0x55555555, %%edx")
545                 __ASM_EMIT("shr $1, %%eax")
546                 __ASM_EMIT("lea (%%eax, %%edx, 2), %%eax")
547 
548                 __ASM_EMIT("xor %%edx, %%edx")
549                 __ASM_EMIT("shr %%cl, %%eax")
550 
551                 : [v] "+A"(v), [c] "+c" (count)
552                 :
553                 : "cc"
554             );
555         }
556 
557         return v;
558     }
559 
reverse_bits(int64_t v,size_t count)560     inline int64_t __lsp_forced_inline    reverse_bits(int64_t v, size_t count)
561     {
562         register uint32_t tmp1, tmp2;
563         count = 64 - count;
564 
565         if (count < 32)
566         {
567             ARCH_X86_ASM
568             (
569                 __ASM_EMIT("bswap %%eax")
570                 __ASM_EMIT("bswap %%edx")
571                 __ASM_EMIT("xchg %%edx, %%eax")
572 
573                 __ASM_EMIT("mov %%eax, %[t1]")
574                 __ASM_EMIT("mov %%edx, %[t2]")
575                 __ASM_EMIT("and $0xf0f0f0f0, %%eax")
576                 __ASM_EMIT("and $0xf0f0f0f0, %%edx")
577                 __ASM_EMIT("and $0x0f0f0f0f, %[t1]")
578                 __ASM_EMIT("and $0x0f0f0f0f, %[t2]")
579                 __ASM_EMIT("shr $4, %%eax")
580                 __ASM_EMIT("shr $4, %%edx")
581                 __ASM_EMIT("shl $4, %[t1]")
582                 __ASM_EMIT("shl $4, %[t2]")
583                 __ASM_EMIT("or  %[t1], %%eax")
584                 __ASM_EMIT("or  %[t2], %%edx")
585 
586                 __ASM_EMIT("mov %%eax, %[t1]")
587                 __ASM_EMIT("mov %%edx, %[t2]")
588                 __ASM_EMIT("and $0xcccccccc, %%eax")
589                 __ASM_EMIT("and $0xcccccccc, %%edx")
590                 __ASM_EMIT("and $0x33333333, %[t1]")
591                 __ASM_EMIT("and $0x33333333, %[t2]")
592                 __ASM_EMIT("shr $2, %%eax")
593                 __ASM_EMIT("shr $2, %%edx")
594                 __ASM_EMIT("lea (%%eax, %[t1], 4), %%eax")
595                 __ASM_EMIT("lea (%%edx, %[t2], 4), %%edx")
596 
597                 __ASM_EMIT("mov %%eax, %[t1]")
598                 __ASM_EMIT("mov %%edx, %[t2]")
599                 __ASM_EMIT("and $0xaaaaaaaa, %%eax")
600                 __ASM_EMIT("and $0xaaaaaaaa, %%edx")
601                 __ASM_EMIT("and $0x55555555, %[t1]")
602                 __ASM_EMIT("and $0x55555555, %[t2]")
603                 __ASM_EMIT("shr $1, %%eax")
604                 __ASM_EMIT("shr $1, %%edx")
605                 __ASM_EMIT("lea (%%eax, %[t1], 2), %%eax")
606                 __ASM_EMIT("lea (%%edx, %[t2], 2), %%edx")
607 
608                 __ASM_EMIT("shrd %%cl, %%edx, %%eax")
609                 __ASM_EMIT("shr %%cl, %%edx")
610 
611                 : [v] "+A"(v), [t1] "=&r"(tmp1), [t2] "=&r"(tmp2)
612                 : [c] "c" (count)
613                 : "cc"
614             );
615         }
616         else
617         {
618             ARCH_X86_ASM
619             (
620                 __ASM_EMIT("bswap %%eax")
621                 __ASM_EMIT("sub $32, %[c]")
622 
623                 __ASM_EMIT("mov %%eax, %%edx")
624                 __ASM_EMIT("and $0xf0f0f0f0, %%eax")
625                 __ASM_EMIT("and $0x0f0f0f0f, %%edx")
626                 __ASM_EMIT("shr $4, %%eax")
627                 __ASM_EMIT("shl $4, %%edx")
628                 __ASM_EMIT("or  %%edx, %%eax")
629 
630                 __ASM_EMIT("mov %%eax, %%edx")
631                 __ASM_EMIT("and $0xcccccccc, %%eax")
632                 __ASM_EMIT("and $0x33333333, %%edx")
633                 __ASM_EMIT("shr $2, %%eax")
634                 __ASM_EMIT("lea (%%eax, %%edx, 4), %%eax")
635 
636                 __ASM_EMIT("mov %%eax, %%edx")
637                 __ASM_EMIT("and $0xaaaaaaaa, %%eax")
638                 __ASM_EMIT("and $0x55555555, %%edx")
639                 __ASM_EMIT("shr $1, %%eax")
640                 __ASM_EMIT("lea (%%eax, %%edx, 2), %%eax")
641 
642                 __ASM_EMIT("xor %%edx, %%edx")
643                 __ASM_EMIT("shr %%cl, %%eax")
644 
645                 : [v] "+A"(v), [c] "+c" (count)
646                 :
647                 : "cc"
648             );
649         }
650 
651         return v;
652     }
653 #else /* ARCH_X86_64 */
reverse_bits(uint64_t v)654     inline uint64_t __lsp_forced_inline    reverse_bits(uint64_t v)
655     {
656         register uint64_t tmp;
657 
658         ARCH_X86_ASM (
659             __ASM_EMIT("bswap %0")
660 
661             __ASM_EMIT("mov %0, %1")
662             __ASM_EMIT("and %2, %1")
663             __ASM_EMIT("shr $4, %0")
664             __ASM_EMIT("shl $4, %1")
665             __ASM_EMIT("and %2, %0")
666             __ASM_EMIT("or  %1, %0")
667 
668             __ASM_EMIT("mov %0, %1")
669             __ASM_EMIT("and %3, %1")
670             __ASM_EMIT("shr $2, %0")
671             __ASM_EMIT("and %3, %0")
672             __ASM_EMIT("lea (%0,%1,4), %0")
673 
674             __ASM_EMIT("mov %0, %1")
675             __ASM_EMIT("and %4, %1")
676             __ASM_EMIT("shr $1, %0")
677             __ASM_EMIT("and %4, %0")
678             __ASM_EMIT("lea (%0,%1,2), %0")
679 
680             : "+r"(v), "=&r"(tmp)
681             :
682             "r"(0x0f0f0f0f0f0f0f0fULL),
683             "r"(0x3333333333333333ULL),
684             "r"(0x5555555555555555ULL)
685             : "cc"
686         );
687 
688         return v;
689     }
690 
reverse_bits(int64_t v)691     inline int64_t __lsp_forced_inline    reverse_bits(int64_t v)
692     {
693         register uint64_t tmp;
694 
695         ARCH_X86_ASM (
696             __ASM_EMIT("bswap %0")
697 
698             __ASM_EMIT("mov %0, %1")
699             __ASM_EMIT("and %2, %1")
700             __ASM_EMIT("shr $4, %0")
701             __ASM_EMIT("shl $4, %1")
702             __ASM_EMIT("and %2, %0")
703             __ASM_EMIT("or  %1, %0")
704 
705             __ASM_EMIT("mov %0, %1")
706             __ASM_EMIT("and %3, %1")
707             __ASM_EMIT("shr $2, %0")
708             __ASM_EMIT("and %3, %0")
709             __ASM_EMIT("lea (%0,%1,4), %0")
710 
711             __ASM_EMIT("mov %0, %1")
712             __ASM_EMIT("and %4, %1")
713             __ASM_EMIT("shr $1, %0")
714             __ASM_EMIT("and %4, %0")
715             __ASM_EMIT("lea (%0,%1,2), %0")
716 
717             : "+r"(v), "=&r"(tmp)
718             :
719             "r"(0x0f0f0f0f0f0f0f0fULL),
720             "r"(0x3333333333333333ULL),
721             "r"(0x5555555555555555ULL)
722             : "cc"
723         );
724 
725         return v;
726     }
727 
reverse_bits(uint64_t v,size_t count)728     inline uint64_t __lsp_forced_inline    reverse_bits(uint64_t v, size_t count)
729     {
730         register uint64_t tmp;
731 
732         ARCH_X86_ASM (
733             __ASM_EMIT("bswap %0")
734 
735             __ASM_EMIT("mov %0, %1")
736             __ASM_EMIT("and %2, %1")
737             __ASM_EMIT("shr $4, %0")
738             __ASM_EMIT("shl $4, %1")
739             __ASM_EMIT("and %2, %0")
740             __ASM_EMIT("or  %1, %0")
741 
742             __ASM_EMIT("mov %0, %1")
743             __ASM_EMIT("and %3, %1")
744             __ASM_EMIT("shr $2, %0")
745             __ASM_EMIT("and %3, %0")
746             __ASM_EMIT("lea (%0,%1,4), %0")
747 
748             __ASM_EMIT("mov %0, %1")
749             __ASM_EMIT("and %4, %1")
750             __ASM_EMIT("shr $1, %0")
751             __ASM_EMIT("and %4, %0")
752             __ASM_EMIT("lea (%0,%1,2), %0")
753 
754             __ASM_EMIT("shr %%cl, %0")
755 
756             : "+r"(v), "=&r"(tmp)
757             :
758             "r"(0x0f0f0f0f0f0f0f0fULL),
759             "r"(0x3333333333333333ULL),
760             "r"(0x5555555555555555ULL),
761             "c"(64-count)
762             : "cc"
763         );
764 
765         return v;
766     }
767 
reverse_bits(int64_t v,size_t count)768     inline int64_t __lsp_forced_inline    reverse_bits(int64_t v, size_t count)
769     {
770         register uint64_t tmp;
771 
772         ARCH_X86_ASM (
773             __ASM_EMIT("bswap %0")
774 
775             __ASM_EMIT("mov %0, %1")
776             __ASM_EMIT("and %2, %1")
777             __ASM_EMIT("shr $4, %0")
778             __ASM_EMIT("shl $4, %1")
779             __ASM_EMIT("and %2, %0")
780             __ASM_EMIT("or  %1, %0")
781 
782             __ASM_EMIT("mov %0, %1")
783             __ASM_EMIT("and %3, %1")
784             __ASM_EMIT("shr $2, %0")
785             __ASM_EMIT("and %3, %0")
786             __ASM_EMIT("lea (%0,%1,4), %0")
787 
788             __ASM_EMIT("mov %0, %1")
789             __ASM_EMIT("and %4, %1")
790             __ASM_EMIT("shr $1, %0")
791             __ASM_EMIT("and %4, %0")
792             __ASM_EMIT("lea (%0,%1,2), %0")
793 
794             __ASM_EMIT("shr %%cl, %0")
795 
796             : "+r"(v), "=&r"(tmp)
797             :
798             "r"(0x0f0f0f0f0f0f0f0fULL),
799             "r"(0x3333333333333333ULL),
800             "r"(0x5555555555555555ULL),
801             "c"(64-count)
802             : "cc"
803         );
804 
805         return v;
806     }
807 
808 #endif /* ARCH_I386 */
809 
810 
int_log2(uint8_t v)811     inline int __lsp_forced_inline int_log2(uint8_t v)
812     {
813         uint32_t res = v, tmp;
814 
815         ARCH_X86_ASM (
816             __ASM_EMIT("xor     %[tmp], %[tmp]")
817             __ASM_EMIT("bsr     %[res], %[res]")
818             __ASM_EMIT("cmovz   %[tmp], %[res]")
819             : [res] "+r" (res), [tmp] "=&r" (tmp)
820             :
821             : "cc"
822         );
823         return res;
824     }
825 
int_log2(int8_t v)826     inline int __lsp_forced_inline     int_log2(int8_t v)
827     {
828         uint32_t res = uint8_t(v), tmp;
829 
830         ARCH_X86_ASM (
831             __ASM_EMIT("xor     %[tmp], %[tmp]")
832             __ASM_EMIT("bsr     %[res], %[res]")
833             __ASM_EMIT("cmovz   %[tmp], %[res]")
834             : [res] "+r" (res), [tmp] "=&r" (tmp)
835             :
836             : "cc"
837         );
838         return res;
839     }
840 
int_log2(uint16_t v)841     inline int __lsp_forced_inline     int_log2(uint16_t v)
842     {
843         uint32_t res = v, tmp;
844 
845         ARCH_X86_ASM (
846             __ASM_EMIT("xor     %[tmp], %[tmp]")
847             __ASM_EMIT("bsr     %[res], %[res]")
848             __ASM_EMIT("cmovz   %[tmp], %[res]")
849             : [res] "+r" (res), [tmp] "=&r" (tmp)
850             :
851             : "cc"
852         );
853         return res;
854     }
855 
int_log2(int16_t v)856     inline int __lsp_forced_inline     int_log2(int16_t v)
857     {
858         uint32_t res = uint16_t(v), tmp;
859 
860         ARCH_X86_ASM (
861             __ASM_EMIT("xor     %[tmp], %[tmp]")
862             __ASM_EMIT("bsr     %[res], %[res]")
863             __ASM_EMIT("cmovz   %[tmp], %[res]")
864             : [res] "+r" (res), [tmp] "=&r" (tmp)
865             :
866             : "cc"
867         );
868         return res;
869     }
870 
int_log2(uint32_t v)871     inline int __lsp_forced_inline     int_log2(uint32_t v)
872     {
873         uint32_t tmp;
874 
875         ARCH_X86_ASM (
876             __ASM_EMIT("xor     %[tmp], %[tmp]")
877             __ASM_EMIT("bsr     %[res], %[res]")
878             __ASM_EMIT("cmovz   %[tmp], %[res]")
879             : [res] "+r" (v), [tmp] "=&r" (tmp)
880             :
881             : "cc"
882         );
883         return v;
884     }
885 
int_log2(int32_t v)886     inline int __lsp_forced_inline     int_log2(int32_t v)
887     {
888         uint32_t tmp;
889 
890         ARCH_X86_ASM (
891             __ASM_EMIT("xor     %[tmp], %[tmp]")
892             __ASM_EMIT("bsr     %[res], %[res]")
893             __ASM_EMIT("cmovz   %[tmp], %[res]")
894             : [res] "+r" (v), [tmp] "=&r" (tmp)
895             :
896             : "cc"
897         );
898         return v;
899     }
900 
901 #ifdef ARCH_X86_64
int_log2(uint64_t v)902     inline int __lsp_forced_inline     int_log2(uint64_t v)
903     {
904         uint64_t tmp;
905 
906         ARCH_X86_ASM (
907             __ASM_EMIT("xor     %[tmp], %[tmp]")
908             __ASM_EMIT("bsr     %[res], %[res]")
909             __ASM_EMIT("cmovz   %[tmp], %[res]")
910             : [res] "+r" (v), [tmp] "=&r" (tmp)
911             :
912             : "cc"
913         );
914         return int(v);
915     }
916 
int_log2(int64_t v)917     inline int __lsp_forced_inline     int_log2(int64_t v)
918     {
919         uint64_t tmp;
920 
921         ARCH_X86_ASM (
922             __ASM_EMIT("xor     %[tmp], %[tmp]")
923             __ASM_EMIT("bsr     %[res], %[res]")
924             __ASM_EMIT("cmovz   %[tmp], %[res]")
925             : [res] "+r" (v), [tmp] "=&r" (tmp)
926             :
927             : "cc"
928         );
929         return int(v);
930     }
931 #else
int_log2(uint64_t v)932     inline int __lsp_forced_inline     int_log2(uint64_t v)
933     {
934         ARCH_X86_ASM (
935             __ASM_EMIT("test    %%edx, %%edx")
936             __ASM_EMIT("jz      2f")
937             __ASM_EMIT("mov     %%edx, %%eax")
938             __ASM_EMIT("xor     %%edx, %%edx")
939             __ASM_EMIT("bsr     %%eax, %%eax")
940             __ASM_EMIT("cmovz   %%edx, %%eax")
941             __ASM_EMIT("add     $32, %%eax")
942             __ASM_EMIT("jmp     4f")
943 
944             __ASM_EMIT("2:")
945             __ASM_EMIT("xor     %%edx, %%edx")
946             __ASM_EMIT("bsr     %%eax, %%eax")
947             __ASM_EMIT("cmovz   %%edx, %%eax")
948 
949             __ASM_EMIT("4:")
950 
951             : [v] "+A" (v)
952             :
953             : "cc"
954         );
955         return int(v);
956     }
957 
int_log2(int64_t v)958     inline int __lsp_forced_inline     int_log2(int64_t v)
959     {
960         ARCH_X86_ASM (
961             __ASM_EMIT("test    %%edx, %%edx")
962             __ASM_EMIT("jz      2f")
963             __ASM_EMIT("mov     %%edx, %%eax")
964             __ASM_EMIT("xor     %%edx, %%edx")
965             __ASM_EMIT("bsr     %%eax, %%eax")
966             __ASM_EMIT("cmovz   %%edx, %%eax")
967             __ASM_EMIT("add     $32, %%eax")
968             __ASM_EMIT("jmp     4f")
969 
970             __ASM_EMIT("2:")
971             __ASM_EMIT("xor     %%edx, %%edx")
972             __ASM_EMIT("bsr     %%eax, %%eax")
973             __ASM_EMIT("cmovz   %%edx, %%eax")
974 
975             __ASM_EMIT("4:")
976 
977             : [v] "+A" (v)
978             :
979             : "cc"
980         );
981         return int(v);
982     }
983 #endif /* ARCH_X86_64 */
984 
985 #endif /* DSP_ARCH_X86_BITS_H_ */
986