Imported Upstream version 2.0.1
[platform/upstream/libjpeg-turbo.git] / simd / i386 / jidctint-mmx.asm
1 ;
2 ; jidctint.asm - accurate integer IDCT (MMX)
3 ;
4 ; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 ; Copyright (C) 2016, D. R. Commander.
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 ; This file contains a slow-but-accurate integer implementation of the
18 ; inverse DCT (Discrete Cosine Transform). The following code is based
19 ; directly on the IJG's original jidctint.c; see the jidctint.c for
20 ; more details.
21 ;
22 ; [TAB8]
23
24 %include "jsimdext.inc"
25 %include "jdct.inc"
26
27 ; --------------------------------------------------------------------------
28
29 %define CONST_BITS  13
30 %define PASS1_BITS  2
31
32 %define DESCALE_P1  (CONST_BITS - PASS1_BITS)
33 %define DESCALE_P2  (CONST_BITS + PASS1_BITS + 3)
34
35 %if CONST_BITS == 13
36 F_0_298 equ  2446  ; FIX(0.298631336)
37 F_0_390 equ  3196  ; FIX(0.390180644)
38 F_0_541 equ  4433  ; FIX(0.541196100)
39 F_0_765 equ  6270  ; FIX(0.765366865)
40 F_0_899 equ  7373  ; FIX(0.899976223)
41 F_1_175 equ  9633  ; FIX(1.175875602)
42 F_1_501 equ 12299  ; FIX(1.501321110)
43 F_1_847 equ 15137  ; FIX(1.847759065)
44 F_1_961 equ 16069  ; FIX(1.961570560)
45 F_2_053 equ 16819  ; FIX(2.053119869)
46 F_2_562 equ 20995  ; FIX(2.562915447)
47 F_3_072 equ 25172  ; FIX(3.072711026)
48 %else
49 ; NASM cannot do compile-time arithmetic on floating-point constants.
50 %define DESCALE(x, n)  (((x) + (1 << ((n) - 1))) >> (n))
51 F_0_298 equ DESCALE( 320652955, 30 - CONST_BITS)  ; FIX(0.298631336)
52 F_0_390 equ DESCALE( 418953276, 30 - CONST_BITS)  ; FIX(0.390180644)
53 F_0_541 equ DESCALE( 581104887, 30 - CONST_BITS)  ; FIX(0.541196100)
54 F_0_765 equ DESCALE( 821806413, 30 - CONST_BITS)  ; FIX(0.765366865)
55 F_0_899 equ DESCALE( 966342111, 30 - CONST_BITS)  ; FIX(0.899976223)
56 F_1_175 equ DESCALE(1262586813, 30 - CONST_BITS)  ; FIX(1.175875602)
57 F_1_501 equ DESCALE(1612031267, 30 - CONST_BITS)  ; FIX(1.501321110)
58 F_1_847 equ DESCALE(1984016188, 30 - CONST_BITS)  ; FIX(1.847759065)
59 F_1_961 equ DESCALE(2106220350, 30 - CONST_BITS)  ; FIX(1.961570560)
60 F_2_053 equ DESCALE(2204520673, 30 - CONST_BITS)  ; FIX(2.053119869)
61 F_2_562 equ DESCALE(2751909506, 30 - CONST_BITS)  ; FIX(2.562915447)
62 F_3_072 equ DESCALE(3299298341, 30 - CONST_BITS)  ; FIX(3.072711026)
63 %endif
64
65 ; --------------------------------------------------------------------------
66     SECTION     SEG_CONST
67
68     alignz      32
69     GLOBAL_DATA(jconst_idct_islow_mmx)
70
71 EXTN(jconst_idct_islow_mmx):
72
73 PW_F130_F054   times 2 dw  (F_0_541 + F_0_765),  F_0_541
74 PW_F054_MF130  times 2 dw  F_0_541, (F_0_541 - F_1_847)
75 PW_MF078_F117  times 2 dw  (F_1_175 - F_1_961),  F_1_175
76 PW_F117_F078   times 2 dw  F_1_175, (F_1_175 - F_0_390)
77 PW_MF060_MF089 times 2 dw  (F_0_298 - F_0_899), -F_0_899
78 PW_MF089_F060  times 2 dw -F_0_899, (F_1_501 - F_0_899)
79 PW_MF050_MF256 times 2 dw  (F_2_053 - F_2_562), -F_2_562
80 PW_MF256_F050  times 2 dw -F_2_562, (F_3_072 - F_2_562)
81 PD_DESCALE_P1  times 2 dd  1 << (DESCALE_P1 - 1)
82 PD_DESCALE_P2  times 2 dd  1 << (DESCALE_P2 - 1)
83 PB_CENTERJSAMP times 8 db  CENTERJSAMPLE
84
85     alignz      32
86
87 ; --------------------------------------------------------------------------
88     SECTION     SEG_TEXT
89     BITS        32
90 ;
91 ; Perform dequantization and inverse DCT on one block of coefficients.
92 ;
93 ; GLOBAL(void)
94 ; jsimd_idct_islow_mmx(void *dct_table, JCOEFPTR coef_block,
95 ;                      JSAMPARRAY output_buf, JDIMENSION output_col)
96 ;
97
98 %define dct_table(b)   (b) + 8          ; jpeg_component_info *compptr
99 %define coef_block(b)  (b) + 12         ; JCOEFPTR coef_block
100 %define output_buf(b)  (b) + 16         ; JSAMPARRAY output_buf
101 %define output_col(b)  (b) + 20         ; JDIMENSION output_col
102
103 %define original_ebp   ebp + 0
104 %define wk(i)          ebp - (WK_NUM - (i)) * SIZEOF_MMWORD
105                                         ; mmword wk[WK_NUM]
106 %define WK_NUM         12
107 %define workspace      wk(0) - DCTSIZE2 * SIZEOF_JCOEF
108                                         ; JCOEF workspace[DCTSIZE2]
109
110     align       32
111     GLOBAL_FUNCTION(jsimd_idct_islow_mmx)
112
113 EXTN(jsimd_idct_islow_mmx):
114     push        ebp
115     mov         eax, esp                    ; eax = original ebp
116     sub         esp, byte 4
117     and         esp, byte (-SIZEOF_MMWORD)  ; align to 64 bits
118     mov         [esp], eax
119     mov         ebp, esp                    ; ebp = aligned ebp
120     lea         esp, [workspace]
121     push        ebx
122 ;   push        ecx                     ; need not be preserved
123 ;   push        edx                     ; need not be preserved
124     push        esi
125     push        edi
126
127     get_GOT     ebx                     ; get GOT address
128
129     ; ---- Pass 1: process columns from input, store into work array.
130
131 ;   mov         eax, [original_ebp]
132     mov         edx, POINTER [dct_table(eax)]    ; quantptr
133     mov         esi, JCOEFPTR [coef_block(eax)]  ; inptr
134     lea         edi, [workspace]                 ; JCOEF *wsptr
135     mov         ecx, DCTSIZE/4                   ; ctr
136     alignx      16, 7
137 .columnloop:
138 %ifndef NO_ZERO_COLUMN_TEST_ISLOW_MMX
139     mov         eax, DWORD [DWBLOCK(1,0,esi,SIZEOF_JCOEF)]
140     or          eax, DWORD [DWBLOCK(2,0,esi,SIZEOF_JCOEF)]
141     jnz         short .columnDCT
142
143     movq        mm0, MMWORD [MMBLOCK(1,0,esi,SIZEOF_JCOEF)]
144     movq        mm1, MMWORD [MMBLOCK(2,0,esi,SIZEOF_JCOEF)]
145     por         mm0, MMWORD [MMBLOCK(3,0,esi,SIZEOF_JCOEF)]
146     por         mm1, MMWORD [MMBLOCK(4,0,esi,SIZEOF_JCOEF)]
147     por         mm0, MMWORD [MMBLOCK(5,0,esi,SIZEOF_JCOEF)]
148     por         mm1, MMWORD [MMBLOCK(6,0,esi,SIZEOF_JCOEF)]
149     por         mm0, MMWORD [MMBLOCK(7,0,esi,SIZEOF_JCOEF)]
150     por         mm1, mm0
151     packsswb    mm1, mm1
152     movd        eax, mm1
153     test        eax, eax
154     jnz         short .columnDCT
155
156     ; -- AC terms all zero
157
158     movq        mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_JCOEF)]
159     pmullw      mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
160
161     psllw       mm0, PASS1_BITS
162
163     movq        mm2, mm0                ; mm0=in0=(00 01 02 03)
164     punpcklwd   mm0, mm0                ; mm0=(00 00 01 01)
165     punpckhwd   mm2, mm2                ; mm2=(02 02 03 03)
166
167     movq        mm1, mm0
168     punpckldq   mm0, mm0                ; mm0=(00 00 00 00)
169     punpckhdq   mm1, mm1                ; mm1=(01 01 01 01)
170     movq        mm3, mm2
171     punpckldq   mm2, mm2                ; mm2=(02 02 02 02)
172     punpckhdq   mm3, mm3                ; mm3=(03 03 03 03)
173
174     movq        MMWORD [MMBLOCK(0,0,edi,SIZEOF_JCOEF)], mm0
175     movq        MMWORD [MMBLOCK(0,1,edi,SIZEOF_JCOEF)], mm0
176     movq        MMWORD [MMBLOCK(1,0,edi,SIZEOF_JCOEF)], mm1
177     movq        MMWORD [MMBLOCK(1,1,edi,SIZEOF_JCOEF)], mm1
178     movq        MMWORD [MMBLOCK(2,0,edi,SIZEOF_JCOEF)], mm2
179     movq        MMWORD [MMBLOCK(2,1,edi,SIZEOF_JCOEF)], mm2
180     movq        MMWORD [MMBLOCK(3,0,edi,SIZEOF_JCOEF)], mm3
181     movq        MMWORD [MMBLOCK(3,1,edi,SIZEOF_JCOEF)], mm3
182     jmp         near .nextcolumn
183     alignx      16, 7
184 %endif
185 .columnDCT:
186
187     ; -- Even part
188
189     movq        mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_JCOEF)]
190     movq        mm1, MMWORD [MMBLOCK(2,0,esi,SIZEOF_JCOEF)]
191     pmullw      mm0, MMWORD [MMBLOCK(0,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
192     pmullw      mm1, MMWORD [MMBLOCK(2,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
193     movq        mm2, MMWORD [MMBLOCK(4,0,esi,SIZEOF_JCOEF)]
194     movq        mm3, MMWORD [MMBLOCK(6,0,esi,SIZEOF_JCOEF)]
195     pmullw      mm2, MMWORD [MMBLOCK(4,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
196     pmullw      mm3, MMWORD [MMBLOCK(6,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
197
198     ; (Original)
199     ; z1 = (z2 + z3) * 0.541196100;
200     ; tmp2 = z1 + z3 * -1.847759065;
201     ; tmp3 = z1 + z2 * 0.765366865;
202     ;
203     ; (This implementation)
204     ; tmp2 = z2 * 0.541196100 + z3 * (0.541196100 - 1.847759065);
205     ; tmp3 = z2 * (0.541196100 + 0.765366865) + z3 * 0.541196100;
206
207     movq        mm4, mm1                ; mm1=in2=z2
208     movq        mm5, mm1
209     punpcklwd   mm4, mm3                ; mm3=in6=z3
210     punpckhwd   mm5, mm3
211     movq        mm1, mm4
212     movq        mm3, mm5
213     pmaddwd     mm4, [GOTOFF(ebx,PW_F130_F054)]   ; mm4=tmp3L
214     pmaddwd     mm5, [GOTOFF(ebx,PW_F130_F054)]   ; mm5=tmp3H
215     pmaddwd     mm1, [GOTOFF(ebx,PW_F054_MF130)]  ; mm1=tmp2L
216     pmaddwd     mm3, [GOTOFF(ebx,PW_F054_MF130)]  ; mm3=tmp2H
217
218     movq        mm6, mm0
219     paddw       mm0, mm2                ; mm0=in0+in4
220     psubw       mm6, mm2                ; mm6=in0-in4
221
222     pxor        mm7, mm7
223     pxor        mm2, mm2
224     punpcklwd   mm7, mm0                ; mm7=tmp0L
225     punpckhwd   mm2, mm0                ; mm2=tmp0H
226     psrad       mm7, (16-CONST_BITS)    ; psrad mm7,16 & pslld mm7,CONST_BITS
227     psrad       mm2, (16-CONST_BITS)    ; psrad mm2,16 & pslld mm2,CONST_BITS
228
229     movq        mm0, mm7
230     paddd       mm7, mm4                ; mm7=tmp10L
231     psubd       mm0, mm4                ; mm0=tmp13L
232     movq        mm4, mm2
233     paddd       mm2, mm5                ; mm2=tmp10H
234     psubd       mm4, mm5                ; mm4=tmp13H
235
236     movq        MMWORD [wk(0)], mm7     ; wk(0)=tmp10L
237     movq        MMWORD [wk(1)], mm2     ; wk(1)=tmp10H
238     movq        MMWORD [wk(2)], mm0     ; wk(2)=tmp13L
239     movq        MMWORD [wk(3)], mm4     ; wk(3)=tmp13H
240
241     pxor        mm5, mm5
242     pxor        mm7, mm7
243     punpcklwd   mm5, mm6                ; mm5=tmp1L
244     punpckhwd   mm7, mm6                ; mm7=tmp1H
245     psrad       mm5, (16-CONST_BITS)    ; psrad mm5,16 & pslld mm5,CONST_BITS
246     psrad       mm7, (16-CONST_BITS)    ; psrad mm7,16 & pslld mm7,CONST_BITS
247
248     movq        mm2, mm5
249     paddd       mm5, mm1                ; mm5=tmp11L
250     psubd       mm2, mm1                ; mm2=tmp12L
251     movq        mm0, mm7
252     paddd       mm7, mm3                ; mm7=tmp11H
253     psubd       mm0, mm3                ; mm0=tmp12H
254
255     movq        MMWORD [wk(4)], mm5     ; wk(4)=tmp11L
256     movq        MMWORD [wk(5)], mm7     ; wk(5)=tmp11H
257     movq        MMWORD [wk(6)], mm2     ; wk(6)=tmp12L
258     movq        MMWORD [wk(7)], mm0     ; wk(7)=tmp12H
259
260     ; -- Odd part
261
262     movq        mm4, MMWORD [MMBLOCK(1,0,esi,SIZEOF_JCOEF)]
263     movq        mm6, MMWORD [MMBLOCK(3,0,esi,SIZEOF_JCOEF)]
264     pmullw      mm4, MMWORD [MMBLOCK(1,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
265     pmullw      mm6, MMWORD [MMBLOCK(3,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
266     movq        mm1, MMWORD [MMBLOCK(5,0,esi,SIZEOF_JCOEF)]
267     movq        mm3, MMWORD [MMBLOCK(7,0,esi,SIZEOF_JCOEF)]
268     pmullw      mm1, MMWORD [MMBLOCK(5,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
269     pmullw      mm3, MMWORD [MMBLOCK(7,0,edx,SIZEOF_ISLOW_MULT_TYPE)]
270
271     movq        mm5, mm6
272     movq        mm7, mm4
273     paddw       mm5, mm3                ; mm5=z3
274     paddw       mm7, mm1                ; mm7=z4
275
276     ; (Original)
277     ; z5 = (z3 + z4) * 1.175875602;
278     ; z3 = z3 * -1.961570560;  z4 = z4 * -0.390180644;
279     ; z3 += z5;  z4 += z5;
280     ;
281     ; (This implementation)
282     ; z3 = z3 * (1.175875602 - 1.961570560) + z4 * 1.175875602;
283     ; z4 = z3 * 1.175875602 + z4 * (1.175875602 - 0.390180644);
284
285     movq        mm2, mm5
286     movq        mm0, mm5
287     punpcklwd   mm2, mm7
288     punpckhwd   mm0, mm7
289     movq        mm5, mm2
290     movq        mm7, mm0
291     pmaddwd     mm2, [GOTOFF(ebx,PW_MF078_F117)]  ; mm2=z3L
292     pmaddwd     mm0, [GOTOFF(ebx,PW_MF078_F117)]  ; mm0=z3H
293     pmaddwd     mm5, [GOTOFF(ebx,PW_F117_F078)]   ; mm5=z4L
294     pmaddwd     mm7, [GOTOFF(ebx,PW_F117_F078)]   ; mm7=z4H
295
296     movq        MMWORD [wk(10)], mm2    ; wk(10)=z3L
297     movq        MMWORD [wk(11)], mm0    ; wk(11)=z3H
298
299     ; (Original)
300     ; z1 = tmp0 + tmp3;  z2 = tmp1 + tmp2;
301     ; tmp0 = tmp0 * 0.298631336;  tmp1 = tmp1 * 2.053119869;
302     ; tmp2 = tmp2 * 3.072711026;  tmp3 = tmp3 * 1.501321110;
303     ; z1 = z1 * -0.899976223;  z2 = z2 * -2.562915447;
304     ; tmp0 += z1 + z3;  tmp1 += z2 + z4;
305     ; tmp2 += z2 + z3;  tmp3 += z1 + z4;
306     ;
307     ; (This implementation)
308     ; tmp0 = tmp0 * (0.298631336 - 0.899976223) + tmp3 * -0.899976223;
309     ; tmp1 = tmp1 * (2.053119869 - 2.562915447) + tmp2 * -2.562915447;
310     ; tmp2 = tmp1 * -2.562915447 + tmp2 * (3.072711026 - 2.562915447);
311     ; tmp3 = tmp0 * -0.899976223 + tmp3 * (1.501321110 - 0.899976223);
312     ; tmp0 += z3;  tmp1 += z4;
313     ; tmp2 += z3;  tmp3 += z4;
314
315     movq        mm2, mm3
316     movq        mm0, mm3
317     punpcklwd   mm2, mm4
318     punpckhwd   mm0, mm4
319     movq        mm3, mm2
320     movq        mm4, mm0
321     pmaddwd     mm2, [GOTOFF(ebx,PW_MF060_MF089)]  ; mm2=tmp0L
322     pmaddwd     mm0, [GOTOFF(ebx,PW_MF060_MF089)]  ; mm0=tmp0H
323     pmaddwd     mm3, [GOTOFF(ebx,PW_MF089_F060)]   ; mm3=tmp3L
324     pmaddwd     mm4, [GOTOFF(ebx,PW_MF089_F060)]   ; mm4=tmp3H
325
326     paddd       mm2, MMWORD [wk(10)]    ; mm2=tmp0L
327     paddd       mm0, MMWORD [wk(11)]    ; mm0=tmp0H
328     paddd       mm3, mm5                ; mm3=tmp3L
329     paddd       mm4, mm7                ; mm4=tmp3H
330
331     movq        MMWORD [wk(8)], mm2     ; wk(8)=tmp0L
332     movq        MMWORD [wk(9)], mm0     ; wk(9)=tmp0H
333
334     movq        mm2, mm1
335     movq        mm0, mm1
336     punpcklwd   mm2, mm6
337     punpckhwd   mm0, mm6
338     movq        mm1, mm2
339     movq        mm6, mm0
340     pmaddwd     mm2, [GOTOFF(ebx,PW_MF050_MF256)]  ; mm2=tmp1L
341     pmaddwd     mm0, [GOTOFF(ebx,PW_MF050_MF256)]  ; mm0=tmp1H
342     pmaddwd     mm1, [GOTOFF(ebx,PW_MF256_F050)]   ; mm1=tmp2L
343     pmaddwd     mm6, [GOTOFF(ebx,PW_MF256_F050)]   ; mm6=tmp2H
344
345     paddd       mm2, mm5                ; mm2=tmp1L
346     paddd       mm0, mm7                ; mm0=tmp1H
347     paddd       mm1, MMWORD [wk(10)]    ; mm1=tmp2L
348     paddd       mm6, MMWORD [wk(11)]    ; mm6=tmp2H
349
350     movq        MMWORD [wk(10)], mm2    ; wk(10)=tmp1L
351     movq        MMWORD [wk(11)], mm0    ; wk(11)=tmp1H
352
353     ; -- Final output stage
354
355     movq        mm5, MMWORD [wk(0)]     ; mm5=tmp10L
356     movq        mm7, MMWORD [wk(1)]     ; mm7=tmp10H
357
358     movq        mm2, mm5
359     movq        mm0, mm7
360     paddd       mm5, mm3                ; mm5=data0L
361     paddd       mm7, mm4                ; mm7=data0H
362     psubd       mm2, mm3                ; mm2=data7L
363     psubd       mm0, mm4                ; mm0=data7H
364
365     movq        mm3, [GOTOFF(ebx,PD_DESCALE_P1)]  ; mm3=[PD_DESCALE_P1]
366
367     paddd       mm5, mm3
368     paddd       mm7, mm3
369     psrad       mm5, DESCALE_P1
370     psrad       mm7, DESCALE_P1
371     paddd       mm2, mm3
372     paddd       mm0, mm3
373     psrad       mm2, DESCALE_P1
374     psrad       mm0, DESCALE_P1
375
376     packssdw    mm5, mm7                ; mm5=data0=(00 01 02 03)
377     packssdw    mm2, mm0                ; mm2=data7=(70 71 72 73)
378
379     movq        mm4, MMWORD [wk(4)]     ; mm4=tmp11L
380     movq        mm3, MMWORD [wk(5)]     ; mm3=tmp11H
381
382     movq        mm7, mm4
383     movq        mm0, mm3
384     paddd       mm4, mm1                ; mm4=data1L
385     paddd       mm3, mm6                ; mm3=data1H
386     psubd       mm7, mm1                ; mm7=data6L
387     psubd       mm0, mm6                ; mm0=data6H
388
389     movq        mm1, [GOTOFF(ebx,PD_DESCALE_P1)]  ; mm1=[PD_DESCALE_P1]
390
391     paddd       mm4, mm1
392     paddd       mm3, mm1
393     psrad       mm4, DESCALE_P1
394     psrad       mm3, DESCALE_P1
395     paddd       mm7, mm1
396     paddd       mm0, mm1
397     psrad       mm7, DESCALE_P1
398     psrad       mm0, DESCALE_P1
399
400     packssdw    mm4, mm3                ; mm4=data1=(10 11 12 13)
401     packssdw    mm7, mm0                ; mm7=data6=(60 61 62 63)
402
403     movq        mm6, mm5                ; transpose coefficients(phase 1)
404     punpcklwd   mm5, mm4                ; mm5=(00 10 01 11)
405     punpckhwd   mm6, mm4                ; mm6=(02 12 03 13)
406     movq        mm1, mm7                ; transpose coefficients(phase 1)
407     punpcklwd   mm7, mm2                ; mm7=(60 70 61 71)
408     punpckhwd   mm1, mm2                ; mm1=(62 72 63 73)
409
410     movq        mm3, MMWORD [wk(6)]     ; mm3=tmp12L
411     movq        mm0, MMWORD [wk(7)]     ; mm0=tmp12H
412     movq        mm4, MMWORD [wk(10)]    ; mm4=tmp1L
413     movq        mm2, MMWORD [wk(11)]    ; mm2=tmp1H
414
415     movq        MMWORD [wk(0)], mm5     ; wk(0)=(00 10 01 11)
416     movq        MMWORD [wk(1)], mm6     ; wk(1)=(02 12 03 13)
417     movq        MMWORD [wk(4)], mm7     ; wk(4)=(60 70 61 71)
418     movq        MMWORD [wk(5)], mm1     ; wk(5)=(62 72 63 73)
419
420     movq        mm5, mm3
421     movq        mm6, mm0
422     paddd       mm3, mm4                ; mm3=data2L
423     paddd       mm0, mm2                ; mm0=data2H
424     psubd       mm5, mm4                ; mm5=data5L
425     psubd       mm6, mm2                ; mm6=data5H
426
427     movq        mm7, [GOTOFF(ebx,PD_DESCALE_P1)]  ; mm7=[PD_DESCALE_P1]
428
429     paddd       mm3, mm7
430     paddd       mm0, mm7
431     psrad       mm3, DESCALE_P1
432     psrad       mm0, DESCALE_P1
433     paddd       mm5, mm7
434     paddd       mm6, mm7
435     psrad       mm5, DESCALE_P1
436     psrad       mm6, DESCALE_P1
437
438     packssdw    mm3, mm0                ; mm3=data2=(20 21 22 23)
439     packssdw    mm5, mm6                ; mm5=data5=(50 51 52 53)
440
441     movq        mm1, MMWORD [wk(2)]     ; mm1=tmp13L
442     movq        mm4, MMWORD [wk(3)]     ; mm4=tmp13H
443     movq        mm2, MMWORD [wk(8)]     ; mm2=tmp0L
444     movq        mm7, MMWORD [wk(9)]     ; mm7=tmp0H
445
446     movq        mm0, mm1
447     movq        mm6, mm4
448     paddd       mm1, mm2                ; mm1=data3L
449     paddd       mm4, mm7                ; mm4=data3H
450     psubd       mm0, mm2                ; mm0=data4L
451     psubd       mm6, mm7                ; mm6=data4H
452
453     movq        mm2, [GOTOFF(ebx,PD_DESCALE_P1)]  ; mm2=[PD_DESCALE_P1]
454
455     paddd       mm1, mm2
456     paddd       mm4, mm2
457     psrad       mm1, DESCALE_P1
458     psrad       mm4, DESCALE_P1
459     paddd       mm0, mm2
460     paddd       mm6, mm2
461     psrad       mm0, DESCALE_P1
462     psrad       mm6, DESCALE_P1
463
464     packssdw    mm1, mm4                ; mm1=data3=(30 31 32 33)
465     packssdw    mm0, mm6                ; mm0=data4=(40 41 42 43)
466
467     movq        mm7, MMWORD [wk(0)]     ; mm7=(00 10 01 11)
468     movq        mm2, MMWORD [wk(1)]     ; mm2=(02 12 03 13)
469
470     movq        mm4, mm3                ; transpose coefficients(phase 1)
471     punpcklwd   mm3, mm1                ; mm3=(20 30 21 31)
472     punpckhwd   mm4, mm1                ; mm4=(22 32 23 33)
473     movq        mm6, mm0                ; transpose coefficients(phase 1)
474     punpcklwd   mm0, mm5                ; mm0=(40 50 41 51)
475     punpckhwd   mm6, mm5                ; mm6=(42 52 43 53)
476
477     movq        mm1, mm7                ; transpose coefficients(phase 2)
478     punpckldq   mm7, mm3                ; mm7=(00 10 20 30)
479     punpckhdq   mm1, mm3                ; mm1=(01 11 21 31)
480     movq        mm5, mm2                ; transpose coefficients(phase 2)
481     punpckldq   mm2, mm4                ; mm2=(02 12 22 32)
482     punpckhdq   mm5, mm4                ; mm5=(03 13 23 33)
483
484     movq        mm3, MMWORD [wk(4)]     ; mm3=(60 70 61 71)
485     movq        mm4, MMWORD [wk(5)]     ; mm4=(62 72 63 73)
486
487     movq        MMWORD [MMBLOCK(0,0,edi,SIZEOF_JCOEF)], mm7
488     movq        MMWORD [MMBLOCK(1,0,edi,SIZEOF_JCOEF)], mm1
489     movq        MMWORD [MMBLOCK(2,0,edi,SIZEOF_JCOEF)], mm2
490     movq        MMWORD [MMBLOCK(3,0,edi,SIZEOF_JCOEF)], mm5
491
492     movq        mm7, mm0                ; transpose coefficients(phase 2)
493     punpckldq   mm0, mm3                ; mm0=(40 50 60 70)
494     punpckhdq   mm7, mm3                ; mm7=(41 51 61 71)
495     movq        mm1, mm6                ; transpose coefficients(phase 2)
496     punpckldq   mm6, mm4                ; mm6=(42 52 62 72)
497     punpckhdq   mm1, mm4                ; mm1=(43 53 63 73)
498
499     movq        MMWORD [MMBLOCK(0,1,edi,SIZEOF_JCOEF)], mm0
500     movq        MMWORD [MMBLOCK(1,1,edi,SIZEOF_JCOEF)], mm7
501     movq        MMWORD [MMBLOCK(2,1,edi,SIZEOF_JCOEF)], mm6
502     movq        MMWORD [MMBLOCK(3,1,edi,SIZEOF_JCOEF)], mm1
503
504 .nextcolumn:
505     add         esi, byte 4*SIZEOF_JCOEF            ; coef_block
506     add         edx, byte 4*SIZEOF_ISLOW_MULT_TYPE  ; quantptr
507     add         edi, byte 4*DCTSIZE*SIZEOF_JCOEF    ; wsptr
508     dec         ecx                                 ; ctr
509     jnz         near .columnloop
510
511     ; ---- Pass 2: process rows from work array, store into output array.
512
513     mov         eax, [original_ebp]
514     lea         esi, [workspace]                   ; JCOEF *wsptr
515     mov         edi, JSAMPARRAY [output_buf(eax)]  ; (JSAMPROW *)
516     mov         eax, JDIMENSION [output_col(eax)]
517     mov         ecx, DCTSIZE/4                     ; ctr
518     alignx      16, 7
519 .rowloop:
520
521     ; -- Even part
522
523     movq        mm0, MMWORD [MMBLOCK(0,0,esi,SIZEOF_JCOEF)]
524     movq        mm1, MMWORD [MMBLOCK(2,0,esi,SIZEOF_JCOEF)]
525     movq        mm2, MMWORD [MMBLOCK(4,0,esi,SIZEOF_JCOEF)]
526     movq        mm3, MMWORD [MMBLOCK(6,0,esi,SIZEOF_JCOEF)]
527
528     ; (Original)
529     ; z1 = (z2 + z3) * 0.541196100;
530     ; tmp2 = z1 + z3 * -1.847759065;
531     ; tmp3 = z1 + z2 * 0.765366865;
532     ;
533     ; (This implementation)
534     ; tmp2 = z2 * 0.541196100 + z3 * (0.541196100 - 1.847759065);
535     ; tmp3 = z2 * (0.541196100 + 0.765366865) + z3 * 0.541196100;
536
537     movq        mm4, mm1                ; mm1=in2=z2
538     movq        mm5, mm1
539     punpcklwd   mm4, mm3                ; mm3=in6=z3
540     punpckhwd   mm5, mm3
541     movq        mm1, mm4
542     movq        mm3, mm5
543     pmaddwd     mm4, [GOTOFF(ebx,PW_F130_F054)]   ; mm4=tmp3L
544     pmaddwd     mm5, [GOTOFF(ebx,PW_F130_F054)]   ; mm5=tmp3H
545     pmaddwd     mm1, [GOTOFF(ebx,PW_F054_MF130)]  ; mm1=tmp2L
546     pmaddwd     mm3, [GOTOFF(ebx,PW_F054_MF130)]  ; mm3=tmp2H
547
548     movq        mm6, mm0
549     paddw       mm0, mm2                ; mm0=in0+in4
550     psubw       mm6, mm2                ; mm6=in0-in4
551
552     pxor        mm7, mm7
553     pxor        mm2, mm2
554     punpcklwd   mm7, mm0                ; mm7=tmp0L
555     punpckhwd   mm2, mm0                ; mm2=tmp0H
556     psrad       mm7, (16-CONST_BITS)    ; psrad mm7,16 & pslld mm7,CONST_BITS
557     psrad       mm2, (16-CONST_BITS)    ; psrad mm2,16 & pslld mm2,CONST_BITS
558
559     movq        mm0, mm7
560     paddd       mm7, mm4                ; mm7=tmp10L
561     psubd       mm0, mm4                ; mm0=tmp13L
562     movq        mm4, mm2
563     paddd       mm2, mm5                ; mm2=tmp10H
564     psubd       mm4, mm5                ; mm4=tmp13H
565
566     movq        MMWORD [wk(0)], mm7     ; wk(0)=tmp10L
567     movq        MMWORD [wk(1)], mm2     ; wk(1)=tmp10H
568     movq        MMWORD [wk(2)], mm0     ; wk(2)=tmp13L
569     movq        MMWORD [wk(3)], mm4     ; wk(3)=tmp13H
570
571     pxor        mm5, mm5
572     pxor        mm7, mm7
573     punpcklwd   mm5, mm6                ; mm5=tmp1L
574     punpckhwd   mm7, mm6                ; mm7=tmp1H
575     psrad       mm5, (16-CONST_BITS)    ; psrad mm5,16 & pslld mm5,CONST_BITS
576     psrad       mm7, (16-CONST_BITS)    ; psrad mm7,16 & pslld mm7,CONST_BITS
577
578     movq        mm2, mm5
579     paddd       mm5, mm1                ; mm5=tmp11L
580     psubd       mm2, mm1                ; mm2=tmp12L
581     movq        mm0, mm7
582     paddd       mm7, mm3                ; mm7=tmp11H
583     psubd       mm0, mm3                ; mm0=tmp12H
584
585     movq        MMWORD [wk(4)], mm5     ; wk(4)=tmp11L
586     movq        MMWORD [wk(5)], mm7     ; wk(5)=tmp11H
587     movq        MMWORD [wk(6)], mm2     ; wk(6)=tmp12L
588     movq        MMWORD [wk(7)], mm0     ; wk(7)=tmp12H
589
590     ; -- Odd part
591
592     movq        mm4, MMWORD [MMBLOCK(1,0,esi,SIZEOF_JCOEF)]
593     movq        mm6, MMWORD [MMBLOCK(3,0,esi,SIZEOF_JCOEF)]
594     movq        mm1, MMWORD [MMBLOCK(5,0,esi,SIZEOF_JCOEF)]
595     movq        mm3, MMWORD [MMBLOCK(7,0,esi,SIZEOF_JCOEF)]
596
597     movq        mm5, mm6
598     movq        mm7, mm4
599     paddw       mm5, mm3                ; mm5=z3
600     paddw       mm7, mm1                ; mm7=z4
601
602     ; (Original)
603     ; z5 = (z3 + z4) * 1.175875602;
604     ; z3 = z3 * -1.961570560;  z4 = z4 * -0.390180644;
605     ; z3 += z5;  z4 += z5;
606     ;
607     ; (This implementation)
608     ; z3 = z3 * (1.175875602 - 1.961570560) + z4 * 1.175875602;
609     ; z4 = z3 * 1.175875602 + z4 * (1.175875602 - 0.390180644);
610
611     movq        mm2, mm5
612     movq        mm0, mm5
613     punpcklwd   mm2, mm7
614     punpckhwd   mm0, mm7
615     movq        mm5, mm2
616     movq        mm7, mm0
617     pmaddwd     mm2, [GOTOFF(ebx,PW_MF078_F117)]  ; mm2=z3L
618     pmaddwd     mm0, [GOTOFF(ebx,PW_MF078_F117)]  ; mm0=z3H
619     pmaddwd     mm5, [GOTOFF(ebx,PW_F117_F078)]   ; mm5=z4L
620     pmaddwd     mm7, [GOTOFF(ebx,PW_F117_F078)]   ; mm7=z4H
621
622     movq        MMWORD [wk(10)], mm2    ; wk(10)=z3L
623     movq        MMWORD [wk(11)], mm0    ; wk(11)=z3H
624
625     ; (Original)
626     ; z1 = tmp0 + tmp3;  z2 = tmp1 + tmp2;
627     ; tmp0 = tmp0 * 0.298631336;  tmp1 = tmp1 * 2.053119869;
628     ; tmp2 = tmp2 * 3.072711026;  tmp3 = tmp3 * 1.501321110;
629     ; z1 = z1 * -0.899976223;  z2 = z2 * -2.562915447;
630     ; tmp0 += z1 + z3;  tmp1 += z2 + z4;
631     ; tmp2 += z2 + z3;  tmp3 += z1 + z4;
632     ;
633     ; (This implementation)
634     ; tmp0 = tmp0 * (0.298631336 - 0.899976223) + tmp3 * -0.899976223;
635     ; tmp1 = tmp1 * (2.053119869 - 2.562915447) + tmp2 * -2.562915447;
636     ; tmp2 = tmp1 * -2.562915447 + tmp2 * (3.072711026 - 2.562915447);
637     ; tmp3 = tmp0 * -0.899976223 + tmp3 * (1.501321110 - 0.899976223);
638     ; tmp0 += z3;  tmp1 += z4;
639     ; tmp2 += z3;  tmp3 += z4;
640
641     movq        mm2, mm3
642     movq        mm0, mm3
643     punpcklwd   mm2, mm4
644     punpckhwd   mm0, mm4
645     movq        mm3, mm2
646     movq        mm4, mm0
647     pmaddwd     mm2, [GOTOFF(ebx,PW_MF060_MF089)]  ; mm2=tmp0L
648     pmaddwd     mm0, [GOTOFF(ebx,PW_MF060_MF089)]  ; mm0=tmp0H
649     pmaddwd     mm3, [GOTOFF(ebx,PW_MF089_F060)]   ; mm3=tmp3L
650     pmaddwd     mm4, [GOTOFF(ebx,PW_MF089_F060)]   ; mm4=tmp3H
651
652     paddd       mm2, MMWORD [wk(10)]    ; mm2=tmp0L
653     paddd       mm0, MMWORD [wk(11)]    ; mm0=tmp0H
654     paddd       mm3, mm5                ; mm3=tmp3L
655     paddd       mm4, mm7                ; mm4=tmp3H
656
657     movq        MMWORD [wk(8)], mm2     ; wk(8)=tmp0L
658     movq        MMWORD [wk(9)], mm0     ; wk(9)=tmp0H
659
660     movq        mm2, mm1
661     movq        mm0, mm1
662     punpcklwd   mm2, mm6
663     punpckhwd   mm0, mm6
664     movq        mm1, mm2
665     movq        mm6, mm0
666     pmaddwd     mm2, [GOTOFF(ebx,PW_MF050_MF256)]  ; mm2=tmp1L
667     pmaddwd     mm0, [GOTOFF(ebx,PW_MF050_MF256)]  ; mm0=tmp1H
668     pmaddwd     mm1, [GOTOFF(ebx,PW_MF256_F050)]   ; mm1=tmp2L
669     pmaddwd     mm6, [GOTOFF(ebx,PW_MF256_F050)]   ; mm6=tmp2H
670
671     paddd       mm2, mm5                ; mm2=tmp1L
672     paddd       mm0, mm7                ; mm0=tmp1H
673     paddd       mm1, MMWORD [wk(10)]    ; mm1=tmp2L
674     paddd       mm6, MMWORD [wk(11)]    ; mm6=tmp2H
675
676     movq        MMWORD [wk(10)], mm2    ; wk(10)=tmp1L
677     movq        MMWORD [wk(11)], mm0    ; wk(11)=tmp1H
678
679     ; -- Final output stage
680
681     movq        mm5, MMWORD [wk(0)]     ; mm5=tmp10L
682     movq        mm7, MMWORD [wk(1)]     ; mm7=tmp10H
683
684     movq        mm2, mm5
685     movq        mm0, mm7
686     paddd       mm5, mm3                ; mm5=data0L
687     paddd       mm7, mm4                ; mm7=data0H
688     psubd       mm2, mm3                ; mm2=data7L
689     psubd       mm0, mm4                ; mm0=data7H
690
691     movq        mm3, [GOTOFF(ebx,PD_DESCALE_P2)]  ; mm3=[PD_DESCALE_P2]
692
693     paddd       mm5, mm3
694     paddd       mm7, mm3
695     psrad       mm5, DESCALE_P2
696     psrad       mm7, DESCALE_P2
697     paddd       mm2, mm3
698     paddd       mm0, mm3
699     psrad       mm2, DESCALE_P2
700     psrad       mm0, DESCALE_P2
701
702     packssdw    mm5, mm7                ; mm5=data0=(00 10 20 30)
703     packssdw    mm2, mm0                ; mm2=data7=(07 17 27 37)
704
705     movq        mm4, MMWORD [wk(4)]     ; mm4=tmp11L
706     movq        mm3, MMWORD [wk(5)]     ; mm3=tmp11H
707
708     movq        mm7, mm4
709     movq        mm0, mm3
710     paddd       mm4, mm1                ; mm4=data1L
711     paddd       mm3, mm6                ; mm3=data1H
712     psubd       mm7, mm1                ; mm7=data6L
713     psubd       mm0, mm6                ; mm0=data6H
714
715     movq        mm1, [GOTOFF(ebx,PD_DESCALE_P2)]  ; mm1=[PD_DESCALE_P2]
716
717     paddd       mm4, mm1
718     paddd       mm3, mm1
719     psrad       mm4, DESCALE_P2
720     psrad       mm3, DESCALE_P2
721     paddd       mm7, mm1
722     paddd       mm0, mm1
723     psrad       mm7, DESCALE_P2
724     psrad       mm0, DESCALE_P2
725
726     packssdw    mm4, mm3                ; mm4=data1=(01 11 21 31)
727     packssdw    mm7, mm0                ; mm7=data6=(06 16 26 36)
728
729     packsswb    mm5, mm7                ; mm5=(00 10 20 30 06 16 26 36)
730     packsswb    mm4, mm2                ; mm4=(01 11 21 31 07 17 27 37)
731
732     movq        mm6, MMWORD [wk(6)]     ; mm6=tmp12L
733     movq        mm1, MMWORD [wk(7)]     ; mm1=tmp12H
734     movq        mm3, MMWORD [wk(10)]    ; mm3=tmp1L
735     movq        mm0, MMWORD [wk(11)]    ; mm0=tmp1H
736
737     movq        MMWORD [wk(0)], mm5     ; wk(0)=(00 10 20 30 06 16 26 36)
738     movq        MMWORD [wk(1)], mm4     ; wk(1)=(01 11 21 31 07 17 27 37)
739
740     movq        mm7, mm6
741     movq        mm2, mm1
742     paddd       mm6, mm3                ; mm6=data2L
743     paddd       mm1, mm0                ; mm1=data2H
744     psubd       mm7, mm3                ; mm7=data5L
745     psubd       mm2, mm0                ; mm2=data5H
746
747     movq        mm5, [GOTOFF(ebx,PD_DESCALE_P2)]  ; mm5=[PD_DESCALE_P2]
748
749     paddd       mm6, mm5
750     paddd       mm1, mm5
751     psrad       mm6, DESCALE_P2
752     psrad       mm1, DESCALE_P2
753     paddd       mm7, mm5
754     paddd       mm2, mm5
755     psrad       mm7, DESCALE_P2
756     psrad       mm2, DESCALE_P2
757
758     packssdw    mm6, mm1                ; mm6=data2=(02 12 22 32)
759     packssdw    mm7, mm2                ; mm7=data5=(05 15 25 35)
760
761     movq        mm4, MMWORD [wk(2)]     ; mm4=tmp13L
762     movq        mm3, MMWORD [wk(3)]     ; mm3=tmp13H
763     movq        mm0, MMWORD [wk(8)]     ; mm0=tmp0L
764     movq        mm5, MMWORD [wk(9)]     ; mm5=tmp0H
765
766     movq        mm1, mm4
767     movq        mm2, mm3
768     paddd       mm4, mm0                ; mm4=data3L
769     paddd       mm3, mm5                ; mm3=data3H
770     psubd       mm1, mm0                ; mm1=data4L
771     psubd       mm2, mm5                ; mm2=data4H
772
773     movq        mm0, [GOTOFF(ebx,PD_DESCALE_P2)]  ; mm0=[PD_DESCALE_P2]
774
775     paddd       mm4, mm0
776     paddd       mm3, mm0
777     psrad       mm4, DESCALE_P2
778     psrad       mm3, DESCALE_P2
779     paddd       mm1, mm0
780     paddd       mm2, mm0
781     psrad       mm1, DESCALE_P2
782     psrad       mm2, DESCALE_P2
783
784     movq        mm5, [GOTOFF(ebx,PB_CENTERJSAMP)]  ; mm5=[PB_CENTERJSAMP]
785
786     packssdw    mm4, mm3                ; mm4=data3=(03 13 23 33)
787     packssdw    mm1, mm2                ; mm1=data4=(04 14 24 34)
788
789     movq        mm0, MMWORD [wk(0)]     ; mm0=(00 10 20 30 06 16 26 36)
790     movq        mm3, MMWORD [wk(1)]     ; mm3=(01 11 21 31 07 17 27 37)
791
792     packsswb    mm6, mm1                ; mm6=(02 12 22 32 04 14 24 34)
793     packsswb    mm4, mm7                ; mm4=(03 13 23 33 05 15 25 35)
794
795     paddb       mm0, mm5
796     paddb       mm3, mm5
797     paddb       mm6, mm5
798     paddb       mm4, mm5
799
800     movq        mm2, mm0                ; transpose coefficients(phase 1)
801     punpcklbw   mm0, mm3                ; mm0=(00 01 10 11 20 21 30 31)
802     punpckhbw   mm2, mm3                ; mm2=(06 07 16 17 26 27 36 37)
803     movq        mm1, mm6                ; transpose coefficients(phase 1)
804     punpcklbw   mm6, mm4                ; mm6=(02 03 12 13 22 23 32 33)
805     punpckhbw   mm1, mm4                ; mm1=(04 05 14 15 24 25 34 35)
806
807     movq        mm7, mm0                ; transpose coefficients(phase 2)
808     punpcklwd   mm0, mm6                ; mm0=(00 01 02 03 10 11 12 13)
809     punpckhwd   mm7, mm6                ; mm7=(20 21 22 23 30 31 32 33)
810     movq        mm5, mm1                ; transpose coefficients(phase 2)
811     punpcklwd   mm1, mm2                ; mm1=(04 05 06 07 14 15 16 17)
812     punpckhwd   mm5, mm2                ; mm5=(24 25 26 27 34 35 36 37)
813
814     movq        mm3, mm0                ; transpose coefficients(phase 3)
815     punpckldq   mm0, mm1                ; mm0=(00 01 02 03 04 05 06 07)
816     punpckhdq   mm3, mm1                ; mm3=(10 11 12 13 14 15 16 17)
817     movq        mm4, mm7                ; transpose coefficients(phase 3)
818     punpckldq   mm7, mm5                ; mm7=(20 21 22 23 24 25 26 27)
819     punpckhdq   mm4, mm5                ; mm4=(30 31 32 33 34 35 36 37)
820
821     pushpic     ebx                     ; save GOT address
822
823     mov         edx, JSAMPROW [edi+0*SIZEOF_JSAMPROW]
824     mov         ebx, JSAMPROW [edi+1*SIZEOF_JSAMPROW]
825     movq        MMWORD [edx+eax*SIZEOF_JSAMPLE], mm0
826     movq        MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm3
827     mov         edx, JSAMPROW [edi+2*SIZEOF_JSAMPROW]
828     mov         ebx, JSAMPROW [edi+3*SIZEOF_JSAMPROW]
829     movq        MMWORD [edx+eax*SIZEOF_JSAMPLE], mm7
830     movq        MMWORD [ebx+eax*SIZEOF_JSAMPLE], mm4
831
832     poppic      ebx                     ; restore GOT address
833
834     add         esi, byte 4*SIZEOF_JCOEF     ; wsptr
835     add         edi, byte 4*SIZEOF_JSAMPROW
836     dec         ecx                          ; ctr
837     jnz         near .rowloop
838
839     emms                                ; empty MMX state
840
841     pop         edi
842     pop         esi
843 ;   pop         edx                     ; need not be preserved
844 ;   pop         ecx                     ; need not be preserved
845     pop         ebx
846     mov         esp, ebp                ; esp <- aligned ebp
847     pop         esp                     ; esp <- original ebp
848     pop         ebp
849     ret
850
851 ; For some reason, the OS X linker does not honor the request to align the
852 ; segment unless we do this.
853     align       32