Fix MSVC compilation broken in r17736.
[theora.git] / lib / x86_vc / mmxfdct.c
1 /********************************************************************\r
2  *                                                                  *\r
3  * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *\r
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *\r
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *\r
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *\r
7  *                                                                  *\r
8  * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006                *\r
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *\r
10  *                                                                  *\r
11  ********************************************************************/ \r
12  /*MMX fDCT implementation for x86_32*/\r
13 /*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/\r
14 #include "x86enc.h"\r
15 #include "x86zigzag.h"\r
16 \r
17 #if defined(OC_X86_ASM)\r
18 \r
19 #define OC_FDCT_STAGE1_8x4  __asm{ \\r
20   /*Stage 1:*/ \\r
21   /*mm0=t7'=t0-t7*/ \\r
22   __asm  psubw mm0,mm7 \\r
23   __asm  paddw mm7,mm7 \\r
24   /*mm1=t6'=t1-t6*/ \\r
25   __asm  psubw mm1, mm6 \\r
26   __asm  paddw mm6,mm6 \\r
27   /*mm2=t5'=t2-t5*/ \\r
28   __asm  psubw mm2,mm5 \\r
29   __asm  paddw mm5,mm5 \\r
30   /*mm3=t4'=t3-t4*/ \\r
31   __asm  psubw mm3,mm4 \\r
32   __asm  paddw mm4,mm4 \\r
33   /*mm7=t0'=t0+t7*/ \\r
34   __asm  paddw mm7,mm0 \\r
35   /*mm6=t1'=t1+t6*/  \\r
36   __asm  paddw mm6,mm1 \\r
37   /*mm5=t2'=t2+t5*/ \\r
38   __asm  paddw mm5,mm2 \\r
39   /*mm4=t3'=t3+t4*/ \\r
40   __asm  paddw mm4,mm3\\r
41 }\r
42 \r
43 #define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \\r
44   /*Stage 2:*/ \\r
45   /*mm7=t3''=t0'-t3'*/ \\r
46   __asm  psubw mm7,mm4 \\r
47   __asm  paddw mm4,mm4 \\r
48   /*mm6=t2''=t1'-t2'*/ \\r
49   __asm  psubw mm6,mm5 \\r
50   __asm  movq [Y+_r6],mm7 \\r
51   __asm  paddw mm5,mm5 \\r
52   /*mm1=t5''=t6'-t5'*/ \\r
53   __asm  psubw mm1,mm2 \\r
54   __asm  movq [Y+_r2],mm6 \\r
55   /*mm4=t0''=t0'+t3'*/ \\r
56   __asm  paddw mm4,mm7 \\r
57   __asm  paddw mm2,mm2 \\r
58   /*mm5=t1''=t1'+t2'*/ \\r
59   __asm  movq [Y+_r0],mm4 \\r
60   __asm  paddw mm5,mm6 \\r
61   /*mm2=t6''=t6'+t5'*/ \\r
62   __asm  paddw mm2,mm1 \\r
63   __asm  movq [Y+_r4],mm5 \\r
64   /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \\r
65   /*mm4, mm5, mm6, mm7 are free.*/ \\r
66   /*Stage 3:*/ \\r
67   /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \\r
68   __asm  mov A,0x5A806A0A \\r
69   __asm  pcmpeqb mm6,mm6 \\r
70   __asm  movd mm7,A \\r
71   __asm  psrlw mm6,15 \\r
72   __asm  punpckldq mm7,mm7 \\r
73   __asm  paddw mm6,mm6 \\r
74   /*mm0=0, m2={-1}x4 \\r
75     mm5:mm4=t5''*27146+0xB500*/ \\r
76   __asm  movq mm4,mm1 \\r
77   __asm  movq mm5,mm1 \\r
78   __asm  punpcklwd mm4,mm6 \\r
79   __asm  movq [Y+_r3],mm2 \\r
80   __asm  pmaddwd mm4,mm7 \\r
81   __asm  movq [Y+_r7],mm0 \\r
82   __asm  punpckhwd mm5,mm6 \\r
83   __asm  pxor mm0,mm0 \\r
84   __asm  pmaddwd mm5,mm7 \\r
85   __asm  pcmpeqb mm2,mm2 \\r
86   /*mm2=t6'', mm1=t5''+(t5''!=0) \\r
87     mm4=(t5''*27146+0xB500>>16)*/ \\r
88   __asm  pcmpeqw mm0,mm1 \\r
89   __asm  psrad mm4,16 \\r
90   __asm  psubw mm0,mm2 \\r
91   __asm  movq mm2, [Y+_r3] \\r
92   __asm  psrad mm5,16 \\r
93   __asm  paddw mm1,mm0 \\r
94   __asm  packssdw mm4,mm5 \\r
95   /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \\r
96   __asm  paddw mm4,mm1 \\r
97   __asm  movq mm0, [Y+_r7] \\r
98   __asm  psraw mm4,1 \\r
99   __asm  movq mm1,mm3 \\r
100   /*mm3=t4''=t4'+s*/ \\r
101   __asm  paddw mm3,mm4 \\r
102   /*mm1=t5'''=t4'-s*/ \\r
103   __asm  psubw mm1,mm4 \\r
104   /*mm1=0, mm3={-1}x4 \\r
105     mm5:mm4=t6''*27146+0xB500*/ \\r
106   __asm  movq mm4,mm2 \\r
107   __asm  movq mm5,mm2 \\r
108   __asm  punpcklwd mm4,mm6 \\r
109   __asm  movq [Y+_r5],mm1 \\r
110   __asm  pmaddwd mm4,mm7 \\r
111   __asm  movq [Y+_r1],mm3 \\r
112   __asm  punpckhwd mm5,mm6 \\r
113   __asm  pxor mm1,mm1 \\r
114   __asm  pmaddwd mm5,mm7 \\r
115   __asm  pcmpeqb mm3,mm3 \\r
116   /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \\r
117   __asm  psrad mm4,16 \\r
118   __asm  pcmpeqw mm1,mm2 \\r
119   __asm  psrad mm5,16 \\r
120   __asm  psubw mm1,mm3 \\r
121   __asm  packssdw mm4,mm5 \\r
122   __asm  paddw mm2,mm1 \\r
123   /*mm1=t1'' \\r
124     mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \\r
125   __asm  paddw mm4,mm2 \\r
126   __asm  movq mm1,[Y+_r4] \\r
127   __asm  psraw mm4,1 \\r
128   __asm  movq mm2,mm0 \\r
129   /*mm7={54491-0x7FFF,0x7FFF}x2 \\r
130     mm0=t7''=t7'+s*/ \\r
131   __asm  paddw mm0,mm4 \\r
132   /*mm2=t6'''=t7'-s*/ \\r
133   __asm  psubw mm2,mm4 \\r
134   /*Stage 4:*/ \\r
135   /*mm0=0, mm2=t0'' \\r
136     mm5:mm4=t1''*27146+0xB500*/ \\r
137   __asm  movq mm4,mm1 \\r
138   __asm  movq mm5,mm1 \\r
139   __asm  punpcklwd mm4,mm6 \\r
140   __asm  movq [Y+_r3],mm2 \\r
141   __asm  pmaddwd mm4,mm7 \\r
142   __asm  movq mm2,[Y+_r0] \\r
143   __asm  punpckhwd mm5,mm6 \\r
144   __asm  movq [Y+_r7],mm0 \\r
145   __asm  pmaddwd mm5,mm7 \\r
146   __asm  pxor mm0,mm0 \\r
147   /*mm7={27146,0x4000>>1}x2 \\r
148     mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \\r
149   __asm  psrad mm4,16 \\r
150   __asm  mov A,0x20006A0A \\r
151   __asm  pcmpeqw mm0,mm1 \\r
152   __asm  movd mm7,A \\r
153   __asm  psrad mm5,16 \\r
154   __asm  psubw mm0,mm3 \\r
155   __asm  packssdw mm4,mm5 \\r
156   __asm  paddw mm0,mm1 \\r
157   __asm  punpckldq mm7,mm7 \\r
158   __asm  paddw mm0,mm4 \\r
159   /*mm6={0x00000E3D}x2 \\r
160     mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \\r
161   __asm  movq mm4,mm2 \\r
162   __asm  movq mm5,mm2 \\r
163   __asm  punpcklwd mm4,mm6 \\r
164   __asm  mov A,0x0E3D \\r
165   __asm  pmaddwd mm4,mm7 \\r
166   __asm  punpckhwd mm5,mm6 \\r
167   __asm  movd mm6,A \\r
168   __asm  pmaddwd mm5,mm7 \\r
169   __asm  pxor mm1,mm1 \\r
170   __asm  punpckldq mm6,mm6 \\r
171   __asm  pcmpeqw mm1,mm2 \\r
172   /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \\r
173   __asm  psrad mm4,16 \\r
174   __asm  psubw mm1,mm3 \\r
175   __asm  psrad mm5,16 \\r
176   __asm  paddw mm2,mm1 \\r
177   __asm  packssdw mm4,mm5 \\r
178   __asm  movq mm1,[Y+_r5] \\r
179   __asm  paddw mm4,mm2 \\r
180   /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \\r
181     The naive implementation could cause overflow, so we use \\r
182      u=(r&s)+((r^s)>>1).*/ \\r
183   __asm  movq mm2,[Y+_r3] \\r
184   __asm  movq mm7,mm0 \\r
185   __asm  pxor mm0,mm4 \\r
186   __asm  pand mm7,mm4 \\r
187   __asm  psraw mm0,1 \\r
188   __asm  mov A,0x7FFF54DC \\r
189   __asm  paddw mm0,mm7 \\r
190   __asm  movd mm7,A \\r
191   /*mm7={54491-0x7FFF,0x7FFF}x2 \\r
192     mm4=_y[4]=v=r-u*/ \\r
193   __asm  psubw mm4,mm0 \\r
194   __asm  punpckldq mm7,mm7 \\r
195   __asm  movq [Y+_r4],mm4 \\r
196   /*mm0=0, mm7={36410}x4 \\r
197     mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \\r
198   __asm  movq mm4,mm1 \\r
199   __asm  movq mm5,mm1 \\r
200   __asm  punpcklwd mm4,mm1 \\r
201   __asm  mov A,0x8E3A8E3A \\r
202   __asm  pmaddwd mm4,mm7 \\r
203   __asm  movq [Y+_r0],mm0 \\r
204   __asm  punpckhwd mm5,mm1 \\r
205   __asm  pxor mm0,mm0 \\r
206   __asm  pmaddwd mm5,mm7 \\r
207   __asm  pcmpeqw mm1,mm0 \\r
208   __asm  movd mm7,A \\r
209   __asm  psubw mm1,mm3 \\r
210   __asm  punpckldq mm7,mm7 \\r
211   __asm  paddd mm4,mm6 \\r
212   __asm  paddd mm5,mm6 \\r
213   /*mm0=0 \\r
214     mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \\r
215   __asm  movq mm6,mm2 \\r
216   __asm  movq mm3,mm2 \\r
217   __asm  pmulhw mm6,mm7 \\r
218   __asm  paddw mm1,mm2 \\r
219   __asm  pmullw mm3,mm7 \\r
220   __asm  pxor mm0,mm0 \\r
221   __asm  paddw mm6,mm1 \\r
222   __asm  movq mm1,mm3 \\r
223   __asm  punpckhwd mm3,mm6 \\r
224   __asm  punpcklwd mm1,mm6 \\r
225   /*mm3={-1}x4, mm6={1}x4 \\r
226     mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \\r
227   __asm  paddd mm5,mm3 \\r
228   __asm  paddd mm4,mm1 \\r
229   __asm  psrad mm5,16 \\r
230   __asm  pxor mm6,mm6 \\r
231   __asm  psrad mm4,16 \\r
232   __asm  pcmpeqb mm3,mm3 \\r
233   __asm  packssdw mm4,mm5 \\r
234   __asm  psubw mm6,mm3 \\r
235   /*mm1=t7'', mm7={26568,0x3400}x2 \\r
236     mm2=s=t6'''-(36410*u>>16)*/ \\r
237   __asm  movq mm1,mm4 \\r
238   __asm  mov A,0x340067C8 \\r
239   __asm  pmulhw mm4,mm7 \\r
240   __asm  movd mm7,A \\r
241   __asm  movq [Y+_r5],mm1 \\r
242   __asm  punpckldq mm7,mm7 \\r
243   __asm  paddw mm4,mm1 \\r
244   __asm  movq mm1,[Y+_r7] \\r
245   __asm  psubw mm2,mm4 \\r
246   /*mm6={0x00007B1B}x2 \\r
247     mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \\r
248   __asm  movq mm4,mm2 \\r
249   __asm  movq mm5,mm2 \\r
250   __asm  punpcklwd mm4,mm6 \\r
251   __asm  pcmpeqw mm0,mm2 \\r
252   __asm  pmaddwd mm4,mm7 \\r
253   __asm  mov A,0x7B1B \\r
254   __asm  punpckhwd mm5,mm6 \\r
255   __asm  movd mm6,A \\r
256   __asm  pmaddwd mm5,mm7 \\r
257   __asm  psubw mm0,mm3 \\r
258   __asm  punpckldq mm6,mm6 \\r
259   /*mm7={64277-0x7FFF,0x7FFF}x2 \\r
260     mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \\r
261   __asm  psrad mm4,17 \\r
262   __asm  paddw mm2,mm0 \\r
263   __asm  psrad mm5,17 \\r
264   __asm  mov A,0x7FFF7B16 \\r
265   __asm  packssdw mm4,mm5 \\r
266   __asm  movd mm7,A \\r
267   __asm  paddw mm2,mm4 \\r
268   __asm  punpckldq mm7,mm7 \\r
269   /*mm0=0, mm7={12785}x4 \\r
270     mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \\r
271   __asm  movq mm4,mm1 \\r
272   __asm  movq mm5,mm1 \\r
273   __asm  movq [Y+_r3],mm2 \\r
274   __asm  punpcklwd mm4,mm1 \\r
275   __asm  movq mm2,[Y+_r1] \\r
276   __asm  pmaddwd mm4,mm7 \\r
277   __asm  mov A,0x31F131F1 \\r
278   __asm  punpckhwd mm5,mm1 \\r
279   __asm  pxor mm0,mm0 \\r
280   __asm  pmaddwd mm5,mm7 \\r
281   __asm  pcmpeqw mm1,mm0 \\r
282   __asm  movd mm7,A \\r
283   __asm  psubw mm1,mm3 \\r
284   __asm  punpckldq mm7,mm7 \\r
285   __asm  paddd mm4,mm6 \\r
286   __asm  paddd mm5,mm6 \\r
287   /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \\r
288   __asm  movq mm6,mm2 \\r
289   __asm  movq mm3,mm2 \\r
290   __asm  pmulhw mm6,mm7 \\r
291   __asm  pmullw mm3,mm7 \\r
292   __asm  paddw mm6,mm1 \\r
293   __asm  movq mm1,mm3 \\r
294   __asm  punpckhwd mm3,mm6 \\r
295   __asm  punpcklwd mm1,mm6 \\r
296   /*mm3={-1}x4, mm6={1}x4 \\r
297     mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \\r
298   __asm  paddd mm5,mm3 \\r
299   __asm  paddd mm4,mm1 \\r
300   __asm  psrad mm5,16 \\r
301   __asm  pxor mm6,mm6 \\r
302   __asm  psrad mm4,16 \\r
303   __asm  pcmpeqb mm3,mm3 \\r
304   __asm  packssdw mm4,mm5 \\r
305   __asm  psubw mm6,mm3 \\r
306   /*mm1=t3'', mm7={20539,0x3000}x2 \\r
307     mm4=s=(12785*u>>16)-t4''*/ \\r
308   __asm  movq [Y+_r1],mm4 \\r
309   __asm  pmulhw mm4,mm7 \\r
310   __asm  mov A,0x3000503B \\r
311   __asm  movq mm1,[Y+_r6] \\r
312   __asm  movd mm7,A \\r
313   __asm  psubw mm4,mm2 \\r
314   __asm  punpckldq mm7,mm7 \\r
315   /*mm6={0x00006CB7}x2 \\r
316     mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \\r
317   __asm  movq mm5,mm4 \\r
318   __asm  movq mm2,mm4 \\r
319   __asm  punpcklwd mm4,mm6 \\r
320   __asm  pcmpeqw mm0,mm2 \\r
321   __asm  pmaddwd mm4,mm7 \\r
322   __asm  mov A,0x6CB7 \\r
323   __asm  punpckhwd mm5,mm6 \\r
324   __asm  movd mm6,A \\r
325   __asm  pmaddwd mm5,mm7 \\r
326   __asm  psubw mm0,mm3 \\r
327   __asm  punpckldq mm6,mm6 \\r
328   /*mm7={60547-0x7FFF,0x7FFF}x2 \\r
329     mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \\r
330   __asm  psrad mm4,20 \\r
331   __asm  paddw mm2,mm0 \\r
332   __asm  psrad mm5,20 \\r
333   __asm  mov A,0x7FFF6C84 \\r
334   __asm  packssdw mm4,mm5 \\r
335   __asm  movd mm7,A \\r
336   __asm  paddw mm2,mm4 \\r
337   __asm  punpckldq mm7,mm7 \\r
338   /*mm0=0, mm7={25080}x4 \\r
339     mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \\r
340   __asm  movq mm4,mm1 \\r
341   __asm  movq mm5,mm1 \\r
342   __asm  movq [Y+_r7],mm2 \\r
343   __asm  punpcklwd mm4,mm1 \\r
344   __asm  movq mm2,[Y+_r2] \\r
345   __asm  pmaddwd mm4,mm7 \\r
346   __asm  mov A,0x61F861F8 \\r
347   __asm  punpckhwd mm5,mm1 \\r
348   __asm  pxor mm0,mm0 \\r
349   __asm  pmaddwd mm5,mm7 \\r
350   __asm  movd mm7,A \\r
351   __asm  pcmpeqw mm1,mm0 \\r
352   __asm  psubw mm1,mm3 \\r
353   __asm  punpckldq mm7,mm7 \\r
354   __asm  paddd mm4,mm6 \\r
355   __asm  paddd mm5,mm6 \\r
356   /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \\r
357   __asm  movq mm6,mm2 \\r
358   __asm  movq mm3,mm2 \\r
359   __asm  pmulhw mm6,mm7 \\r
360   __asm  pmullw mm3,mm7 \\r
361   __asm  paddw mm6,mm1 \\r
362   __asm  movq mm1,mm3 \\r
363   __asm  punpckhwd mm3,mm6 \\r
364   __asm  punpcklwd mm1,mm6 \\r
365   /*mm1={-1}x4 \\r
366     mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \\r
367   __asm  paddd mm5,mm3 \\r
368   __asm  paddd mm4,mm1 \\r
369   __asm  psrad mm5,16 \\r
370   __asm  mov A,0x28005460 \\r
371   __asm  psrad mm4,16 \\r
372   __asm  pcmpeqb mm1,mm1 \\r
373   __asm  packssdw mm4,mm5 \\r
374   /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \\r
375     mm4=s=(25080*u>>16)-t2''*/ \\r
376   __asm  movq mm6,mm4 \\r
377   __asm  pmulhw mm4,mm7 \\r
378   __asm  pxor mm5,mm5 \\r
379   __asm  movd mm7,A \\r
380   __asm  psubw mm5,mm1 \\r
381   __asm  punpckldq mm7,mm7 \\r
382   __asm  psubw mm4,mm2 \\r
383   /*mm2=s+(s!=0) \\r
384     mm4:mm3=s*21600+0x2800*/ \\r
385   __asm  movq mm3,mm4 \\r
386   __asm  movq mm2,mm4 \\r
387   __asm  punpckhwd mm4,mm5 \\r
388   __asm  pcmpeqw mm0,mm2 \\r
389   __asm  pmaddwd mm4,mm7 \\r
390   __asm  psubw mm0,mm1 \\r
391   __asm  punpcklwd mm3,mm5 \\r
392   __asm  paddw mm2,mm0 \\r
393   __asm  pmaddwd mm3,mm7 \\r
394   /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \\r
395     mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \\r
396   __asm  movq mm0,[Y+_r4] \\r
397   __asm  psrad mm4,18 \\r
398   __asm  movq mm5,[Y+_r5] \\r
399   __asm  psrad mm3,18 \\r
400   __asm  movq mm1,[Y+_r7] \\r
401   __asm  packssdw mm3,mm4 \\r
402   __asm  movq mm4,[Y+_r0] \\r
403   __asm  paddw mm3,mm2 \\r
404 }\r
405 \r
406 /*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7].\r
407   On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and\r
408    {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/\r
409 #define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) __asm{ \\r
410   /*First 4x4 transpose:*/ \\r
411   /*mm0 = e3 e2 e1 e0 \\r
412     mm5 = f3 f2 f1 f0 \\r
413     mm3 = g3 g2 g1 g0 \\r
414     mm1 = h3 h2 h1 h0*/ \\r
415   __asm  movq mm2,mm0 \\r
416   __asm  punpcklwd mm0,mm5 \\r
417   __asm  punpckhwd mm2,mm5 \\r
418   __asm  movq mm5,mm3 \\r
419   __asm  punpcklwd mm3,mm1 \\r
420   __asm  punpckhwd mm5,mm1 \\r
421   /*mm0 = f1 e1 f0 e0 \\r
422     mm2 = f3 e3 f2 e2 \\r
423     mm3 = h1 g1 h0 g0 \\r
424     mm5 = h3 g3 h2 g2*/ \\r
425   __asm  movq mm1,mm0 \\r
426   __asm  punpckldq mm0,mm3 \\r
427   __asm  movq [Y+_r4],mm0 \\r
428   __asm  punpckhdq mm1,mm3 \\r
429   __asm  movq mm0,[Y+_r1] \\r
430   __asm  movq mm3,mm2 \\r
431   __asm  punpckldq mm2,mm5 \\r
432   __asm  punpckhdq mm3,mm5 \\r
433   __asm  movq mm5,[Y+_r3] \\r
434   /*_y[4] = h0 g0 f0 e0 \\r
435    mm1  = h1 g1 f1 e1 \\r
436    mm2  = h2 g2 f2 e2 \\r
437    mm3  = h3 g3 f3 e3*/ \\r
438   /*Second 4x4 transpose:*/ \\r
439   /*mm4 = a3 a2 a1 a0 \\r
440     mm0 = b3 b2 b1 b0 \\r
441     mm6 = c3 c2 c1 c0 \\r
442     mm5 = d3 d2 d1 d0*/ \\r
443   __asm  movq mm7,mm4 \\r
444   __asm  punpcklwd mm4,mm0 \\r
445   __asm  punpckhwd mm7,mm0 \\r
446   __asm  movq mm0,mm6 \\r
447   __asm  punpcklwd mm6,mm5 \\r
448   __asm  punpckhwd mm0,mm5 \\r
449   /*mm4 = b1 a1 b0 a0 \\r
450     mm7 = b3 a3 b2 a2 \\r
451     mm6 = d1 c1 d0 c0 \\r
452     mm0 = d3 c3 d2 c2*/ \\r
453   __asm  movq mm5,mm4 \\r
454   __asm  punpckldq mm4,mm6 \\r
455   __asm  punpckhdq mm5,mm6 \\r
456   __asm  movq mm6,mm7 \\r
457   __asm  punpckhdq mm7,mm0 \\r
458   __asm  punpckldq mm6,mm0 \\r
459   /*mm4 = d0 c0 b0 a0 \\r
460     mm5 = d1 c1 b1 a1 \\r
461     mm6 = d2 c2 b2 a2 \\r
462     mm7 = d3 c3 b3 a3*/ \\r
463 }\r
464 \r
465 /*MMX implementation of the fDCT.*/\r
466 void oc_enc_fdct8x8_mmxext(ogg_int16_t _y[64],const ogg_int16_t _x[64]){\r
467   OC_ALIGN8(ogg_int16_t buf[64]);\r
468   ptrdiff_t a;\r
469   __asm{\r
470 #define X edx\r
471 #define Y eax\r
472 #define A ecx\r
473 #define BUF esi\r
474     /*Add two extra bits of working precision to improve accuracy; any more and\r
475        we could overflow.*/\r
476     /*We also add biases to correct for some systematic error that remains in\r
477        the full fDCT->iDCT round trip.*/\r
478     mov X, _x\r
479     mov Y, _y\r
480     movq mm0,[0x00+X]\r
481     movq mm1,[0x10+X]\r
482     movq mm2,[0x20+X]\r
483     movq mm3,[0x30+X]\r
484     pcmpeqb mm4,mm4\r
485     pxor mm7,mm7\r
486     movq mm5,mm0\r
487     psllw mm0,2\r
488     pcmpeqw mm5,mm7\r
489     movq mm7,[0x70+X]\r
490     psllw mm1,2\r
491     psubw mm5,mm4\r
492     psllw mm2,2\r
493     mov A,1\r
494     pslld mm5,16\r
495     movd mm6,A\r
496     psllq mm5,16\r
497     mov A,0x10001\r
498     psllw mm3,2\r
499     movd mm4,A\r
500     punpckhwd mm5,mm6\r
501     psubw mm1,mm6\r
502     movq mm6,[0x60+X]\r
503     paddw mm0,mm5\r
504     movq mm5,[0x50+X]\r
505     paddw mm0,mm4\r
506     movq mm4,[0x40+X]\r
507     /*We inline stage1 of the transform here so we can get better instruction\r
508        scheduling with the shifts.*/\r
509     /*mm0=t7'=t0-t7*/\r
510     psllw mm7,2\r
511     psubw mm0,mm7\r
512     psllw mm6,2\r
513     paddw mm7,mm7\r
514     /*mm1=t6'=t1-t6*/\r
515     psllw mm5,2\r
516     psubw mm1,mm6\r
517     psllw mm4,2\r
518     paddw mm6,mm6\r
519     /*mm2=t5'=t2-t5*/\r
520     psubw mm2,mm5\r
521     paddw mm5,mm5\r
522     /*mm3=t4'=t3-t4*/\r
523     psubw mm3,mm4\r
524     paddw mm4,mm4\r
525     /*mm7=t0'=t0+t7*/\r
526     paddw mm7,mm0\r
527     /*mm6=t1'=t1+t6*/\r
528     paddw mm6,mm1\r
529     /*mm5=t2'=t2+t5*/\r
530     paddw mm5,mm2\r
531     /*mm4=t3'=t3+t4*/\r
532     paddw mm4,mm3\r
533     OC_FDCT8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)\r
534     OC_TRANSPOSE8x4(0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70)\r
535     /*Swap out this 8x4 block for the next one.*/\r
536     movq mm0,[0x08+X]\r
537     movq [0x30+Y],mm7\r
538     movq mm7,[0x78+X]\r
539     movq [0x50+Y],mm1\r
540     movq mm1,[0x18+X]\r
541     movq [0x20+Y],mm6\r
542     movq mm6,[0x68+X]\r
543     movq [0x60+Y],mm2\r
544     movq mm2,[0x28+X]\r
545     movq [0x10+Y],mm5\r
546     movq mm5,[0x58+X]\r
547     movq [0x70+Y],mm3\r
548     movq mm3,[0x38+X]\r
549     /*And increase its working precision, too.*/\r
550     psllw mm0,2\r
551     movq [0x00+Y],mm4\r
552     psllw mm7,2\r
553     movq mm4,[0x48+X]\r
554     /*We inline stage1 of the transform here so we can get better instruction\r
555        scheduling with the shifts.*/\r
556     /*mm0=t7'=t0-t7*/\r
557     psubw mm0,mm7\r
558     psllw mm1,2\r
559     paddw mm7,mm7\r
560     psllw mm6,2\r
561     /*mm1=t6'=t1-t6*/\r
562     psubw mm1,mm6\r
563     psllw mm2,2\r
564     paddw mm6,mm6\r
565     psllw mm5,2\r
566     /*mm2=t5'=t2-t5*/\r
567     psubw mm2,mm5\r
568     psllw mm3,2\r
569     paddw mm5,mm5\r
570     psllw mm4,2\r
571     /*mm3=t4'=t3-t4*/\r
572     psubw mm3,mm4\r
573     paddw mm4,mm4\r
574     /*mm7=t0'=t0+t7*/\r
575     paddw mm7,mm0\r
576     /*mm6=t1'=t1+t6*/\r
577     paddw mm6,mm1\r
578     /*mm5=t2'=t2+t5*/\r
579     paddw mm5,mm2\r
580     /*mm4=t3'=t3+t4*/\r
581     paddw mm4,mm3\r
582     OC_FDCT8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)\r
583     OC_TRANSPOSE8x4(0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78)\r
584     /*Here the first 4x4 block of output from the last transpose is the second\r
585        4x4 block of input for the next transform.\r
586       We have cleverly arranged that it already be in the appropriate place,\r
587        so we only have to do half the stores and loads.*/\r
588     movq mm0,[0x00+Y]\r
589     movq [0x58+Y],mm1\r
590     movq mm1,[0x10+Y]\r
591     movq [0x68+Y],mm2\r
592     movq mm2,[0x20+Y]\r
593     movq [0x78+Y],mm3\r
594     movq mm3,[0x30+Y]\r
595     OC_FDCT_STAGE1_8x4\r
596     OC_FDCT8x4(0x00,0x10,0x20,0x30,0x08,0x18,0x28,0x38)\r
597     /*mm0={-2}x4*/\r
598     pcmpeqw mm2,mm2\r
599     paddw mm2,mm2\r
600     /*Round and store the results (no transpose).*/\r
601     movq mm7,[Y+0x10]\r
602     psubw mm4,mm2\r
603     psubw mm6,mm2\r
604     psraw mm4,2\r
605     psubw mm0,mm2\r
606     movq [BUF+0x00],mm4\r
607     movq mm4,[Y+0x30]\r
608     psraw mm6,2\r
609     psubw mm5,mm2\r
610     movq [BUF+0x20],mm6\r
611     psraw mm0,2\r
612     psubw mm3,mm2\r
613     movq [BUF+0x40],mm0\r
614     psraw mm5,2\r
615     psubw mm1,mm2\r
616     movq [BUF+0x50],mm5\r
617     psraw mm3,2\r
618     psubw mm7,mm2\r
619     movq [BUF+0x60],mm3\r
620     psraw mm1,2\r
621     psubw mm4,mm2\r
622     movq [BUF+0x70],mm1\r
623     psraw mm7,2\r
624     movq [BUF+0x10],mm7\r
625     psraw mm4,2\r
626     movq [BUF+0x30],mm4\r
627     /*Load the next block.*/\r
628     movq mm0,[0x40+Y]\r
629     movq mm7,[0x78+Y]\r
630     movq mm1,[0x50+Y]\r
631     movq mm6,[0x68+Y]\r
632     movq mm2,[0x60+Y]\r
633     movq mm5,[0x58+Y]\r
634     movq mm3,[0x70+Y]\r
635     movq mm4,[0x48+Y]\r
636     OC_FDCT_STAGE1_8x4\r
637     OC_FDCT8x4(0x40,0x50,0x60,0x70,0x48,0x58,0x68,0x78)\r
638     /*mm0={-2}x4*/\r
639     pcmpeqw mm2,mm2\r
640     paddw mm2,mm2\r
641     /*Round and store the results (no transpose).*/\r
642     movq mm7,[Y+0x50]\r
643     psubw mm4,mm2\r
644     psubw mm6,mm2\r
645     psraw mm4,2\r
646     psubw mm0,mm2\r
647     movq [BUF+0x08],mm4\r
648     movq mm4,[Y+0x70]\r
649     psraw mm6,2\r
650     psubw mm5,mm2\r
651     movq [BUF+0x28],mm6\r
652     psraw mm0,2\r
653     psubw mm3,mm2\r
654     movq [BUF+0x48],mm0\r
655     psraw mm5,2\r
656     psubw mm1,mm2\r
657     movq [BUF+0x58],mm5\r
658     psraw mm3,2\r
659     psubw mm7,mm2\r
660     movq [BUF+0x68],mm3\r
661     psraw mm1,2\r
662     psubw mm4,mm2\r
663     movq [BUF+0x78],mm1\r
664     psraw mm7,2\r
665     movq [BUF+0x18],mm7\r
666     psraw mm4,2\r
667     movq [BUF+0x38],mm4\r
668 #define OC_ZZ_LOAD_ROW_LO(_row,_reg) \\r
669     __asm movq _reg,[BUF+16*(_row)] \\r
670 \r
671 #define OC_ZZ_LOAD_ROW_HI(_row,_reg) \\r
672     __asm movq _reg,[BUF+16*(_row)+8] \\r
673 \r
674     OC_TRANSPOSE_ZIG_ZAG_MMXEXT\r
675 #undef OC_ZZ_LOAD_ROW_LO\r
676 #undef OC_ZZ_LOAD_ROW_HI\r
677 #undef X\r
678 #undef Y\r
679 #undef A\r
680 #undef BUF\r
681   }\r
682 }\r
683 \r
684 #endif\r