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