Imported Upstream version 2.0.1
[platform/upstream/libjpeg-turbo.git] / simd / x86_64 / jccolext-avx2.asm
1 ;
2 ; jccolext.asm - colorspace conversion (64-bit AVX2)
3 ;
4 ; Copyright (C) 2009, 2016, D. R. Commander.
5 ; Copyright (C) 2015, Intel Corporation.
6 ;
7 ; Based on the x86 SIMD extension for IJG JPEG library
8 ; Copyright (C) 1999-2006, MIYASAKA Masaru.
9 ; For conditions of distribution and use, see copyright notice in jsimdext.inc
10 ;
11 ; This file should be assembled with NASM (Netwide Assembler),
12 ; can *not* be assembled with Microsoft's MASM or any compatible
13 ; assembler (including Borland's Turbo Assembler).
14 ; NASM is available from http://nasm.sourceforge.net/ or
15 ; http://sourceforge.net/project/showfiles.php?group_id=6208
16 ;
17 ; [TAB8]
18
19 %include "jcolsamp.inc"
20
21 ; --------------------------------------------------------------------------
22 ;
23 ; Convert some rows of samples to the output colorspace.
24 ;
25 ; GLOBAL(void)
26 ; jsimd_rgb_ycc_convert_avx2(JDIMENSION img_width, JSAMPARRAY input_buf,
27 ;                            JSAMPIMAGE output_buf, JDIMENSION output_row,
28 ;                            int num_rows);
29 ;
30
31 ; r10d = JDIMENSION img_width
32 ; r11 = JSAMPARRAY input_buf
33 ; r12 = JSAMPIMAGE output_buf
34 ; r13d = JDIMENSION output_row
35 ; r14d = int num_rows
36
37 %define wk(i)   rbp - (WK_NUM - (i)) * SIZEOF_YMMWORD  ; ymmword wk[WK_NUM]
38 %define WK_NUM  8
39
40     align       32
41     GLOBAL_FUNCTION(jsimd_rgb_ycc_convert_avx2)
42
43 EXTN(jsimd_rgb_ycc_convert_avx2):
44     push        rbp
45     mov         rax, rsp                     ; rax = original rbp
46     sub         rsp, byte 4
47     and         rsp, byte (-SIZEOF_YMMWORD)  ; align to 256 bits
48     mov         [rsp], rax
49     mov         rbp, rsp                     ; rbp = aligned rbp
50     lea         rsp, [wk(0)]
51     collect_args 5
52     push        rbx
53
54     mov         ecx, r10d
55     test        rcx, rcx
56     jz          near .return
57
58     push        rcx
59
60     mov         rsi, r12
61     mov         ecx, r13d
62     mov         rdi, JSAMPARRAY [rsi+0*SIZEOF_JSAMPARRAY]
63     mov         rbx, JSAMPARRAY [rsi+1*SIZEOF_JSAMPARRAY]
64     mov         rdx, JSAMPARRAY [rsi+2*SIZEOF_JSAMPARRAY]
65     lea         rdi, [rdi+rcx*SIZEOF_JSAMPROW]
66     lea         rbx, [rbx+rcx*SIZEOF_JSAMPROW]
67     lea         rdx, [rdx+rcx*SIZEOF_JSAMPROW]
68
69     pop         rcx
70
71     mov         rsi, r11
72     mov         eax, r14d
73     test        rax, rax
74     jle         near .return
75 .rowloop:
76     push        rdx
77     push        rbx
78     push        rdi
79     push        rsi
80     push        rcx                     ; col
81
82     mov         rsi, JSAMPROW [rsi]     ; inptr
83     mov         rdi, JSAMPROW [rdi]     ; outptr0
84     mov         rbx, JSAMPROW [rbx]     ; outptr1
85     mov         rdx, JSAMPROW [rdx]     ; outptr2
86
87     cmp         rcx, byte SIZEOF_YMMWORD
88     jae         near .columnloop
89
90 %if RGB_PIXELSIZE == 3  ; ---------------
91
92 .column_ld1:
93     push        rax
94     push        rdx
95     lea         rcx, [rcx+rcx*2]        ; imul ecx,RGB_PIXELSIZE
96     test        cl, SIZEOF_BYTE
97     jz          short .column_ld2
98     sub         rcx, byte SIZEOF_BYTE
99     movzx       rax, BYTE [rsi+rcx]
100 .column_ld2:
101     test        cl, SIZEOF_WORD
102     jz          short .column_ld4
103     sub         rcx, byte SIZEOF_WORD
104     movzx       rdx, WORD [rsi+rcx]
105     shl         rax, WORD_BIT
106     or          rax, rdx
107 .column_ld4:
108     vmovd       xmmA, eax
109     pop         rdx
110     pop         rax
111     test        cl, SIZEOF_DWORD
112     jz          short .column_ld8
113     sub         rcx, byte SIZEOF_DWORD
114     vmovd       xmmF, XMM_DWORD [rsi+rcx]
115     vpslldq     xmmA, xmmA, SIZEOF_DWORD
116     vpor        xmmA, xmmA, xmmF
117 .column_ld8:
118     test        cl, SIZEOF_MMWORD
119     jz          short .column_ld16
120     sub         rcx, byte SIZEOF_MMWORD
121     vmovq       xmmB, XMM_MMWORD [rsi+rcx]
122     vpslldq     xmmA, xmmA, SIZEOF_MMWORD
123     vpor        xmmA, xmmA, xmmB
124 .column_ld16:
125     test        cl, SIZEOF_XMMWORD
126     jz          short .column_ld32
127     sub         rcx, byte SIZEOF_XMMWORD
128     vmovdqu     xmmB, XMM_MMWORD [rsi+rcx]
129     vperm2i128  ymmA, ymmA, ymmA, 1
130     vpor        ymmA, ymmB
131 .column_ld32:
132     test        cl, SIZEOF_YMMWORD
133     jz          short .column_ld64
134     sub         rcx, byte SIZEOF_YMMWORD
135     vmovdqa     ymmF, ymmA
136     vmovdqu     ymmA, YMMWORD [rsi+0*SIZEOF_YMMWORD]
137 .column_ld64:
138     test        cl, 2*SIZEOF_YMMWORD
139     mov         rcx, SIZEOF_YMMWORD
140     jz          short .rgb_ycc_cnv
141     vmovdqa     ymmB, ymmA
142     vmovdqu     ymmA, YMMWORD [rsi+0*SIZEOF_YMMWORD]
143     vmovdqu     ymmF, YMMWORD [rsi+1*SIZEOF_YMMWORD]
144     jmp         short .rgb_ycc_cnv
145
146 .columnloop:
147     vmovdqu     ymmA, YMMWORD [rsi+0*SIZEOF_YMMWORD]
148     vmovdqu     ymmF, YMMWORD [rsi+1*SIZEOF_YMMWORD]
149     vmovdqu     ymmB, YMMWORD [rsi+2*SIZEOF_YMMWORD]
150
151 .rgb_ycc_cnv:
152     ; ymmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05
153     ;       15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
154     ; ymmF=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F
155     ;       0G 1G 2G 0H 1H 2H 0I 1I 2I 0J 1J 2J 0K 1K 2K 0L)
156     ; ymmB=(1L 2L 0M 1M 2M 0N 1N 2N 0O 1O 2O 0P 1P 2P 0Q 1Q
157     ;       2Q 0R 1R 2R 0S 1S 2S 0T 1T 2T 0U 1U 2U 0V 1V 2V)
158
159     vmovdqu     ymmC, ymmA
160     vinserti128 ymmA, ymmF, xmmA, 0  ; ymmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05
161                                      ;       0G 1G 2G 0H 1H 2H 0I 1I 2I 0J 1J 2J 0K 1K 2K 0L)
162     vinserti128 ymmC, ymmC, xmmB, 0  ; ymmC=(1L 2L 0M 1M 2M 0N 1N 2N 0O 1O 2O 0P 1P 2P 0Q 1Q
163                                      ;       15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
164     vinserti128 ymmB, ymmB, xmmF, 0  ; ymmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F
165                                      ;       2Q 0R 1R 2R 0S 1S 2S 0T 1T 2T 0U 1U 2U 0V 1V 2V)
166     vperm2i128  ymmF, ymmC, ymmC, 1  ; ymmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A
167                                      ;       1L 2L 0M 1M 2M 0N 1N 2N 0O 1O 2O 0P 1P 2P 0Q 1Q)
168
169     vmovdqa     ymmG, ymmA
170     vpslldq     ymmA, ymmA, 8     ; ymmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12
171                                   ;       22 03 13 23 04 14 24 05 0G 1G 2G 0H 1H 2H 0I 1I)
172     vpsrldq     ymmG, ymmG, 8     ; ymmG=(22 03 13 23 04 14 24 05 0G 1G 2G 0H 1H 2H 0I 1I
173                                   ;       2I 0J 1J 2J 0K 1K 2K 0L -- -- -- -- -- -- -- --)
174
175     vpunpckhbw  ymmA, ymmA, ymmF  ; ymmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A
176                                   ;       0G 0O 1G 1O 2G 2O 0H 0P 1H 1P 2H 2P 0I 0Q 1I 1Q)
177     vpslldq     ymmF, ymmF, 8     ; ymmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27
178                                   ;       08 18 28 09 19 29 0A 1A 1L 2L 0M 1M 2M 0N 1N 2N)
179
180     vpunpcklbw  ymmG, ymmG, ymmB  ; ymmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D
181                                   ;       2I 2Q 0J 0R 1J 1R 2J 2R 0K 0S 1K 1S 2K 2S 0L 0T)
182     vpunpckhbw  ymmF, ymmF, ymmB  ; ymmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F
183                                   ;       1L 1T 2L 2T 0M 0U 1M 1U 2M 2U 0N 0V 1N 1V 2N 2V)
184
185     vmovdqa     ymmD, ymmA
186     vpslldq     ymmA, ymmA, 8     ; ymmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09
187                                   ;       11 19 21 29 02 0A 12 1A 0G 0O 1G 1O 2G 2O 0H 0P)
188     vpsrldq     ymmD, ymmD, 8     ; ymmD=(11 19 21 29 02 0A 12 1A 0G 0O 1G 1O 2G 2O 0H 0P
189                                   ;       1H 1P 2H 2P 0I 0Q 1I 1Q -- -- -- -- -- -- -- --)
190
191     vpunpckhbw  ymmA, ymmA, ymmG  ; ymmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D
192                                   ;       0G 0K 0O 0S 1G 1K 1O 1S 2G 2K 2O 2S 0H 0L 0P 0T)
193     vpslldq     ymmG, ymmG, 8     ; ymmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B
194                                   ;       04 0C 14 1C 24 2C 05 0D 2I 2Q 0J 0R 1J 1R 2J 2R)
195
196     vpunpcklbw  ymmD, ymmD, ymmF  ; ymmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E
197                                   ;       1H 1L 1P 1T 2H 2L 2P 2T 0I 0M 0Q 0U 1I 1M 1Q 1U)
198     vpunpckhbw  ymmG, ymmG, ymmF  ; ymmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F
199                                   ;       2I 2M 2Q 2U 0J 0N 0R 0V 1J 1N 1R 1V 2J 2N 2R 2V)
200
201     vmovdqa     ymmE, ymmA
202     vpslldq     ymmA, ymmA, 8     ; ymmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C
203                                   ;       20 24 28 2C 01 05 09 0D 0G 0K 0O 0S 1G 1K 1O 1S)
204     vpsrldq     ymmE, ymmE, 8     ; ymmE=(20 24 28 2C 01 05 09 0D 0G 0K 0O 0S 1G 1K 1O 1S
205                                   ;       2G 2K 2O 2S 0H 0L 0P 0T -- -- -- -- -- -- -- --)
206
207     vpunpckhbw  ymmA, ymmA, ymmD  ; ymmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E
208                                   ;       0G 0I 0K 0M 0O 0Q 0S 0U 1G 1I 1K 1M 1O 1Q 1S 1U)
209     vpslldq     ymmD, ymmD, 8     ; ymmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D
210                                   ;       02 06 0A 0E 12 16 1A 1E 1H 1L 1P 1T 2H 2L 2P 2T)
211
212     vpunpcklbw  ymmE, ymmE, ymmG  ; ymmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F
213                                   ;       2G 2I 2K 2M 2O 2Q 2S 2U 0H 0J 0L 0N 0P 0R 0T 0V)
214     vpunpckhbw  ymmD, ymmD, ymmG  ; ymmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F
215                                   ;       1H 1J 1L 1N 1P 1R 1T 1V 2H 2J 2L 2N 2P 2R 2T 2V)
216
217     vpxor       ymmH, ymmH, ymmH
218
219     vmovdqa     ymmC, ymmA
220     vpunpcklbw  ymmA, ymmA, ymmH  ; ymmA=(00 02 04 06 08 0A 0C 0E 0G 0I 0K 0M 0O 0Q 0S 0U)
221     vpunpckhbw  ymmC, ymmC, ymmH  ; ymmC=(10 12 14 16 18 1A 1C 1E 1G 1I 1K 1M 1O 1Q 1S 1U)
222
223     vmovdqa     ymmB, ymmE
224     vpunpcklbw  ymmE, ymmE, ymmH  ; ymmE=(20 22 24 26 28 2A 2C 2E 2G 2I 2K 2M 2O 2Q 2S 2U)
225     vpunpckhbw  ymmB, ymmB, ymmH  ; ymmB=(01 03 05 07 09 0B 0D 0F 0H 0J 0L 0N 0P 0R 0T 0V)
226
227     vmovdqa     ymmF, ymmD
228     vpunpcklbw  ymmD, ymmD, ymmH  ; ymmD=(11 13 15 17 19 1B 1D 1F 1H 1J 1L 1N 1P 1R 1T 1V)
229     vpunpckhbw  ymmF, ymmF, ymmH  ; ymmF=(21 23 25 27 29 2B 2D 2F 2H 2J 2L 2N 2P 2R 2T 2V)
230
231 %else  ; RGB_PIXELSIZE == 4 ; -----------
232
233 .column_ld1:
234     test        cl, SIZEOF_XMMWORD/16
235     jz          short .column_ld2
236     sub         rcx, byte SIZEOF_XMMWORD/16
237     vmovd       xmmA, XMM_DWORD [rsi+rcx*RGB_PIXELSIZE]
238 .column_ld2:
239     test        cl, SIZEOF_XMMWORD/8
240     jz          short .column_ld4
241     sub         rcx, byte SIZEOF_XMMWORD/8
242     vmovq       xmmF, XMM_MMWORD [rsi+rcx*RGB_PIXELSIZE]
243     vpslldq     xmmA, xmmA, SIZEOF_MMWORD
244     vpor        xmmA, xmmA, xmmF
245 .column_ld4:
246     test        cl, SIZEOF_XMMWORD/4
247     jz          short .column_ld8
248     sub         rcx, byte SIZEOF_XMMWORD/4
249     vmovdqa     xmmF, xmmA
250     vperm2i128  ymmF, ymmF, ymmF, 1
251     vmovdqu     xmmA, XMMWORD [rsi+rcx*RGB_PIXELSIZE]
252     vpor        ymmA, ymmA, ymmF
253 .column_ld8:
254     test        cl, SIZEOF_XMMWORD/2
255     jz          short .column_ld16
256     sub         rcx, byte SIZEOF_XMMWORD/2
257     vmovdqa     ymmF, ymmA
258     vmovdqu     ymmA, YMMWORD [rsi+rcx*RGB_PIXELSIZE]
259 .column_ld16:
260     test        cl, SIZEOF_XMMWORD
261     mov         rcx, SIZEOF_YMMWORD
262     jz          short .rgb_ycc_cnv
263     vmovdqa     ymmE, ymmA
264     vmovdqa     ymmH, ymmF
265     vmovdqu     ymmA, YMMWORD [rsi+0*SIZEOF_YMMWORD]
266     vmovdqu     ymmF, YMMWORD [rsi+1*SIZEOF_YMMWORD]
267     jmp         short .rgb_ycc_cnv
268
269 .columnloop:
270     vmovdqu     ymmA, YMMWORD [rsi+0*SIZEOF_YMMWORD]
271     vmovdqu     ymmF, YMMWORD [rsi+1*SIZEOF_YMMWORD]
272     vmovdqu     ymmE, YMMWORD [rsi+2*SIZEOF_YMMWORD]
273     vmovdqu     ymmH, YMMWORD [rsi+3*SIZEOF_YMMWORD]
274
275 .rgb_ycc_cnv:
276     ; ymmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33
277     ;       04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37)
278     ; ymmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B
279     ;       0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F)
280     ; ymmE=(0G 1G 2G 3G 0H 1H 2H 3H 0I 1I 2I 3I 0J 1J 2J 3J
281     ;       0K 1K 2K 3K 0L 1L 2L 3L 0M 1M 2M 3M 0N 1N 2N 3N)
282     ; ymmH=(0O 1O 2O 3O 0P 1P 2P 3P 0Q 1Q 2Q 3Q 0R 1R 2R 3R
283     ;       0S 1S 2S 3S 0T 1T 2T 3T 0U 1U 2U 3U 0V 1V 2V 3V)
284
285     vmovdqa     ymmB, ymmA
286     vinserti128 ymmA, ymmA, xmmE, 1     ; ymmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33
287                                         ;       0G 1G 2G 3G 0H 1H 2H 3H 0I 1I 2I 3I 0J 1J 2J 3J)
288     vperm2i128  ymmE, ymmB, ymmE, 0x31  ; ymmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37
289                                         ;       0K 1K 2K 3K 0L 1L 2L 3L 0M 1M 2M 3M 0N 1N 2N 3N)
290
291     vmovdqa     ymmB, ymmF
292     vinserti128 ymmF, ymmF, xmmH, 1     ; ymmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B
293                                         ;       0O 1O 2O 3O 0P 1P 2P 3P 0Q 1Q 2Q 3Q 0R 1R 2R 3R)
294     vperm2i128  ymmH, ymmB, ymmH, 0x31  ; ymmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F
295                                         ;       0S 1S 2S 3S 0T 1T 2T 3T 0U 1U 2U 3U 0V 1V 2V 3V)
296
297     vmovdqa     ymmD, ymmA
298     vpunpcklbw  ymmA, ymmA, ymmE      ; ymmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35
299                                       ;       0G 0K 1G 1K 2G 2K 3G 3K 0H 0L 1H 1L 2H 2L 3H 3L)
300     vpunpckhbw  ymmD, ymmD, ymmE      ; ymmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37
301                                       ;       0I 0M 1I 1M 2I 2M 3I 3M 0J 0N 1J 1N 2J 2N 3J 3N)
302
303     vmovdqa     ymmC, ymmF
304     vpunpcklbw  ymmF, ymmF, ymmH      ; ymmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D
305                                       ;       0O 0S 1O 1S 2O 2S 3O 3S 0P 0T 1P 1T 2P 2T 3P 3T)
306     vpunpckhbw  ymmC, ymmC, ymmH      ; ymmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F
307                                       ;       0Q 0U 1Q 1U 2Q 2U 3Q 3U 0R 0V 1R 1V 2R 2V 3R 3V)
308
309     vmovdqa     ymmB, ymmA
310     vpunpcklwd  ymmA, ymmA, ymmF      ; ymmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C
311                                       ;       0G 0K 0O 0S 1G 1K 1O 1S 2G 2K 2O 2S 3G 3K 3O 3S)
312     vpunpckhwd  ymmB, ymmB, ymmF      ; ymmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D
313                                       ;       0H 0L 0P 0T 1H 1L 1P 1T 2H 2L 2P 2T 3H 3L 3P 3T)
314
315     vmovdqa     ymmG, ymmD
316     vpunpcklwd  ymmD, ymmD, ymmC      ; ymmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E
317                                       ;       0I 0M 0Q 0U 1I 1M 1Q 1U 2I 2M 2Q 2U 3I 3M 3Q 3U)
318     vpunpckhwd  ymmG, ymmG, ymmC      ; ymmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F
319                                       ;       0J 0N 0R 0V 1J 1N 1R 1V 2J 2N 2R 2V 3J 3N 3R 3V)
320
321     vmovdqa     ymmE, ymmA
322     vpunpcklbw  ymmA, ymmA, ymmD      ; ymmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E
323                                       ;       0G 0I 0K 0M 0O 0Q 0S 0U 1G 1I 1K 1M 1O 1Q 1S 1U)
324     vpunpckhbw  ymmE, ymmE, ymmD      ; ymmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E
325                                       ;       2G 2I 2K 2M 2O 2Q 2S 2U 3G 3I 3K 3M 3O 3Q 3S 3U)
326
327     vmovdqa     ymmH, ymmB
328     vpunpcklbw  ymmB, ymmB, ymmG      ; ymmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F
329                                       ;       0H 0J 0L 0N 0P 0R 0T 0V 1H 1J 1L 1N 1P 1R 1T 1V)
330     vpunpckhbw  ymmH, ymmH, ymmG      ; ymmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F
331                                       ;       2H 2J 2L 2N 2P 2R 2T 2V 3H 3J 3L 3N 3P 3R 3T 3V)
332
333     vpxor       ymmF, ymmF, ymmF
334
335     vmovdqa     ymmC, ymmA
336     vpunpcklbw  ymmA, ymmA, ymmF      ; ymmA=(00 02 04 06 08 0A 0C 0E 0G 0I 0K 0M 0O 0Q 0S 0U)
337     vpunpckhbw  ymmC, ymmC, ymmF      ; ymmC=(10 12 14 16 18 1A 1C 1E 1G 1I 1K 1M 1O 1Q 1S 1U)
338
339     vmovdqa     ymmD, ymmB
340     vpunpcklbw  ymmB, ymmB, ymmF      ; ymmB=(01 03 05 07 09 0B 0D 0F 0H 0J 0L 0N 0P 0R 0T 0V)
341     vpunpckhbw  ymmD, ymmD, ymmF      ; ymmD=(11 13 15 17 19 1B 1D 1F 1H 1J 1L 1N 1P 1R 1T 1V)
342
343     vmovdqa     ymmG, ymmE
344     vpunpcklbw  ymmE, ymmE, ymmF      ; ymmE=(20 22 24 26 28 2A 2C 2E 2G 2I 2K 2M 2O 2Q 2S 2U)
345     vpunpckhbw  ymmG, ymmG, ymmF      ; ymmG=(30 32 34 36 38 3A 3C 3E 3G 3I 3K 3M 3O 3Q 3S 3U)
346
347     vpunpcklbw  ymmF, ymmF, ymmH
348     vpunpckhbw  ymmH, ymmH, ymmH
349     vpsrlw      ymmF, ymmF, BYTE_BIT  ; ymmF=(21 23 25 27 29 2B 2D 2F 2H 2J 2L 2N 2P 2R 2T 2V)
350     vpsrlw      ymmH, ymmH, BYTE_BIT  ; ymmH=(31 33 35 37 39 3B 3D 3F 3H 3J 3L 3N 3P 3R 3T 3V)
351
352 %endif  ; RGB_PIXELSIZE ; ---------------
353
354     ; ymm0=R(02468ACEGIKMOQSU)=RE, ymm2=G(02468ACEGIKMOQSU)=GE, ymm4=B(02468ACEGIKMOQSU)=BE
355     ; ymm1=R(13579BDFHJLNPRTV)=RO, ymm3=G(13579BDFHJLNPRTV)=GO, ymm5=B(13579BDFHJLNPRTV)=BO
356
357     ; (Original)
358     ; Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
359     ; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
360     ; Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
361     ;
362     ; (This implementation)
363     ; Y  =  0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
364     ; Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
365     ; Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
366
367     vmovdqa     YMMWORD [wk(0)], ymm0   ; wk(0)=RE
368     vmovdqa     YMMWORD [wk(1)], ymm1   ; wk(1)=RO
369     vmovdqa     YMMWORD [wk(2)], ymm4   ; wk(2)=BE
370     vmovdqa     YMMWORD [wk(3)], ymm5   ; wk(3)=BO
371
372     vmovdqa     ymm6, ymm1
373     vpunpcklwd  ymm1, ymm1, ymm3
374     vpunpckhwd  ymm6, ymm6, ymm3
375     vmovdqa     ymm7, ymm1
376     vmovdqa     ymm4, ymm6
377     vpmaddwd    ymm1, ymm1, [rel PW_F0299_F0337]  ; ymm1=ROL*FIX(0.299)+GOL*FIX(0.337)
378     vpmaddwd    ymm6, ymm6, [rel PW_F0299_F0337]  ; ymm6=ROH*FIX(0.299)+GOH*FIX(0.337)
379     vpmaddwd    ymm7, ymm7, [rel PW_MF016_MF033]  ; ymm7=ROL*-FIX(0.168)+GOL*-FIX(0.331)
380     vpmaddwd    ymm4, ymm4, [rel PW_MF016_MF033]  ; ymm4=ROH*-FIX(0.168)+GOH*-FIX(0.331)
381
382     vmovdqa     YMMWORD [wk(4)], ymm1   ; wk(4)=ROL*FIX(0.299)+GOL*FIX(0.337)
383     vmovdqa     YMMWORD [wk(5)], ymm6   ; wk(5)=ROH*FIX(0.299)+GOH*FIX(0.337)
384
385     vpxor       ymm1, ymm1, ymm1
386     vpxor       ymm6, ymm6, ymm6
387     vpunpcklwd  ymm1, ymm1, ymm5        ; ymm1=BOL
388     vpunpckhwd  ymm6, ymm6, ymm5        ; ymm6=BOH
389     vpsrld      ymm1, ymm1, 1           ; ymm1=BOL*FIX(0.500)
390     vpsrld      ymm6, ymm6, 1           ; ymm6=BOH*FIX(0.500)
391
392     vmovdqa     ymm5, [rel PD_ONEHALFM1_CJ]  ; ymm5=[PD_ONEHALFM1_CJ]
393
394     vpaddd      ymm7, ymm7, ymm1
395     vpaddd      ymm4, ymm4, ymm6
396     vpaddd      ymm7, ymm7, ymm5
397     vpaddd      ymm4, ymm4, ymm5
398     vpsrld      ymm7, ymm7, SCALEBITS   ; ymm7=CbOL
399     vpsrld      ymm4, ymm4, SCALEBITS   ; ymm4=CbOH
400     vpackssdw   ymm7, ymm7, ymm4        ; ymm7=CbO
401
402     vmovdqa     ymm1, YMMWORD [wk(2)]   ; ymm1=BE
403
404     vmovdqa     ymm6, ymm0
405     vpunpcklwd  ymm0, ymm0, ymm2
406     vpunpckhwd  ymm6, ymm6, ymm2
407     vmovdqa     ymm5, ymm0
408     vmovdqa     ymm4, ymm6
409     vpmaddwd    ymm0, ymm0, [rel PW_F0299_F0337]  ; ymm0=REL*FIX(0.299)+GEL*FIX(0.337)
410     vpmaddwd    ymm6, ymm6, [rel PW_F0299_F0337]  ; ymm6=REH*FIX(0.299)+GEH*FIX(0.337)
411     vpmaddwd    ymm5, ymm5, [rel PW_MF016_MF033]  ; ymm5=REL*-FIX(0.168)+GEL*-FIX(0.331)
412     vpmaddwd    ymm4, ymm4, [rel PW_MF016_MF033]  ; ymm4=REH*-FIX(0.168)+GEH*-FIX(0.331)
413
414     vmovdqa     YMMWORD [wk(6)], ymm0   ; wk(6)=REL*FIX(0.299)+GEL*FIX(0.337)
415     vmovdqa     YMMWORD [wk(7)], ymm6   ; wk(7)=REH*FIX(0.299)+GEH*FIX(0.337)
416
417     vpxor       ymm0, ymm0, ymm0
418     vpxor       ymm6, ymm6, ymm6
419     vpunpcklwd  ymm0, ymm0, ymm1        ; ymm0=BEL
420     vpunpckhwd  ymm6, ymm6, ymm1        ; ymm6=BEH
421     vpsrld      ymm0, ymm0, 1           ; ymm0=BEL*FIX(0.500)
422     vpsrld      ymm6, ymm6, 1           ; ymm6=BEH*FIX(0.500)
423
424     vmovdqa     ymm1, [rel PD_ONEHALFM1_CJ]  ; ymm1=[PD_ONEHALFM1_CJ]
425
426     vpaddd      ymm5, ymm5, ymm0
427     vpaddd      ymm4, ymm4, ymm6
428     vpaddd      ymm5, ymm5, ymm1
429     vpaddd      ymm4, ymm4, ymm1
430     vpsrld      ymm5, ymm5, SCALEBITS   ; ymm5=CbEL
431     vpsrld      ymm4, ymm4, SCALEBITS   ; ymm4=CbEH
432     vpackssdw   ymm5, ymm5, ymm4        ; ymm5=CbE
433
434     vpsllw      ymm7, ymm7, BYTE_BIT
435     vpor        ymm5, ymm5, ymm7        ; ymm5=Cb
436     vmovdqu     YMMWORD [rbx], ymm5     ; Save Cb
437
438     vmovdqa     ymm0, YMMWORD [wk(3)]   ; ymm0=BO
439     vmovdqa     ymm6, YMMWORD [wk(2)]   ; ymm6=BE
440     vmovdqa     ymm1, YMMWORD [wk(1)]   ; ymm1=RO
441
442     vmovdqa     ymm4, ymm0
443     vpunpcklwd  ymm0, ymm0, ymm3
444     vpunpckhwd  ymm4, ymm4, ymm3
445     vmovdqa     ymm7, ymm0
446     vmovdqa     ymm5, ymm4
447     vpmaddwd    ymm0, ymm0, [rel PW_F0114_F0250]  ; ymm0=BOL*FIX(0.114)+GOL*FIX(0.250)
448     vpmaddwd    ymm4, ymm4, [rel PW_F0114_F0250]  ; ymm4=BOH*FIX(0.114)+GOH*FIX(0.250)
449     vpmaddwd    ymm7, ymm7, [rel PW_MF008_MF041]  ; ymm7=BOL*-FIX(0.081)+GOL*-FIX(0.418)
450     vpmaddwd    ymm5, ymm5, [rel PW_MF008_MF041]  ; ymm5=BOH*-FIX(0.081)+GOH*-FIX(0.418)
451
452     vmovdqa     ymm3, [rel PD_ONEHALF]            ; ymm3=[PD_ONEHALF]
453
454     vpaddd      ymm0, ymm0, YMMWORD [wk(4)]
455     vpaddd      ymm4, ymm4, YMMWORD [wk(5)]
456     vpaddd      ymm0, ymm0, ymm3
457     vpaddd      ymm4, ymm4, ymm3
458     vpsrld      ymm0, ymm0, SCALEBITS   ; ymm0=YOL
459     vpsrld      ymm4, ymm4, SCALEBITS   ; ymm4=YOH
460     vpackssdw   ymm0, ymm0, ymm4        ; ymm0=YO
461
462     vpxor       ymm3, ymm3, ymm3
463     vpxor       ymm4, ymm4, ymm4
464     vpunpcklwd  ymm3, ymm3, ymm1        ; ymm3=ROL
465     vpunpckhwd  ymm4, ymm4, ymm1        ; ymm4=ROH
466     vpsrld      ymm3, ymm3, 1           ; ymm3=ROL*FIX(0.500)
467     vpsrld      ymm4, ymm4, 1           ; ymm4=ROH*FIX(0.500)
468
469     vmovdqa     ymm1, [rel PD_ONEHALFM1_CJ]  ; ymm1=[PD_ONEHALFM1_CJ]
470
471     vpaddd      ymm7, ymm7, ymm3
472     vpaddd      ymm5, ymm5, ymm4
473     vpaddd      ymm7, ymm7, ymm1
474     vpaddd      ymm5, ymm5, ymm1
475     vpsrld      ymm7, ymm7, SCALEBITS   ; ymm7=CrOL
476     vpsrld      ymm5, ymm5, SCALEBITS   ; ymm5=CrOH
477     vpackssdw   ymm7, ymm7, ymm5        ; ymm7=CrO
478
479     vmovdqa     ymm3, YMMWORD [wk(0)]   ; ymm3=RE
480
481     vmovdqa     ymm4, ymm6
482     vpunpcklwd  ymm6, ymm6, ymm2
483     vpunpckhwd  ymm4, ymm4, ymm2
484     vmovdqa     ymm1, ymm6
485     vmovdqa     ymm5, ymm4
486     vpmaddwd    ymm6, ymm6, [rel PW_F0114_F0250]  ; ymm6=BEL*FIX(0.114)+GEL*FIX(0.250)
487     vpmaddwd    ymm4, ymm4, [rel PW_F0114_F0250]  ; ymm4=BEH*FIX(0.114)+GEH*FIX(0.250)
488     vpmaddwd    ymm1, ymm1, [rel PW_MF008_MF041]  ; ymm1=BEL*-FIX(0.081)+GEL*-FIX(0.418)
489     vpmaddwd    ymm5, ymm5, [rel PW_MF008_MF041]  ; ymm5=BEH*-FIX(0.081)+GEH*-FIX(0.418)
490
491     vmovdqa     ymm2, [rel PD_ONEHALF]            ; ymm2=[PD_ONEHALF]
492
493     vpaddd      ymm6, ymm6, YMMWORD [wk(6)]
494     vpaddd      ymm4, ymm4, YMMWORD [wk(7)]
495     vpaddd      ymm6, ymm6, ymm2
496     vpaddd      ymm4, ymm4, ymm2
497     vpsrld      ymm6, ymm6, SCALEBITS   ; ymm6=YEL
498     vpsrld      ymm4, ymm4, SCALEBITS   ; ymm4=YEH
499     vpackssdw   ymm6, ymm6, ymm4        ; ymm6=YE
500
501     vpsllw      ymm0, ymm0, BYTE_BIT
502     vpor        ymm6, ymm6, ymm0        ; ymm6=Y
503     vmovdqu     YMMWORD [rdi], ymm6     ; Save Y
504
505     vpxor       ymm2, ymm2, ymm2
506     vpxor       ymm4, ymm4, ymm4
507     vpunpcklwd  ymm2, ymm2, ymm3        ; ymm2=REL
508     vpunpckhwd  ymm4, ymm4, ymm3        ; ymm4=REH
509     vpsrld      ymm2, ymm2, 1           ; ymm2=REL*FIX(0.500)
510     vpsrld      ymm4, ymm4, 1           ; ymm4=REH*FIX(0.500)
511
512     vmovdqa     ymm0, [rel PD_ONEHALFM1_CJ]  ; ymm0=[PD_ONEHALFM1_CJ]
513
514     vpaddd      ymm1, ymm1, ymm2
515     vpaddd      ymm5, ymm5, ymm4
516     vpaddd      ymm1, ymm1, ymm0
517     vpaddd      ymm5, ymm5, ymm0
518     vpsrld      ymm1, ymm1, SCALEBITS   ; ymm1=CrEL
519     vpsrld      ymm5, ymm5, SCALEBITS   ; ymm5=CrEH
520     vpackssdw   ymm1, ymm1, ymm5        ; ymm1=CrE
521
522     vpsllw      ymm7, ymm7, BYTE_BIT
523     vpor        ymm1, ymm1, ymm7        ; ymm1=Cr
524     vmovdqu     YMMWORD [rdx], ymm1     ; Save Cr
525
526     sub         rcx, byte SIZEOF_YMMWORD
527     add         rsi, RGB_PIXELSIZE*SIZEOF_YMMWORD  ; inptr
528     add         rdi, byte SIZEOF_YMMWORD           ; outptr0
529     add         rbx, byte SIZEOF_YMMWORD           ; outptr1
530     add         rdx, byte SIZEOF_YMMWORD           ; outptr2
531     cmp         rcx, byte SIZEOF_YMMWORD
532     jae         near .columnloop
533     test        rcx, rcx
534     jnz         near .column_ld1
535
536     pop         rcx                     ; col
537     pop         rsi
538     pop         rdi
539     pop         rbx
540     pop         rdx
541
542     add         rsi, byte SIZEOF_JSAMPROW  ; input_buf
543     add         rdi, byte SIZEOF_JSAMPROW
544     add         rbx, byte SIZEOF_JSAMPROW
545     add         rdx, byte SIZEOF_JSAMPROW
546     dec         rax                        ; num_rows
547     jg          near .rowloop
548
549 .return:
550     pop         rbx
551     vzeroupper
552     uncollect_args 5
553     mov         rsp, rbp                ; rsp <- aligned rbp
554     pop         rsp                     ; rsp <- original rbp
555     pop         rbp
556     ret
557
558 ; For some reason, the OS X linker does not honor the request to align the
559 ; segment unless we do this.
560     align       32