update latest
[external/libjpeg-turbo.git] / simd / jfmmxfst.asm
1 ;
2 ; jfmmxfst.asm - fast integer FDCT (MMX)
3 ;
4 ; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 ;
6 ; Based on
7 ; 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 fast, not so accurate integer implementation of
18 ; the forward DCT (Discrete Cosine Transform). The following code is
19 ; based directly on the IJG's original jfdctfst.c; see the jfdctfst.c
20 ; for more details.
21 ;
22 ; [TAB8]
23
24 %include "jsimdext.inc"
25 %include "jdct.inc"
26
27 ; --------------------------------------------------------------------------
28
29 %define CONST_BITS      8       ; 14 is also OK.
30
31 %if CONST_BITS == 8
32 F_0_382 equ      98             ; FIX(0.382683433)
33 F_0_541 equ     139             ; FIX(0.541196100)
34 F_0_707 equ     181             ; FIX(0.707106781)
35 F_1_306 equ     334             ; FIX(1.306562965)
36 %else
37 ; NASM cannot do compile-time arithmetic on floating-point constants.
38 %define DESCALE(x,n)  (((x)+(1<<((n)-1)))>>(n))
39 F_0_382 equ     DESCALE( 410903207,30-CONST_BITS)       ; FIX(0.382683433)
40 F_0_541 equ     DESCALE( 581104887,30-CONST_BITS)       ; FIX(0.541196100)
41 F_0_707 equ     DESCALE( 759250124,30-CONST_BITS)       ; FIX(0.707106781)
42 F_1_306 equ     DESCALE(1402911301,30-CONST_BITS)       ; FIX(1.306562965)
43 %endif
44
45 ; --------------------------------------------------------------------------
46         SECTION SEG_CONST
47
48 ; PRE_MULTIPLY_SCALE_BITS <= 2 (to avoid overflow)
49 ; CONST_BITS + CONST_SHIFT + PRE_MULTIPLY_SCALE_BITS == 16 (for pmulhw)
50
51 %define PRE_MULTIPLY_SCALE_BITS   2
52 %define CONST_SHIFT     (16 - PRE_MULTIPLY_SCALE_BITS - CONST_BITS)
53
54         alignz  16
55         global  EXTN(jconst_fdct_ifast_mmx)
56
57 EXTN(jconst_fdct_ifast_mmx):
58
59 PW_F0707        times 4 dw  F_0_707 << CONST_SHIFT
60 PW_F0382        times 4 dw  F_0_382 << CONST_SHIFT
61 PW_F0541        times 4 dw  F_0_541 << CONST_SHIFT
62 PW_F1306        times 4 dw  F_1_306 << CONST_SHIFT
63
64         alignz  16
65
66 ; --------------------------------------------------------------------------
67         SECTION SEG_TEXT
68         BITS    32
69 ;
70 ; Perform the forward DCT on one block of samples.
71 ;
72 ; GLOBAL(void)
73 ; jsimd_fdct_ifast_mmx (DCTELEM * data)
74 ;
75
76 %define data(b)         (b)+8           ; DCTELEM * data
77
78 %define original_ebp    ebp+0
79 %define wk(i)           ebp-(WK_NUM-(i))*SIZEOF_MMWORD  ; mmword wk[WK_NUM]
80 %define WK_NUM          2
81
82         align   16
83         global  EXTN(jsimd_fdct_ifast_mmx)
84
85 EXTN(jsimd_fdct_ifast_mmx):
86         push    ebp
87         mov     eax,esp                         ; eax = original ebp
88         sub     esp, byte 4
89         and     esp, byte (-SIZEOF_MMWORD)      ; align to 64 bits
90         mov     [esp],eax
91         mov     ebp,esp                         ; ebp = aligned ebp
92         lea     esp, [wk(0)]
93         pushpic ebx
94 ;       push    ecx             ; need not be preserved
95 ;       push    edx             ; need not be preserved
96 ;       push    esi             ; unused
97 ;       push    edi             ; unused
98
99         get_GOT ebx             ; get GOT address
100
101         ; ---- Pass 1: process rows.
102
103         mov     edx, POINTER [data(eax)]        ; (DCTELEM *)
104         mov     ecx, DCTSIZE/4
105         alignx  16,7
106 .rowloop:
107
108         movq    mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)]
109         movq    mm1, MMWORD [MMBLOCK(3,0,edx,SIZEOF_DCTELEM)]
110         movq    mm2, MMWORD [MMBLOCK(2,1,edx,SIZEOF_DCTELEM)]
111         movq    mm3, MMWORD [MMBLOCK(3,1,edx,SIZEOF_DCTELEM)]
112
113         ; mm0=(20 21 22 23), mm2=(24 25 26 27)
114         ; mm1=(30 31 32 33), mm3=(34 35 36 37)
115
116         movq      mm4,mm0               ; transpose coefficients(phase 1)
117         punpcklwd mm0,mm1               ; mm0=(20 30 21 31)
118         punpckhwd mm4,mm1               ; mm4=(22 32 23 33)
119         movq      mm5,mm2               ; transpose coefficients(phase 1)
120         punpcklwd mm2,mm3               ; mm2=(24 34 25 35)
121         punpckhwd mm5,mm3               ; mm5=(26 36 27 37)
122
123         movq    mm6, MMWORD [MMBLOCK(0,0,edx,SIZEOF_DCTELEM)]
124         movq    mm7, MMWORD [MMBLOCK(1,0,edx,SIZEOF_DCTELEM)]
125         movq    mm1, MMWORD [MMBLOCK(0,1,edx,SIZEOF_DCTELEM)]
126         movq    mm3, MMWORD [MMBLOCK(1,1,edx,SIZEOF_DCTELEM)]
127
128         ; mm6=(00 01 02 03), mm1=(04 05 06 07)
129         ; mm7=(10 11 12 13), mm3=(14 15 16 17)
130
131         movq    MMWORD [wk(0)], mm4     ; wk(0)=(22 32 23 33)
132         movq    MMWORD [wk(1)], mm2     ; wk(1)=(24 34 25 35)
133
134         movq      mm4,mm6               ; transpose coefficients(phase 1)
135         punpcklwd mm6,mm7               ; mm6=(00 10 01 11)
136         punpckhwd mm4,mm7               ; mm4=(02 12 03 13)
137         movq      mm2,mm1               ; transpose coefficients(phase 1)
138         punpcklwd mm1,mm3               ; mm1=(04 14 05 15)
139         punpckhwd mm2,mm3               ; mm2=(06 16 07 17)
140
141         movq      mm7,mm6               ; transpose coefficients(phase 2)
142         punpckldq mm6,mm0               ; mm6=(00 10 20 30)=data0
143         punpckhdq mm7,mm0               ; mm7=(01 11 21 31)=data1
144         movq      mm3,mm2               ; transpose coefficients(phase 2)
145         punpckldq mm2,mm5               ; mm2=(06 16 26 36)=data6
146         punpckhdq mm3,mm5               ; mm3=(07 17 27 37)=data7
147
148         movq    mm0,mm7
149         movq    mm5,mm6
150         psubw   mm7,mm2                 ; mm7=data1-data6=tmp6
151         psubw   mm6,mm3                 ; mm6=data0-data7=tmp7
152         paddw   mm0,mm2                 ; mm0=data1+data6=tmp1
153         paddw   mm5,mm3                 ; mm5=data0+data7=tmp0
154
155         movq    mm2, MMWORD [wk(0)]     ; mm2=(22 32 23 33)
156         movq    mm3, MMWORD [wk(1)]     ; mm3=(24 34 25 35)
157         movq    MMWORD [wk(0)], mm7     ; wk(0)=tmp6
158         movq    MMWORD [wk(1)], mm6     ; wk(1)=tmp7
159
160         movq      mm7,mm4               ; transpose coefficients(phase 2)
161         punpckldq mm4,mm2               ; mm4=(02 12 22 32)=data2
162         punpckhdq mm7,mm2               ; mm7=(03 13 23 33)=data3
163         movq      mm6,mm1               ; transpose coefficients(phase 2)
164         punpckldq mm1,mm3               ; mm1=(04 14 24 34)=data4
165         punpckhdq mm6,mm3               ; mm6=(05 15 25 35)=data5
166
167         movq    mm2,mm7
168         movq    mm3,mm4
169         paddw   mm7,mm1                 ; mm7=data3+data4=tmp3
170         paddw   mm4,mm6                 ; mm4=data2+data5=tmp2
171         psubw   mm2,mm1                 ; mm2=data3-data4=tmp4
172         psubw   mm3,mm6                 ; mm3=data2-data5=tmp5
173
174         ; -- Even part
175
176         movq    mm1,mm5
177         movq    mm6,mm0
178         psubw   mm5,mm7                 ; mm5=tmp13
179         psubw   mm0,mm4                 ; mm0=tmp12
180         paddw   mm1,mm7                 ; mm1=tmp10
181         paddw   mm6,mm4                 ; mm6=tmp11
182
183         paddw   mm0,mm5
184         psllw   mm0,PRE_MULTIPLY_SCALE_BITS
185         pmulhw  mm0,[GOTOFF(ebx,PW_F0707)] ; mm0=z1
186
187         movq    mm7,mm1
188         movq    mm4,mm5
189         psubw   mm1,mm6                 ; mm1=data4
190         psubw   mm5,mm0                 ; mm5=data6
191         paddw   mm7,mm6                 ; mm7=data0
192         paddw   mm4,mm0                 ; mm4=data2
193
194         movq    MMWORD [MMBLOCK(0,1,edx,SIZEOF_DCTELEM)], mm1
195         movq    MMWORD [MMBLOCK(2,1,edx,SIZEOF_DCTELEM)], mm5
196         movq    MMWORD [MMBLOCK(0,0,edx,SIZEOF_DCTELEM)], mm7
197         movq    MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)], mm4
198
199         ; -- Odd part
200
201         movq    mm6, MMWORD [wk(0)]     ; mm6=tmp6
202         movq    mm0, MMWORD [wk(1)]     ; mm0=tmp7
203
204         paddw   mm2,mm3                 ; mm2=tmp10
205         paddw   mm3,mm6                 ; mm3=tmp11
206         paddw   mm6,mm0                 ; mm6=tmp12, mm0=tmp7
207
208         psllw   mm2,PRE_MULTIPLY_SCALE_BITS
209         psllw   mm6,PRE_MULTIPLY_SCALE_BITS
210
211         psllw   mm3,PRE_MULTIPLY_SCALE_BITS
212         pmulhw  mm3,[GOTOFF(ebx,PW_F0707)] ; mm3=z3
213
214         movq    mm1,mm2                 ; mm1=tmp10
215         psubw   mm2,mm6
216         pmulhw  mm2,[GOTOFF(ebx,PW_F0382)] ; mm2=z5
217         pmulhw  mm1,[GOTOFF(ebx,PW_F0541)] ; mm1=MULTIPLY(tmp10,FIX_0_54119610)
218         pmulhw  mm6,[GOTOFF(ebx,PW_F1306)] ; mm6=MULTIPLY(tmp12,FIX_1_30656296)
219         paddw   mm1,mm2                 ; mm1=z2
220         paddw   mm6,mm2                 ; mm6=z4
221
222         movq    mm5,mm0
223         psubw   mm0,mm3                 ; mm0=z13
224         paddw   mm5,mm3                 ; mm5=z11
225
226         movq    mm7,mm0
227         movq    mm4,mm5
228         psubw   mm0,mm1                 ; mm0=data3
229         psubw   mm5,mm6                 ; mm5=data7
230         paddw   mm7,mm1                 ; mm7=data5
231         paddw   mm4,mm6                 ; mm4=data1
232
233         movq    MMWORD [MMBLOCK(3,0,edx,SIZEOF_DCTELEM)], mm0
234         movq    MMWORD [MMBLOCK(3,1,edx,SIZEOF_DCTELEM)], mm5
235         movq    MMWORD [MMBLOCK(1,1,edx,SIZEOF_DCTELEM)], mm7
236         movq    MMWORD [MMBLOCK(1,0,edx,SIZEOF_DCTELEM)], mm4
237
238         add     edx, byte 4*DCTSIZE*SIZEOF_DCTELEM
239         dec     ecx
240         jnz     near .rowloop
241
242         ; ---- Pass 2: process columns.
243
244         mov     edx, POINTER [data(eax)]        ; (DCTELEM *)
245         mov     ecx, DCTSIZE/4
246         alignx  16,7
247 .columnloop:
248
249         movq    mm0, MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)]
250         movq    mm1, MMWORD [MMBLOCK(3,0,edx,SIZEOF_DCTELEM)]
251         movq    mm2, MMWORD [MMBLOCK(6,0,edx,SIZEOF_DCTELEM)]
252         movq    mm3, MMWORD [MMBLOCK(7,0,edx,SIZEOF_DCTELEM)]
253
254         ; mm0=(02 12 22 32), mm2=(42 52 62 72)
255         ; mm1=(03 13 23 33), mm3=(43 53 63 73)
256
257         movq      mm4,mm0               ; transpose coefficients(phase 1)
258         punpcklwd mm0,mm1               ; mm0=(02 03 12 13)
259         punpckhwd mm4,mm1               ; mm4=(22 23 32 33)
260         movq      mm5,mm2               ; transpose coefficients(phase 1)
261         punpcklwd mm2,mm3               ; mm2=(42 43 52 53)
262         punpckhwd mm5,mm3               ; mm5=(62 63 72 73)
263
264         movq    mm6, MMWORD [MMBLOCK(0,0,edx,SIZEOF_DCTELEM)]
265         movq    mm7, MMWORD [MMBLOCK(1,0,edx,SIZEOF_DCTELEM)]
266         movq    mm1, MMWORD [MMBLOCK(4,0,edx,SIZEOF_DCTELEM)]
267         movq    mm3, MMWORD [MMBLOCK(5,0,edx,SIZEOF_DCTELEM)]
268
269         ; mm6=(00 10 20 30), mm1=(40 50 60 70)
270         ; mm7=(01 11 21 31), mm3=(41 51 61 71)
271
272         movq    MMWORD [wk(0)], mm4     ; wk(0)=(22 23 32 33)
273         movq    MMWORD [wk(1)], mm2     ; wk(1)=(42 43 52 53)
274
275         movq      mm4,mm6               ; transpose coefficients(phase 1)
276         punpcklwd mm6,mm7               ; mm6=(00 01 10 11)
277         punpckhwd mm4,mm7               ; mm4=(20 21 30 31)
278         movq      mm2,mm1               ; transpose coefficients(phase 1)
279         punpcklwd mm1,mm3               ; mm1=(40 41 50 51)
280         punpckhwd mm2,mm3               ; mm2=(60 61 70 71)
281
282         movq      mm7,mm6               ; transpose coefficients(phase 2)
283         punpckldq mm6,mm0               ; mm6=(00 01 02 03)=data0
284         punpckhdq mm7,mm0               ; mm7=(10 11 12 13)=data1
285         movq      mm3,mm2               ; transpose coefficients(phase 2)
286         punpckldq mm2,mm5               ; mm2=(60 61 62 63)=data6
287         punpckhdq mm3,mm5               ; mm3=(70 71 72 73)=data7
288
289         movq    mm0,mm7
290         movq    mm5,mm6
291         psubw   mm7,mm2                 ; mm7=data1-data6=tmp6
292         psubw   mm6,mm3                 ; mm6=data0-data7=tmp7
293         paddw   mm0,mm2                 ; mm0=data1+data6=tmp1
294         paddw   mm5,mm3                 ; mm5=data0+data7=tmp0
295
296         movq    mm2, MMWORD [wk(0)]     ; mm2=(22 23 32 33)
297         movq    mm3, MMWORD [wk(1)]     ; mm3=(42 43 52 53)
298         movq    MMWORD [wk(0)], mm7     ; wk(0)=tmp6
299         movq    MMWORD [wk(1)], mm6     ; wk(1)=tmp7
300
301         movq      mm7,mm4               ; transpose coefficients(phase 2)
302         punpckldq mm4,mm2               ; mm4=(20 21 22 23)=data2
303         punpckhdq mm7,mm2               ; mm7=(30 31 32 33)=data3
304         movq      mm6,mm1               ; transpose coefficients(phase 2)
305         punpckldq mm1,mm3               ; mm1=(40 41 42 43)=data4
306         punpckhdq mm6,mm3               ; mm6=(50 51 52 53)=data5
307
308         movq    mm2,mm7
309         movq    mm3,mm4
310         paddw   mm7,mm1                 ; mm7=data3+data4=tmp3
311         paddw   mm4,mm6                 ; mm4=data2+data5=tmp2
312         psubw   mm2,mm1                 ; mm2=data3-data4=tmp4
313         psubw   mm3,mm6                 ; mm3=data2-data5=tmp5
314
315         ; -- Even part
316
317         movq    mm1,mm5
318         movq    mm6,mm0
319         psubw   mm5,mm7                 ; mm5=tmp13
320         psubw   mm0,mm4                 ; mm0=tmp12
321         paddw   mm1,mm7                 ; mm1=tmp10
322         paddw   mm6,mm4                 ; mm6=tmp11
323
324         paddw   mm0,mm5
325         psllw   mm0,PRE_MULTIPLY_SCALE_BITS
326         pmulhw  mm0,[GOTOFF(ebx,PW_F0707)] ; mm0=z1
327
328         movq    mm7,mm1
329         movq    mm4,mm5
330         psubw   mm1,mm6                 ; mm1=data4
331         psubw   mm5,mm0                 ; mm5=data6
332         paddw   mm7,mm6                 ; mm7=data0
333         paddw   mm4,mm0                 ; mm4=data2
334
335         movq    MMWORD [MMBLOCK(4,0,edx,SIZEOF_DCTELEM)], mm1
336         movq    MMWORD [MMBLOCK(6,0,edx,SIZEOF_DCTELEM)], mm5
337         movq    MMWORD [MMBLOCK(0,0,edx,SIZEOF_DCTELEM)], mm7
338         movq    MMWORD [MMBLOCK(2,0,edx,SIZEOF_DCTELEM)], mm4
339
340         ; -- Odd part
341
342         movq    mm6, MMWORD [wk(0)]     ; mm6=tmp6
343         movq    mm0, MMWORD [wk(1)]     ; mm0=tmp7
344
345         paddw   mm2,mm3                 ; mm2=tmp10
346         paddw   mm3,mm6                 ; mm3=tmp11
347         paddw   mm6,mm0                 ; mm6=tmp12, mm0=tmp7
348
349         psllw   mm2,PRE_MULTIPLY_SCALE_BITS
350         psllw   mm6,PRE_MULTIPLY_SCALE_BITS
351
352         psllw   mm3,PRE_MULTIPLY_SCALE_BITS
353         pmulhw  mm3,[GOTOFF(ebx,PW_F0707)] ; mm3=z3
354
355         movq    mm1,mm2                 ; mm1=tmp10
356         psubw   mm2,mm6
357         pmulhw  mm2,[GOTOFF(ebx,PW_F0382)] ; mm2=z5
358         pmulhw  mm1,[GOTOFF(ebx,PW_F0541)] ; mm1=MULTIPLY(tmp10,FIX_0_54119610)
359         pmulhw  mm6,[GOTOFF(ebx,PW_F1306)] ; mm6=MULTIPLY(tmp12,FIX_1_30656296)
360         paddw   mm1,mm2                 ; mm1=z2
361         paddw   mm6,mm2                 ; mm6=z4
362
363         movq    mm5,mm0
364         psubw   mm0,mm3                 ; mm0=z13
365         paddw   mm5,mm3                 ; mm5=z11
366
367         movq    mm7,mm0
368         movq    mm4,mm5
369         psubw   mm0,mm1                 ; mm0=data3
370         psubw   mm5,mm6                 ; mm5=data7
371         paddw   mm7,mm1                 ; mm7=data5
372         paddw   mm4,mm6                 ; mm4=data1
373
374         movq    MMWORD [MMBLOCK(3,0,edx,SIZEOF_DCTELEM)], mm0
375         movq    MMWORD [MMBLOCK(7,0,edx,SIZEOF_DCTELEM)], mm5
376         movq    MMWORD [MMBLOCK(5,0,edx,SIZEOF_DCTELEM)], mm7
377         movq    MMWORD [MMBLOCK(1,0,edx,SIZEOF_DCTELEM)], mm4
378
379         add     edx, byte 4*SIZEOF_DCTELEM
380         dec     ecx
381         jnz     near .columnloop
382
383         emms            ; empty MMX state
384
385 ;       pop     edi             ; unused
386 ;       pop     esi             ; unused
387 ;       pop     edx             ; need not be preserved
388 ;       pop     ecx             ; need not be preserved
389         poppic  ebx
390         mov     esp,ebp         ; esp <- aligned ebp
391         pop     esp             ; esp <- original ebp
392         pop     ebp
393         ret
394
395 ; For some reason, the OS X linker does not honor the request to align the
396 ; segment unless we do this.
397         align   16