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 апр. 2018 г.
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 /* Copyright (C) 2007  Julien Pommier
23 
24   This software is provided 'as-is', without any express or implied
25   warranty.  In no event will the authors be held liable for any damages
26   arising from the use of this software.
27 
28   Permission is granted to anyone to use this software for any purpose,
29   including commercial applications, and to alter it and redistribute it
30   freely, subject to the following restrictions:
31 
32   1. The origin of this software must not be misrepresented; you must not
33      claim that you wrote the original software. If you use this software
34      in a product, an acknowledgment in the product documentation would be
35      appreciated but is not required.
36   2. Altered source versions must be plainly marked as such, and must not be
37      misrepresented as being the original software.
38   3. This notice may not be removed or altered from any source distribution.
39 
40   (this is the zlib license)
41 */
42 
43 #ifndef DSP_ARCH_X86_SSE3_GRAPHICS_H_
44 #define DSP_ARCH_X86_SSE3_GRAPHICS_H_
45 
46 #ifndef DSP_ARCH_X86_SSE3_IMPL
47     #error "This header should not be included directly"
48 #endif /* DSP_ARCH_X86_SSE3_IMPL */
49 
50 namespace sse3
51 {
x64_axis_apply_log1(float * x,const float * v,float zero,float norm_x,size_t count)52     void x64_axis_apply_log1(float *x, const float *v, float zero, float norm_x, size_t count)
53     {
54         //---------------------------------------------------------------
55         // Prepare constants
56         ARCH_X86_64_ASM
57         (
58             __ASM_EMIT("movss       %[zero], %%xmm0")
59             __ASM_EMIT("movss       %[norm_x], %%xmm1")
60             __ASM_EMIT("shufps      $0x00, %%xmm0, %%xmm0")         // xmm0 == zero
61             __ASM_EMIT("shufps      $0x00, %%xmm1, %%xmm1")         // xmm1 == norm_x
62 
63             __ASM_EMIT("sub         $8, %[count]")
64             __ASM_EMIT("jb          2f")
65             __ASM_EMIT("movaps      %%xmm0, %%xmm8")
66             __ASM_EMIT("movaps      %%xmm1, %%xmm9")
67             __ASM_EMIT("movaps      %%xmm2, %%xmm10")
68 
69             // Do x8 blocks
70             __ASM_EMIT("1:")
71             __ASM_EMIT("movups      0x00(%[v]), %%xmm3")            // xmm3 = v
72             __ASM_EMIT("movups      0x10(%[v]), %%xmm11")
73             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
74             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm11")
75             __ASM_EMIT("add         $0x20, %[v]")                   // v   += 4
76             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
77             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm11")
78             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
79             __ASM_EMIT("mulps       %%xmm8, %%xmm11")
80             // Step 2: parse float value
81             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
82             __ASM_EMIT("movdqa      %%xmm11, %%xmm12")
83             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
84             __ASM_EMIT("psrld       $23, %%xmm12")
85             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
86             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm11")
87             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
88             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm12")
89             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
90             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm11")
91             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
92             __ASM_EMIT("cvtdq2ps    %%xmm12, %%xmm12")
93             // Prepare logarithm approximation calculations
94             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
95             __ASM_EMIT("movaps      %%xmm11, %%xmm13")
96             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
97             __ASM_EMIT("movaps      %%xmm11, %%xmm14")
98             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
99             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm13")
100             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
101             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm15")
102             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
103             __ASM_EMIT("andps       %%xmm13, %%xmm14")
104             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
105             __ASM_EMIT("addps       %%xmm14, %%xmm11")
106             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
107             __ASM_EMIT("andnps      %%xmm15, %%xmm13")
108             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
109             __ASM_EMIT("addps       %%xmm13, %%xmm12")
110             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
111             __ASM_EMIT("subps       %%xmm15, %%xmm11")
112             // Calculate logarithmic values
113             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
114             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm13")
115             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = L0*A
116             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
117             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
118             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm13")
119             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
120             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
121             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
122             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm13")
123             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
124             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
125             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
126             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm13")
127             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
128             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
129             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
130             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm13")
131             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
132             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
133             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
134             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm13")
135             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
136             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
137             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
138             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm13")
139             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
140             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
141             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
142             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm13")
143             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
144             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
145             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
146             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm13")
147             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
148             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
149             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
150             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm13")
151             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
152             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
153             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
154             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
155             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
156             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm12")
157             __ASM_EMIT("addps       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
158             __ASM_EMIT("addps       %%xmm12, %%xmm13")
159             __ASM_EMIT("addps       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
160             __ASM_EMIT("addps       %%xmm11, %%xmm13")
161             // Apply values to axes
162             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
163             __ASM_EMIT("movaps      %%xmm13, %%xmm11")
164             __ASM_EMIT("movups      0x00(%[x]), %%xmm4")            // xmm4 = x
165             __ASM_EMIT("movups      0x10(%[x]), %%xmm12")
166             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
167             __ASM_EMIT("mulps       %%xmm9, %%xmm11")
168             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
169             __ASM_EMIT("addps       %%xmm11, %%xmm12")
170             __ASM_EMIT("movups      %%xmm4, 0x00(%[x])")
171             __ASM_EMIT("movups      %%xmm12, 0x10(%[x])")
172             __ASM_EMIT("add         $0x20, %[x]")
173             __ASM_EMIT("sub         $8, %[count]")
174             __ASM_EMIT("jae         1b")
175 
176             __ASM_EMIT("2:")
177             __ASM_EMIT("add         $4, %[count]")
178             __ASM_EMIT("jl          4f")
179             // Do x4 block
180             __ASM_EMIT("movups      (%[v]), %%xmm3")                // xmm3 = v
181             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
182             __ASM_EMIT("add         $0x10, %[v]")                   // v   += 4
183             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
184             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
185             // Step 2: parse float value
186             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
187             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
188             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
189             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
190             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
191             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
192             // Prepare logarithm approximation calculations
193             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
194             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
195             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
196             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
197             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
198             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
199             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
200             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
201             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
202             // Calculate logarithmic values
203             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
204             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = L0*A
205             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
206             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
207             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
208             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
209             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
210             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
211             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
212             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
213             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
214             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
215             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
216             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
217             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
218             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
219             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
220             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
221             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
222             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
223             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
224             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
225             __ASM_EMIT("addps       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
226             __ASM_EMIT("addps       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
227             // Apply values to axes
228             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
229             __ASM_EMIT("movups      (%[x]), %%xmm4")                // xmm4 = x
230             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
231             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
232             __ASM_EMIT("movups      %%xmm4, (%[x])")
233             __ASM_EMIT("add         $0x10, %[x]")
234             __ASM_EMIT("sub         $4, %[count]")
235 
236             __ASM_EMIT("4:")
237             __ASM_EMIT("add         $3, %[count]")
238             __ASM_EMIT("jl          6f")
239             // Do x1 blocks
240             __ASM_EMIT("5:")
241             __ASM_EMIT("movss       (%[v]), %%xmm3")                // xmm3 = v
242             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
243             __ASM_EMIT("add         $0x04, %[v]")                   // v   += 4
244             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
245             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
246             // Step 2: parse float value
247             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
248             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
249             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
250             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
251             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
252             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
253             // Prepare logarithm approximation calculations
254             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
255             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
256             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
257             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
258             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
259             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
260             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
261             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
262             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
263             // Calculate logarithmic values
264             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
265             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = L0*A
266             __ASM_EMIT("addss       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
267             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
268             __ASM_EMIT("addss       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
269             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
270             __ASM_EMIT("addss       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
271             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
272             __ASM_EMIT("addss       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
273             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
274             __ASM_EMIT("addss       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
275             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
276             __ASM_EMIT("addss       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
277             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
278             __ASM_EMIT("addss       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
279             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
280             __ASM_EMIT("addss       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
281             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
282             __ASM_EMIT("addss       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
283             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
284             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
285             __ASM_EMIT("mulss       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
286             __ASM_EMIT("addss       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
287             __ASM_EMIT("addss       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
288             // Apply values to axes
289             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
290             __ASM_EMIT("movss       (%[x]), %%xmm4")                // xmm4 = x
291             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
292             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
293             __ASM_EMIT("movss       %%xmm4, (%[x])")
294             __ASM_EMIT("add         $0x04, %[x]")
295             __ASM_EMIT("dec         %[count]")
296             __ASM_EMIT("jge         5b")
297 
298             __ASM_EMIT("6:")
299             : [v] "+r" (v), [x] "+r" (x) ,
300               [count] "+r" (count)
301             : [zero] "m" (zero), [norm_x] "m" (norm_x),
302               [ILOG] "o" (LOG_IARGS), [FLOG] "o" (LOG_FARGS)
303             :
304               "%xmm0", "%xmm1", "%xmm2", "%xmm3",
305               "%xmm4", "%xmm5", "%xmm6", "%xmm7",
306               "%xmm8", "%xmm9", "%xmm10", "%xmm11",
307               "%xmm12", "%xmm13", "%xmm14", "%xmm15"
308         );
309     }
310 
x64_axis_apply_log2(float * x,float * y,const float * v,float zero,float norm_x,float norm_y,size_t count)311     void x64_axis_apply_log2(float *x, float *y, const float *v, float zero, float norm_x, float norm_y, size_t count)
312     {
313         //---------------------------------------------------------------
314         // Prepare constants
315         ARCH_X86_64_ASM
316         (
317             __ASM_EMIT("movss       %[zero], %%xmm0")
318             __ASM_EMIT("movss       %[norm_x], %%xmm1")
319             __ASM_EMIT("movss       %[norm_y], %%xmm2")
320             __ASM_EMIT("shufps      $0x00, %%xmm0, %%xmm0")         // xmm0 == zero
321             __ASM_EMIT("shufps      $0x00, %%xmm1, %%xmm1")         // xmm1 == norm_x
322             __ASM_EMIT("shufps      $0x00, %%xmm2, %%xmm2")         // xmm2 == norm_y
323 
324             __ASM_EMIT("sub         $8, %[count]")
325             __ASM_EMIT("jb          2f")
326             __ASM_EMIT("movaps      %%xmm0, %%xmm8")
327             __ASM_EMIT("movaps      %%xmm1, %%xmm9")
328             __ASM_EMIT("movaps      %%xmm2, %%xmm10")
329 
330             // Do x8 blocks
331             __ASM_EMIT("1:")
332             __ASM_EMIT("movups      0x00(%[v]), %%xmm3")            // xmm3 = v
333             __ASM_EMIT("movups      0x10(%[v]), %%xmm11")
334             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
335             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm11")
336             __ASM_EMIT("add         $0x20, %[v]")                   // v   += 4
337             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
338             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm11")
339             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
340             __ASM_EMIT("mulps       %%xmm8, %%xmm11")
341             // Step 2: parse float value
342             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
343             __ASM_EMIT("movdqa      %%xmm11, %%xmm12")
344             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
345             __ASM_EMIT("psrld       $23, %%xmm12")
346             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
347             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm11")
348             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
349             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm12")
350             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
351             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm11")
352             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
353             __ASM_EMIT("cvtdq2ps    %%xmm12, %%xmm12")
354             // Prepare logarithm approximation calculations
355             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
356             __ASM_EMIT("movaps      %%xmm11, %%xmm13")
357             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
358             __ASM_EMIT("movaps      %%xmm11, %%xmm14")
359             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
360             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm13")
361             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
362             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm15")
363             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
364             __ASM_EMIT("andps       %%xmm13, %%xmm14")
365             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
366             __ASM_EMIT("addps       %%xmm14, %%xmm11")
367             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
368             __ASM_EMIT("andnps      %%xmm15, %%xmm13")
369             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
370             __ASM_EMIT("addps       %%xmm13, %%xmm12")
371             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
372             __ASM_EMIT("subps       %%xmm15, %%xmm11")
373             // Calculate logarithmic values
374             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
375             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm13")
376             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = L0*A
377             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
378             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
379             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm13")
380             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
381             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
382             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
383             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm13")
384             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
385             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
386             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
387             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm13")
388             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
389             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
390             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
391             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm13")
392             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
393             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
394             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
395             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm13")
396             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
397             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
398             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
399             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm13")
400             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
401             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
402             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
403             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm13")
404             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
405             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
406             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
407             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm13")
408             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
409             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
410             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
411             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm13")
412             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
413             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
414             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
415             __ASM_EMIT("mulps       %%xmm11, %%xmm13")
416             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
417             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm12")
418             __ASM_EMIT("addps       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
419             __ASM_EMIT("addps       %%xmm12, %%xmm13")
420             __ASM_EMIT("addps       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
421             __ASM_EMIT("addps       %%xmm11, %%xmm13")
422             // Apply values to axes
423             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
424             __ASM_EMIT("movaps      %%xmm13, %%xmm11")
425             __ASM_EMIT("movups      0x00(%[x]), %%xmm4")            // xmm4 = x
426             __ASM_EMIT("movups      0x10(%[x]), %%xmm12")
427             __ASM_EMIT("movups      0x00(%[y]), %%xmm6")            // xmm6 = y
428             __ASM_EMIT("movups      0x10(%[y]), %%xmm14")
429             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
430             __ASM_EMIT("mulps       %%xmm9, %%xmm11")
431             __ASM_EMIT("mulps       %%xmm2, %%xmm5")                // xmm5 = log(abs(v*zero)) * norm_y
432             __ASM_EMIT("mulps       %%xmm10, %%xmm13")
433             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
434             __ASM_EMIT("addps       %%xmm11, %%xmm12")
435             __ASM_EMIT("addps       %%xmm5, %%xmm6")                // xmm6 = y + log(abs(v*zero)) * norm_y
436             __ASM_EMIT("addps       %%xmm13, %%xmm14")
437             __ASM_EMIT("movups      %%xmm4, 0x00(%[x])")
438             __ASM_EMIT("movups      %%xmm12, 0x10(%[x])")
439             __ASM_EMIT("movups      %%xmm6, 0x00(%[y])")
440             __ASM_EMIT("movups      %%xmm14, 0x10(%[y])")
441             __ASM_EMIT("add         $0x20, %[x]")
442             __ASM_EMIT("add         $0x20, %[y]")
443             __ASM_EMIT("sub         $8, %[count]")
444             __ASM_EMIT("jae         1b")
445 
446             __ASM_EMIT("2:")
447             __ASM_EMIT("add         $4, %[count]")
448             __ASM_EMIT("jl          4f")
449             // Do x4 block
450             __ASM_EMIT("movups      (%[v]), %%xmm3")                // xmm3 = v
451             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
452             __ASM_EMIT("add         $0x10, %[v]")                   // v   += 4
453             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
454             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
455             // Step 2: parse float value
456             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
457             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
458             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
459             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
460             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
461             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
462             // Prepare logarithm approximation calculations
463             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
464             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
465             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
466             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
467             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
468             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
469             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
470             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
471             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
472             // Calculate logarithmic values
473             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
474             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = L0*A
475             __ASM_EMIT("addps       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
476             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
477             __ASM_EMIT("addps       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
478             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
479             __ASM_EMIT("addps       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
480             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
481             __ASM_EMIT("addps       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
482             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
483             __ASM_EMIT("addps       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
484             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
485             __ASM_EMIT("addps       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
486             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
487             __ASM_EMIT("addps       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
488             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
489             __ASM_EMIT("addps       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
490             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
491             __ASM_EMIT("addps       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
492             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
493             __ASM_EMIT("mulps       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
494             __ASM_EMIT("mulps       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
495             __ASM_EMIT("addps       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
496             __ASM_EMIT("addps       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
497             // Apply values to axes
498             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
499             __ASM_EMIT("movups      (%[x]), %%xmm4")                // xmm4 = x
500             __ASM_EMIT("movups      (%[y]), %%xmm6")                // xmm6 = y
501             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
502             __ASM_EMIT("mulps       %%xmm2, %%xmm5")                // xmm5 = log(abs(v*zero)) * norm_y
503             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
504             __ASM_EMIT("addps       %%xmm5, %%xmm6")                // xmm6 = y + log(abs(v*zero)) * norm_y
505             __ASM_EMIT("movups      %%xmm4, (%[x])")
506             __ASM_EMIT("movups      %%xmm6, (%[y])")
507             __ASM_EMIT("add         $0x10, %[x]")
508             __ASM_EMIT("add         $0x10, %[y]")
509             __ASM_EMIT("sub         $4, %[count]")
510 
511             __ASM_EMIT("4:")
512             __ASM_EMIT("add         $3, %[count]")
513             __ASM_EMIT("jl          6f")
514             // Do x1 blocks
515             __ASM_EMIT("5:")
516             __ASM_EMIT("movss       (%[v]), %%xmm3")                // xmm3 = v
517             __ASM_EMIT("andps       0x00 + %[ILOG], %%xmm3")        // xmm3 = abs(v)
518             __ASM_EMIT("add         $0x04, %[v]")                   // v   += 4
519             __ASM_EMIT("maxps       0x00 + %[FLOG], %%xmm3")        // xmm3 = max(X_AMP, abs(v)), ignores denormalized values
520             __ASM_EMIT("mulps       %%xmm0, %%xmm3")                // xmm5 = max(X_AMP, abs(v)) * zero
521             // Step 2: parse float value
522             __ASM_EMIT("movdqa      %%xmm3, %%xmm4")                // xmm4 = v
523             __ASM_EMIT("psrld       $23, %%xmm4")                   // xmm4 = frac(v)
524             __ASM_EMIT("andps       0x10 + %[ILOG], %%xmm3")        // xmm3 = mant(v)
525             __ASM_EMIT("psubd       0x20 + %[ILOG], %%xmm4")        // xmm4 = frac(v) - 127
526             __ASM_EMIT("orps        0x10 + %[FLOG], %%xmm3")        // xmm3 = V = mant(v)+0.5
527             __ASM_EMIT("cvtdq2ps    %%xmm4, %%xmm4")                // xmm4 = E = float(frac(v)-127)
528             // Prepare logarithm approximation calculations
529             __ASM_EMIT("movaps      %%xmm3, %%xmm5")                // xmm5 = V
530             __ASM_EMIT("movaps      %%xmm3, %%xmm6")                // xmm6 = V
531             __ASM_EMIT("cmpltps     0x20 + %[FLOG], %%xmm5")        // xmm5 = [ V < sqrt(1/2) ]
532             __ASM_EMIT("movaps      0x30 + %[FLOG], %%xmm7")        // xmm7 = 1.0
533             __ASM_EMIT("andps       %%xmm5, %%xmm6")                // xmm6 = V * [ V < sqrt(1/2) ]
534             __ASM_EMIT("addps       %%xmm6, %%xmm3")                // xmm6 = V + V * [ V < sqrt(1/2) ]
535             __ASM_EMIT("andnps      %%xmm7, %%xmm5")                // xmm5 = 1.0 * [ V >= sqrt(1/2) ]
536             __ASM_EMIT("addps       %%xmm5, %%xmm4")                // xmm4 = E + 1.0 * [ V >= sqrt(1/2) ]      = B
537             __ASM_EMIT("subps       %%xmm7, %%xmm3")                // xmm3 = V + V * [ V < sqrt(1/2) ] - 1.0   = A
538             // Calculate logarithmic values
539             __ASM_EMIT("movaps      0x40 + %[FLOG], %%xmm5")        // xmm5 = L0
540             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = L0*A
541             __ASM_EMIT("addss       0x50 + %[FLOG], %%xmm5")        // xmm5 = L1+L0*A
542             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L1+L0*A)
543             __ASM_EMIT("addss       0x60 + %[FLOG], %%xmm5")        // xmm5 = L2+A*(L1+L0*A)
544             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L2+A*(L1+L0*A))
545             __ASM_EMIT("addss       0x70 + %[FLOG], %%xmm5")        // xmm5 = L3+A*L2+A*(L1+L0*A)
546             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L3+A*L2+A*(L1+L0*A))
547             __ASM_EMIT("addss       0x80 + %[FLOG], %%xmm5")        // xmm5 = L4+A*(L3+A*L2+A*(L1+L0*A))
548             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
549             __ASM_EMIT("addss       0x90 + %[FLOG], %%xmm5")        // xmm5 = L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))
550             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
551             __ASM_EMIT("addss       0xa0 + %[FLOG], %%xmm5")        // xmm5 = L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))
552             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
553             __ASM_EMIT("addss       0xb0 + %[FLOG], %%xmm5")        // xmm5 = L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))
554             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
555             __ASM_EMIT("addss       0xc0 + %[FLOG], %%xmm5")        // xmm5 = L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))
556             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
557             __ASM_EMIT("addss       0xd0 + %[FLOG], %%xmm5")        // xmm5 = A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9
558             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
559             __ASM_EMIT("mulss       %%xmm3, %%xmm5")                // xmm5 = A*A*(A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + L9)
560             __ASM_EMIT("mulss       0xe0 + %[FLOG], %%xmm4")        // xmm4 = B*(LXE + LN2)
561             __ASM_EMIT("addss       %%xmm4, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A)))))))
562             __ASM_EMIT("addss       %%xmm3, %%xmm5")                // xmm5 = B*(LXE + LN2) + A*A*A*(L8+A*(L7+A*(L6+A*(L5+A*(L4+A*(L3+A*L2+A*(L1+L0*A))))))) + A
563             // Apply values to axes
564             __ASM_EMIT("movaps      %%xmm5, %%xmm3")                // xmm3 = log(abs(v*zero)), xmm5=log(abs(v*zero))
565             __ASM_EMIT("movss       (%[x]), %%xmm4")                // xmm4 = x
566             __ASM_EMIT("movss       (%[y]), %%xmm6")                // xmm6 = y
567             __ASM_EMIT("mulps       %%xmm1, %%xmm3")                // xmm3 = log(abs(v*zero)) * norm_x
568             __ASM_EMIT("mulps       %%xmm2, %%xmm5")                // xmm5 = log(abs(v*zero)) * norm_y
569             __ASM_EMIT("addps       %%xmm3, %%xmm4")                // xmm4 = x + log(abs(v*zero)) * norm_x
570             __ASM_EMIT("addps       %%xmm5, %%xmm6")                // xmm6 = y + log(abs(v*zero)) * norm_y
571             __ASM_EMIT("movss       %%xmm4, (%[x])")
572             __ASM_EMIT("movss       %%xmm6, (%[y])")
573             __ASM_EMIT("add         $0x04, %[x]")
574             __ASM_EMIT("add         $0x04, %[y]")
575             __ASM_EMIT("dec         %[count]")
576             __ASM_EMIT("jge         5b")
577 
578             __ASM_EMIT("6:")
579             : [v] "+r" (v), [x] "+r" (x) , [y] "+r" (y),
580               [count] "+r" (count)
581             : [zero] "m" (zero), [norm_x] "m" (norm_x), [norm_y] "m" (norm_y),
582               [ILOG] "o" (LOG_IARGS), [FLOG] "o" (LOG_FARGS)
583             :
584               "%xmm0", "%xmm1", "%xmm2", "%xmm3",
585               "%xmm4", "%xmm5", "%xmm6", "%xmm7",
586               "%xmm8", "%xmm9", "%xmm10", "%xmm11",
587               "%xmm12", "%xmm13", "%xmm14", "%xmm15"
588         );
589     }
590 
x64_rgba32_to_bgra32(void * dst,const void * src,size_t count)591     void x64_rgba32_to_bgra32(void *dst, const void *src, size_t count)
592     {
593         IF_ARCH_X86_64(size_t off);
594 
595         ARCH_X86_64_ASM
596         (
597             __ASM_EMIT("movdqa      %[MASK], %%xmm6")                   // xmm6 = 00 ff 00 ff
598             __ASM_EMIT("xor         %[off], %[off]")                    // off  = 0
599             __ASM_EMIT("movdqa      %%xmm6, %%xmm7")                    // xmm7 = 00 ff 00 ff
600             __ASM_EMIT("pslld       $8, %%xmm6")                        // xmm6 = ff 00 ff 00
601 
602             // 16-element blocks
603             __ASM_EMIT("sub         $16, %[count]")
604             __ASM_EMIT("jb          2f")
605             __ASM_EMIT("1:")
606             __ASM_EMIT("prefetcht0  0x40(%[src], %[off])")
607             __ASM_EMIT("prefetcht0  0x60(%[src], %[off])")
608             __ASM_EMIT("movdqu      0x00(%[src], %[off]), %%xmm0")      // xmm0 = A1 R1 G1 B1
609             __ASM_EMIT("movdqu      0x10(%[src], %[off]), %%xmm1")
610             __ASM_EMIT("movdqu      0x20(%[src], %[off]), %%xmm2")
611             __ASM_EMIT("movdqu      0x30(%[src], %[off]), %%xmm3")
612             __ASM_EMIT("movdqa      %%xmm0, %%xmm8")                    // xmm8 = A1 R1 G1 B1
613             __ASM_EMIT("movdqa      %%xmm1, %%xmm10")
614             __ASM_EMIT("movdqa      %%xmm2, %%xmm12")
615             __ASM_EMIT("movdqa      %%xmm3, %%xmm14")
616             __ASM_EMIT("pand        %%xmm7, %%xmm0")                    // xmm0 = 00 R1 00 B1
617             __ASM_EMIT("pand        %%xmm7, %%xmm1")
618             __ASM_EMIT("pand        %%xmm7, %%xmm2")
619             __ASM_EMIT("pand        %%xmm7, %%xmm3")
620             __ASM_EMIT("pand        %%xmm6, %%xmm8")                    // xmm8 = A1 00 G1 00
621             __ASM_EMIT("pand        %%xmm6, %%xmm10")
622             __ASM_EMIT("pand        %%xmm6, %%xmm12")
623             __ASM_EMIT("pand        %%xmm6, %%xmm14")
624             __ASM_EMIT("movdqa      %%xmm0, %%xmm9")                    // xmm9 = A1 00 G1 00
625             __ASM_EMIT("movdqa      %%xmm1, %%xmm11")
626             __ASM_EMIT("movdqa      %%xmm2, %%xmm13")
627             __ASM_EMIT("movdqa      %%xmm3, %%xmm15")
628             __ASM_EMIT("pslld       $16, %%xmm0")                       // xmm0 = 00 B1 00 00
629             __ASM_EMIT("pslld       $16, %%xmm1")
630             __ASM_EMIT("pslld       $16, %%xmm2")
631             __ASM_EMIT("pslld       $16, %%xmm3")
632             __ASM_EMIT("psrld       $16, %%xmm9")                       // xmm9 = 00 00 00 R1
633             __ASM_EMIT("psrld       $16, %%xmm11")
634             __ASM_EMIT("psrld       $16, %%xmm13")
635             __ASM_EMIT("psrld       $16, %%xmm15")
636             __ASM_EMIT("orpd        %%xmm8, %%xmm0")                    // xmm0 = A1 B1 G1 00
637             __ASM_EMIT("orpd        %%xmm10, %%xmm1")
638             __ASM_EMIT("orpd        %%xmm12, %%xmm2")
639             __ASM_EMIT("orpd        %%xmm14, %%xmm3")
640             __ASM_EMIT("orpd        %%xmm9, %%xmm0")                    // xmm0 = A1 B1 G1 R1
641             __ASM_EMIT("orpd        %%xmm11, %%xmm1")
642             __ASM_EMIT("orpd        %%xmm13, %%xmm2")
643             __ASM_EMIT("orpd        %%xmm15, %%xmm3")
644             __ASM_EMIT("movdqu      %%xmm0, 0x00(%[dst], %[off])")
645             __ASM_EMIT("movdqu      %%xmm1, 0x10(%[dst], %[off])")
646             __ASM_EMIT("movdqu      %%xmm2, 0x20(%[dst], %[off])")
647             __ASM_EMIT("movdqu      %%xmm3, 0x30(%[dst], %[off])")
648             __ASM_EMIT("add         $0x40, %[off]")
649             __ASM_EMIT("sub         $16, %[count]")
650             __ASM_EMIT("jae         1b")
651 
652             // 8-element blocks
653             __ASM_EMIT("2:")
654             __ASM_EMIT("add         $8, %[count]")
655             __ASM_EMIT("jl          4f")
656             __ASM_EMIT("movdqu      0x00(%[src], %[off]), %%xmm0")      // xmm0 = A1 R1 G1 B1
657             __ASM_EMIT("movdqu      0x10(%[src], %[off]), %%xmm1")
658             __ASM_EMIT("movdqa      %%xmm0, %%xmm2")                    // xmm2 = A1 R1 G1 B1
659             __ASM_EMIT("movdqa      %%xmm1, %%xmm3")
660             __ASM_EMIT("pand        %%xmm7, %%xmm0")                    // xmm0 = 00 R1 00 B1
661             __ASM_EMIT("pand        %%xmm6, %%xmm2")                    // xmm2 = A1 00 G1 00
662             __ASM_EMIT("pand        %%xmm7, %%xmm1")
663             __ASM_EMIT("pand        %%xmm6, %%xmm3")
664             __ASM_EMIT("movdqa      %%xmm0, %%xmm4")                    // xmm4 = A1 00 G1 00
665             __ASM_EMIT("movdqa      %%xmm1, %%xmm5")
666             __ASM_EMIT("pslld       $16, %%xmm0")                       // xmm0 = 00 B1 00 00
667             __ASM_EMIT("pslld       $16, %%xmm1")
668             __ASM_EMIT("psrld       $16, %%xmm4")                       // xmm4 = 00 00 00 R1
669             __ASM_EMIT("psrld       $16, %%xmm5")
670             __ASM_EMIT("orpd        %%xmm2, %%xmm0")                    // xmm0 = A1 B1 G1 00
671             __ASM_EMIT("orpd        %%xmm3, %%xmm1")
672             __ASM_EMIT("orpd        %%xmm4, %%xmm0")                    // xmm0 = A1 B1 G1 R1
673             __ASM_EMIT("orpd        %%xmm5, %%xmm1")
674             __ASM_EMIT("movdqu      %%xmm0, 0x00(%[dst], %[off])")
675             __ASM_EMIT("movdqu      %%xmm1, 0x10(%[dst], %[off])")
676             __ASM_EMIT("add         $0x20, %[off]")
677             __ASM_EMIT("sub         $8, %[count]")
678 
679             // 4-element block
680             __ASM_EMIT("4:")
681             __ASM_EMIT("add         $4, %[count]")
682             __ASM_EMIT("jl          6f")
683             __ASM_EMIT("movdqu      0x00(%[src], %[off]), %%xmm0")      // xmm0 = A1 R1 G1 B1
684             __ASM_EMIT("movdqa      %%xmm0, %%xmm2")                    // xmm2 = A1 R1 G1 B1
685             __ASM_EMIT("pand        %%xmm7, %%xmm0")                    // xmm0 = 00 R1 00 B1
686             __ASM_EMIT("pand        %%xmm6, %%xmm2")                    // xmm2 = A1 00 G1 00
687             __ASM_EMIT("movdqa      %%xmm0, %%xmm4")                    // xmm4 = A1 00 G1 00
688             __ASM_EMIT("pslld       $16, %%xmm0")                       // xmm0 = 00 B1 00 00
689             __ASM_EMIT("psrld       $16, %%xmm4")                       // xmm4 = 00 00 00 R1
690             __ASM_EMIT("orpd        %%xmm2, %%xmm0")                    // xmm0 = A1 B1 G1 00
691             __ASM_EMIT("orpd        %%xmm4, %%xmm0")                    // xmm0 = A1 B1 G1 R1
692             __ASM_EMIT("movdqu      %%xmm0, 0x00(%[dst], %[off])")
693             __ASM_EMIT("add         $0x10, %[off]")
694             __ASM_EMIT("sub         $4, %[count]")
695 
696             // Tail
697             __ASM_EMIT("6:")
698             __ASM_EMIT("add         $3, %[count]")
699             __ASM_EMIT("jl          8f")
700             __ASM_EMIT("7:")
701             __ASM_EMIT("movd        0x00(%[src], %[off]), %%xmm0")      // xmm0 = AA RR GG BB
702             __ASM_EMIT("movdqa      %%xmm0, %%xmm1")                    // xmm1 = AA RR GG BB
703             __ASM_EMIT("pand        %%xmm7, %%xmm0")                    // xmm0 = 00 RR 00 BB
704             __ASM_EMIT("pand        %%xmm6, %%xmm1")                    // xmm1 = AA 00 GG 00
705             __ASM_EMIT("movdqa      %%xmm0, %%xmm2")                    // xmm2 = 00 RR 00 BB
706             __ASM_EMIT("pslld       $16, %%xmm0")                       // xmm0 = 00 BB 00 00
707             __ASM_EMIT("psrld       $16, %%xmm2")                       // xmm2 = 00 00 00 RR
708             __ASM_EMIT("orpd        %%xmm1, %%xmm0")                    // xmm0 = AA 00 GG RR
709             __ASM_EMIT("orpd        %%xmm2, %%xmm0")                    // xmm0 = AA BB GG RR
710             __ASM_EMIT("movd        %%xmm0, 0x00(%[dst], %[off])")
711             __ASM_EMIT("add         $4, %[off]")
712             __ASM_EMIT("dec         %[count]")
713             __ASM_EMIT("jge         7b")
714 
715             // End
716             __ASM_EMIT("8:")
717 
718             : [dst] "+r"(dst), [src] "+r"(src), [count] "+r" (count),
719               [off] "=&r" (off)
720             : [MASK] "m" (X_CMASK)
721             : "cc", "memory",
722               "%xmm0", "%xmm1", "%xmm2", "%xmm3",
723               "%xmm4", "%xmm5", "%xmm6", "%xmm7",
724               "%xmm8", "%xmm9", "%xmm10", "%xmm11",
725               "%xmm12", "%xmm13", "%xmm14", "%xmm15"
726         );
727     }
728 }
729 
730 #endif /* DSP_ARCH_X86_SSE3_GRAPHICS_H_ */
731