/******************************************************************** * * * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE Theora SOURCE CODE IS COPYRIGHT (C) 1999-2006 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ********************************************************************/ /*MMX fDCT implementation for x86_32*/ /*$Id: fdct_ses2.c 14579 2008-03-12 06:42:40Z xiphmont $*/ #include "x86enc.h" #if defined(OC_X86_ASM) # define OC_FDCT_STAGE1_8x4 \ "#OC_FDCT_STAGE1_8x4\n\t" \ /*Stage 1:*/ \ /*mm0=t7'=t0-t7*/ \ "psubw %%mm7,%%mm0\n\t" \ "paddw %%mm7,%%mm7\n\t" \ /*mm1=t6'=t1-t6*/ \ "psubw %%mm6,%%mm1\n\t" \ "paddw %%mm6,%%mm6\n\t" \ /*mm2=t5'=t2-t5*/ \ "psubw %%mm5,%%mm2\n\t" \ "paddw %%mm5,%%mm5\n\t" \ /*mm3=t4'=t3-t4*/ \ "psubw %%mm4,%%mm3\n\t" \ "paddw %%mm4,%%mm4\n\t" \ /*mm7=t0'=t0+t7*/ \ "paddw %%mm0,%%mm7\n\t" \ /*mm6=t1'=t1+t6*/ \ "paddw %%mm1,%%mm6\n\t" \ /*mm5=t2'=t2+t5*/ \ "paddw %%mm2,%%mm5\n\t" \ /*mm4=t3'=t3+t4*/ \ "paddw %%mm3,%%mm4\n\t" \ # define OC_FDCT8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) \ "#OC_FDCT8x4\n\t" \ /*Stage 2:*/ \ /*mm7=t3''=t0'-t3'*/ \ "psubw %%mm4,%%mm7\n\t" \ "paddw %%mm4,%%mm4\n\t" \ /*mm6=t2''=t1'-t2'*/ \ "psubw %%mm5,%%mm6\n\t" \ "movq %%mm7,"_r6"(%[y])\n\t" \ "paddw %%mm5,%%mm5\n\t" \ /*mm1=t5''=t6'-t5'*/ \ "psubw %%mm2,%%mm1\n\t" \ "movq %%mm6,"_r2"(%[y])\n\t" \ /*mm4=t0''=t0'+t3'*/ \ "paddw %%mm7,%%mm4\n\t" \ "paddw %%mm2,%%mm2\n\t" \ /*mm5=t1''=t1'+t2'*/ \ "movq %%mm4,"_r0"(%[y])\n\t" \ "paddw %%mm6,%%mm5\n\t" \ /*mm2=t6''=t6'+t5'*/ \ "paddw %%mm1,%%mm2\n\t" \ "movq %%mm5,"_r4"(%[y])\n\t" \ /*mm0=t7', mm1=t5'', mm2=t6'', mm3=t4'.*/ \ /*mm4, mm5, mm6, mm7 are free.*/ \ /*Stage 3:*/ \ /*mm6={2}x4, mm7={27146,0xB500>>1}x2*/ \ "mov $0x5A806A0A,%[a]\n\t" \ "pcmpeqb %%mm6,%%mm6\n\t" \ "movd %[a],%%mm7\n\t" \ "psrlw $15,%%mm6\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddw %%mm6,%%mm6\n\t" \ /*mm0=0, m2={-1}x4 \ mm5:mm4=t5''*27146+0xB500*/ \ "movq %%mm1,%%mm4\n\t" \ "movq %%mm1,%%mm5\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "movq %%mm2,"_r3"(%[y])\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "movq %%mm0,"_r7"(%[y])\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "pxor %%mm0,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pcmpeqb %%mm2,%%mm2\n\t" \ /*mm2=t6'', mm1=t5''+(t5''!=0) \ mm4=(t5''*27146+0xB500>>16)*/ \ "pcmpeqw %%mm1,%%mm0\n\t" \ "psrad $16,%%mm4\n\t" \ "psubw %%mm2,%%mm0\n\t" \ "movq "_r3"(%[y]),%%mm2\n\t" \ "psrad $16,%%mm5\n\t" \ "paddw %%mm0,%%mm1\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ /*mm4=s=(t5''*27146+0xB500>>16)+t5''+(t5''!=0)>>1*/ \ "paddw %%mm1,%%mm4\n\t" \ "movq "_r7"(%[y]),%%mm0\n\t" \ "psraw $1,%%mm4\n\t" \ "movq %%mm3,%%mm1\n\t" \ /*mm3=t4''=t4'+s*/ \ "paddw %%mm4,%%mm3\n\t" \ /*mm1=t5'''=t4'-s*/ \ "psubw %%mm4,%%mm1\n\t" \ /*mm1=0, mm3={-1}x4 \ mm5:mm4=t6''*27146+0xB500*/ \ "movq %%mm2,%%mm4\n\t" \ "movq %%mm2,%%mm5\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "movq %%mm1,"_r5"(%[y])\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "movq %%mm3,"_r1"(%[y])\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "pxor %%mm1,%%mm1\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pcmpeqb %%mm3,%%mm3\n\t" \ /*mm2=t6''+(t6''!=0), mm4=(t6''*27146+0xB500>>16)*/ \ "psrad $16,%%mm4\n\t" \ "pcmpeqw %%mm2,%%mm1\n\t" \ "psrad $16,%%mm5\n\t" \ "psubw %%mm3,%%mm1\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "paddw %%mm1,%%mm2\n\t" \ /*mm1=t1'' \ mm4=s=(t6''*27146+0xB500>>16)+t6''+(t6''!=0)>>1*/ \ "paddw %%mm2,%%mm4\n\t" \ "movq "_r4"(%[y]),%%mm1\n\t" \ "psraw $1,%%mm4\n\t" \ "movq %%mm0,%%mm2\n\t" \ /*mm7={54491-0x7FFF,0x7FFF}x2 \ mm0=t7''=t7'+s*/ \ "paddw %%mm4,%%mm0\n\t" \ /*mm2=t6'''=t7'-s*/ \ "psubw %%mm4,%%mm2\n\t" \ /*Stage 4:*/ \ /*mm0=0, mm2=t0'' \ mm5:mm4=t1''*27146+0xB500*/ \ "movq %%mm1,%%mm4\n\t" \ "movq %%mm1,%%mm5\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "movq %%mm2,"_r3"(%[y])\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "movq "_r0"(%[y]),%%mm2\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "movq %%mm0,"_r7"(%[y])\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pxor %%mm0,%%mm0\n\t" \ /*mm7={27146,0x4000>>1}x2 \ mm0=s=(t1''*27146+0xB500>>16)+t1''+(t1''!=0)*/ \ "psrad $16,%%mm4\n\t" \ "mov $0x20006A0A,%[a]\n\t" \ "pcmpeqw %%mm1,%%mm0\n\t" \ "movd %[a],%%mm7\n\t" \ "psrad $16,%%mm5\n\t" \ "psubw %%mm3,%%mm0\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "paddw %%mm1,%%mm0\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddw %%mm4,%%mm0\n\t" \ /*mm6={0x00000E3D}x2 \ mm1=-(t0''==0), mm5:mm4=t0''*27146+0x4000*/ \ "movq %%mm2,%%mm4\n\t" \ "movq %%mm2,%%mm5\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "mov $0x0E3D,%[a]\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "movd %[a],%%mm6\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pxor %%mm1,%%mm1\n\t" \ "punpckldq %%mm6,%%mm6\n\t" \ "pcmpeqw %%mm2,%%mm1\n\t" \ /*mm4=r=(t0''*27146+0x4000>>16)+t0''+(t0''!=0)*/ \ "psrad $16,%%mm4\n\t" \ "psubw %%mm3,%%mm1\n\t" \ "psrad $16,%%mm5\n\t" \ "paddw %%mm1,%%mm2\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "movq "_r5"(%[y]),%%mm1\n\t" \ "paddw %%mm2,%%mm4\n\t" \ /*mm2=t6'', mm0=_y[0]=u=r+s>>1 \ The naive implementation could cause overflow, so we use \ u=(r&s)+((r^s)>>1).*/ \ "movq "_r3"(%[y]),%%mm2\n\t" \ "movq %%mm0,%%mm7\n\t" \ "pxor %%mm4,%%mm0\n\t" \ "pand %%mm4,%%mm7\n\t" \ "psraw $1,%%mm0\n\t" \ "mov $0x7FFF54DC,%[a]\n\t" \ "paddw %%mm7,%%mm0\n\t" \ "movd %[a],%%mm7\n\t" \ /*mm7={54491-0x7FFF,0x7FFF}x2 \ mm4=_y[4]=v=r-u*/ \ "psubw %%mm0,%%mm4\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "movq %%mm4,"_r4"(%[y])\n\t" \ /*mm0=0, mm7={36410}x4 \ mm1=(t5'''!=0), mm5:mm4=54491*t5'''+0x0E3D*/ \ "movq %%mm1,%%mm4\n\t" \ "movq %%mm1,%%mm5\n\t" \ "punpcklwd %%mm1,%%mm4\n\t" \ "mov $0x8E3A8E3A,%[a]\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "movq %%mm0,"_r0"(%[y])\n\t" \ "punpckhwd %%mm1,%%mm5\n\t" \ "pxor %%mm0,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pcmpeqw %%mm0,%%mm1\n\t" \ "movd %[a],%%mm7\n\t" \ "psubw %%mm3,%%mm1\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddd %%mm6,%%mm4\n\t" \ "paddd %%mm6,%%mm5\n\t" \ /*mm0=0 \ mm3:mm1=36410*t6'''+((t5'''!=0)<<16)*/ \ "movq %%mm2,%%mm6\n\t" \ "movq %%mm2,%%mm3\n\t" \ "pmulhw %%mm7,%%mm6\n\t" \ "paddw %%mm2,%%mm1\n\t" \ "pmullw %%mm7,%%mm3\n\t" \ "pxor %%mm0,%%mm0\n\t" \ "paddw %%mm1,%%mm6\n\t" \ "movq %%mm3,%%mm1\n\t" \ "punpckhwd %%mm6,%%mm3\n\t" \ "punpcklwd %%mm6,%%mm1\n\t" \ /*mm3={-1}x4, mm6={1}x4 \ mm4=_y[5]=u=(54491*t5'''+36410*t6'''+0x0E3D>>16)+(t5'''!=0)*/ \ "paddd %%mm3,%%mm5\n\t" \ "paddd %%mm1,%%mm4\n\t" \ "psrad $16,%%mm5\n\t" \ "pxor %%mm6,%%mm6\n\t" \ "psrad $16,%%mm4\n\t" \ "pcmpeqb %%mm3,%%mm3\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "psubw %%mm3,%%mm6\n\t" \ /*mm1=t7'', mm7={26568,0x3400}x2 \ mm2=s=t6'''-(36410*u>>16)*/ \ "movq %%mm4,%%mm1\n\t" \ "mov $0x340067C8,%[a]\n\t" \ "pmulhw %%mm7,%%mm4\n\t" \ "movd %[a],%%mm7\n\t" \ "movq %%mm1,"_r5"(%[y])\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddw %%mm1,%%mm4\n\t" \ "movq "_r7"(%[y]),%%mm1\n\t" \ "psubw %%mm4,%%mm2\n\t" \ /*mm6={0x00007B1B}x2 \ mm0=(s!=0), mm5:mm4=s*26568+0x3400*/ \ "movq %%mm2,%%mm4\n\t" \ "movq %%mm2,%%mm5\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "pcmpeqw %%mm2,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "mov $0x7B1B,%[a]\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "movd %[a],%%mm6\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "psubw %%mm3,%%mm0\n\t" \ "punpckldq %%mm6,%%mm6\n\t" \ /*mm7={64277-0x7FFF,0x7FFF}x2 \ mm2=_y[3]=v=(s*26568+0x3400>>17)+s+(s!=0)*/ \ "psrad $17,%%mm4\n\t" \ "paddw %%mm0,%%mm2\n\t" \ "psrad $17,%%mm5\n\t" \ "mov $0x7FFF7B16,%[a]\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "movd %[a],%%mm7\n\t" \ "paddw %%mm4,%%mm2\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ /*mm0=0, mm7={12785}x4 \ mm1=(t7''!=0), mm2=t4'', mm5:mm4=64277*t7''+0x7B1B*/ \ "movq %%mm1,%%mm4\n\t" \ "movq %%mm1,%%mm5\n\t" \ "movq %%mm2,"_r3"(%[y])\n\t" \ "punpcklwd %%mm1,%%mm4\n\t" \ "movq "_r1"(%[y]),%%mm2\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "mov $0x31F131F1,%[a]\n\t" \ "punpckhwd %%mm1,%%mm5\n\t" \ "pxor %%mm0,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "pcmpeqw %%mm0,%%mm1\n\t" \ "movd %[a],%%mm7\n\t" \ "psubw %%mm3,%%mm1\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddd %%mm6,%%mm4\n\t" \ "paddd %%mm6,%%mm5\n\t" \ /*mm3:mm1=12785*t4'''+((t7''!=0)<<16)*/ \ "movq %%mm2,%%mm6\n\t" \ "movq %%mm2,%%mm3\n\t" \ "pmulhw %%mm7,%%mm6\n\t" \ "pmullw %%mm7,%%mm3\n\t" \ "paddw %%mm1,%%mm6\n\t" \ "movq %%mm3,%%mm1\n\t" \ "punpckhwd %%mm6,%%mm3\n\t" \ "punpcklwd %%mm6,%%mm1\n\t" \ /*mm3={-1}x4, mm6={1}x4 \ mm4=_y[1]=u=(12785*t4'''+64277*t7''+0x7B1B>>16)+(t7''!=0)*/ \ "paddd %%mm3,%%mm5\n\t" \ "paddd %%mm1,%%mm4\n\t" \ "psrad $16,%%mm5\n\t" \ "pxor %%mm6,%%mm6\n\t" \ "psrad $16,%%mm4\n\t" \ "pcmpeqb %%mm3,%%mm3\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "psubw %%mm3,%%mm6\n\t" \ /*mm1=t3'', mm7={20539,0x3000}x2 \ mm4=s=(12785*u>>16)-t4''*/ \ "movq %%mm4,"_r1"(%[y])\n\t" \ "pmulhw %%mm7,%%mm4\n\t" \ "mov $0x3000503B,%[a]\n\t" \ "movq "_r6"(%[y]),%%mm1\n\t" \ "movd %[a],%%mm7\n\t" \ "psubw %%mm2,%%mm4\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ /*mm6={0x00006CB7}x2 \ mm0=(s!=0), mm5:mm4=s*20539+0x3000*/ \ "movq %%mm4,%%mm5\n\t" \ "movq %%mm4,%%mm2\n\t" \ "punpcklwd %%mm6,%%mm4\n\t" \ "pcmpeqw %%mm2,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "mov $0x6CB7,%[a]\n\t" \ "punpckhwd %%mm6,%%mm5\n\t" \ "movd %[a],%%mm6\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "psubw %%mm3,%%mm0\n\t" \ "punpckldq %%mm6,%%mm6\n\t" \ /*mm7={60547-0x7FFF,0x7FFF}x2 \ mm2=_y[7]=v=(s*20539+0x3000>>20)+s+(s!=0)*/ \ "psrad $20,%%mm4\n\t" \ "paddw %%mm0,%%mm2\n\t" \ "psrad $20,%%mm5\n\t" \ "mov $0x7FFF6C84,%[a]\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ "movd %[a],%%mm7\n\t" \ "paddw %%mm4,%%mm2\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ /*mm0=0, mm7={25080}x4 \ mm2=t2'', mm5:mm4=60547*t3''+0x6CB7*/ \ "movq %%mm1,%%mm4\n\t" \ "movq %%mm1,%%mm5\n\t" \ "movq %%mm2,"_r7"(%[y])\n\t" \ "punpcklwd %%mm1,%%mm4\n\t" \ "movq "_r2"(%[y]),%%mm2\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "mov $0x61F861F8,%[a]\n\t" \ "punpckhwd %%mm1,%%mm5\n\t" \ "pxor %%mm0,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm5\n\t" \ "movd %[a],%%mm7\n\t" \ "pcmpeqw %%mm0,%%mm1\n\t" \ "psubw %%mm3,%%mm1\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "paddd %%mm6,%%mm4\n\t" \ "paddd %%mm6,%%mm5\n\t" \ /*mm3:mm1=25080*t2''+((t3''!=0)<<16)*/ \ "movq %%mm2,%%mm6\n\t" \ "movq %%mm2,%%mm3\n\t" \ "pmulhw %%mm7,%%mm6\n\t" \ "pmullw %%mm7,%%mm3\n\t" \ "paddw %%mm1,%%mm6\n\t" \ "movq %%mm3,%%mm1\n\t" \ "punpckhwd %%mm6,%%mm3\n\t" \ "punpcklwd %%mm6,%%mm1\n\t" \ /*mm1={-1}x4 \ mm4=u=(25080*t2''+60547*t3''+0x6CB7>>16)+(t3''!=0)*/ \ "paddd %%mm3,%%mm5\n\t" \ "paddd %%mm1,%%mm4\n\t" \ "psrad $16,%%mm5\n\t" \ "mov $0x28005460,%[a]\n\t" \ "psrad $16,%%mm4\n\t" \ "pcmpeqb %%mm1,%%mm1\n\t" \ "packssdw %%mm5,%%mm4\n\t" \ /*mm5={1}x4, mm6=_y[2]=u, mm7={21600,0x2800}x2 \ mm4=s=(25080*u>>16)-t2''*/ \ "movq %%mm4,%%mm6\n\t" \ "pmulhw %%mm7,%%mm4\n\t" \ "pxor %%mm5,%%mm5\n\t" \ "movd %[a],%%mm7\n\t" \ "psubw %%mm1,%%mm5\n\t" \ "punpckldq %%mm7,%%mm7\n\t" \ "psubw %%mm2,%%mm4\n\t" \ /*mm2=s+(s!=0) \ mm4:mm3=s*21600+0x2800*/ \ "movq %%mm4,%%mm3\n\t" \ "movq %%mm4,%%mm2\n\t" \ "punpckhwd %%mm5,%%mm4\n\t" \ "pcmpeqw %%mm2,%%mm0\n\t" \ "pmaddwd %%mm7,%%mm4\n\t" \ "psubw %%mm1,%%mm0\n\t" \ "punpcklwd %%mm5,%%mm3\n\t" \ "paddw %%mm0,%%mm2\n\t" \ "pmaddwd %%mm7,%%mm3\n\t" \ /*mm0=_y[4], mm1=_y[7], mm4=_y[0], mm5=_y[5] \ mm3=_y[6]=v=(s*21600+0x2800>>18)+s+(s!=0)*/ \ "movq "_r4"(%[y]),%%mm0\n\t" \ "psrad $18,%%mm4\n\t" \ "movq "_r5"(%[y]),%%mm5\n\t" \ "psrad $18,%%mm3\n\t" \ "movq "_r7"(%[y]),%%mm1\n\t" \ "packssdw %%mm4,%%mm3\n\t" \ "movq "_r0"(%[y]),%%mm4\n\t" \ "paddw %%mm2,%%mm3\n\t" \ /*On input, mm4=_y[0], mm6=_y[2], mm0=_y[4], mm5=_y[5], mm3=_y[6], mm1=_y[7]. On output, {_y[4],mm1,mm2,mm3} contains the transpose of _y[4...7] and {mm4,mm5,mm6,mm7} contains the transpose of _y[0...3].*/ # define OC_TRANSPOSE8x4(_r0,_r1,_r2,_r3,_r4,_r5,_r6,_r7) \ "#OC_TRANSPOSE8x4\n\t" \ /*First 4x4 transpose:*/ \ /*mm0 = e3 e2 e1 e0 \ mm5 = f3 f2 f1 f0 \ mm3 = g3 g2 g1 g0 \ mm1 = h3 h2 h1 h0*/ \ "movq %%mm0,%%mm2\n\t" \ "punpcklwd %%mm5,%%mm0\n\t" \ "punpckhwd %%mm5,%%mm2\n\t" \ "movq %%mm3,%%mm5\n\t" \ "punpcklwd %%mm1,%%mm3\n\t" \ "punpckhwd %%mm1,%%mm5\n\t" \ /*mm0 = f1 e1 f0 e0 \ mm2 = f3 e3 f2 e2 \ mm3 = h1 g1 h0 g0 \ mm5 = h3 g3 h2 g2*/ \ "movq %%mm0,%%mm1\n\t" \ "punpckldq %%mm3,%%mm0\n\t" \ "movq %%mm0,"_r4"(%[y])\n\t" \ "punpckhdq %%mm3,%%mm1\n\t" \ "movq "_r1"(%[y]),%%mm0\n\t" \ "movq %%mm2,%%mm3\n\t" \ "punpckldq %%mm5,%%mm2\n\t" \ "punpckhdq %%mm5,%%mm3\n\t" \ "movq "_r3"(%[y]),%%mm5\n\t" \ /*_y[4] = h0 g0 f0 e0 \ mm1 = h1 g1 f1 e1 \ mm2 = h2 g2 f2 e2 \ mm3 = h3 g3 f3 e3*/ \ /*Second 4x4 transpose:*/ \ /*mm4 = a3 a2 a1 a0 \ mm0 = b3 b2 b1 b0 \ mm6 = c3 c2 c1 c0 \ mm5 = d3 d2 d1 d0*/ \ "movq %%mm4,%%mm7\n\t" \ "punpcklwd %%mm0,%%mm4\n\t" \ "punpckhwd %%mm0,%%mm7\n\t" \ "movq %%mm6,%%mm0\n\t" \ "punpcklwd %%mm5,%%mm6\n\t" \ "punpckhwd %%mm5,%%mm0\n\t" \ /*mm4 = b1 a1 b0 a0 \ mm7 = b3 a3 b2 a2 \ mm6 = d1 c1 d0 c0 \ mm0 = d3 c3 d2 c2*/ \ "movq %%mm4,%%mm5\n\t" \ "punpckldq %%mm6,%%mm4\n\t" \ "punpckhdq %%mm6,%%mm5\n\t" \ "movq %%mm7,%%mm6\n\t" \ "punpckhdq %%mm0,%%mm7\n\t" \ "punpckldq %%mm0,%%mm6\n\t" \ /*mm4 = d0 c0 b0 a0 \ mm5 = d1 c1 b1 a1 \ mm6 = d2 c2 b2 a2 \ mm7 = d3 c3 b3 a3*/ \ /*MMX implementation of the fDCT.*/ void oc_enc_fdct8x8_mmx(ogg_int16_t _y[64],const ogg_int16_t _x[64]){ ptrdiff_t a; __asm__ __volatile__( /*Add two extra bits of working precision to improve accuracy; any more and we could overflow.*/ /*We also add biases to correct for some systematic error that remains in the full fDCT->iDCT round trip.*/ "movq 0x00(%[x]),%%mm0\n\t" "movq 0x10(%[x]),%%mm1\n\t" "movq 0x20(%[x]),%%mm2\n\t" "movq 0x30(%[x]),%%mm3\n\t" "pcmpeqb %%mm4,%%mm4\n\t" "pxor %%mm7,%%mm7\n\t" "movq %%mm0,%%mm5\n\t" "psllw $2,%%mm0\n\t" "pcmpeqw %%mm7,%%mm5\n\t" "movq 0x70(%[x]),%%mm7\n\t" "psllw $2,%%mm1\n\t" "psubw %%mm4,%%mm5\n\t" "psllw $2,%%mm2\n\t" "mov $1,%[a]\n\t" "pslld $16,%%mm5\n\t" "movd %[a],%%mm6\n\t" "psllq $16,%%mm5\n\t" "mov $0x10001,%[a]\n\t" "psllw $2,%%mm3\n\t" "movd %[a],%%mm4\n\t" "punpckhwd %%mm6,%%mm5\n\t" "psubw %%mm6,%%mm1\n\t" "movq 0x60(%[x]),%%mm6\n\t" "paddw %%mm5,%%mm0\n\t" "movq 0x50(%[x]),%%mm5\n\t" "paddw %%mm4,%%mm0\n\t" "movq 0x40(%[x]),%%mm4\n\t" /*We inline stage1 of the transform here so we can get better instruction scheduling with the shifts.*/ /*mm0=t7'=t0-t7*/ "psllw $2,%%mm7\n\t" "psubw %%mm7,%%mm0\n\t" "psllw $2,%%mm6\n\t" "paddw %%mm7,%%mm7\n\t" /*mm1=t6'=t1-t6*/ "psllw $2,%%mm5\n\t" "psubw %%mm6,%%mm1\n\t" "psllw $2,%%mm4\n\t" "paddw %%mm6,%%mm6\n\t" /*mm2=t5'=t2-t5*/ "psubw %%mm5,%%mm2\n\t" "paddw %%mm5,%%mm5\n\t" /*mm3=t4'=t3-t4*/ "psubw %%mm4,%%mm3\n\t" "paddw %%mm4,%%mm4\n\t" /*mm7=t0'=t0+t7*/ "paddw %%mm0,%%mm7\n\t" /*mm6=t1'=t1+t6*/ "paddw %%mm1,%%mm6\n\t" /*mm5=t2'=t2+t5*/ "paddw %%mm2,%%mm5\n\t" /*mm4=t3'=t3+t4*/ "paddw %%mm3,%%mm4\n\t" OC_FDCT8x4("0x00","0x10","0x20","0x30","0x40","0x50","0x60","0x70") OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x40","0x50","0x60","0x70") /*Swap out this 8x4 block for the next one.*/ "movq 0x08(%[x]),%%mm0\n\t" "movq %%mm7,0x30(%[y])\n\t" "movq 0x78(%[x]),%%mm7\n\t" "movq %%mm1,0x50(%[y])\n\t" "movq 0x18(%[x]),%%mm1\n\t" "movq %%mm6,0x20(%[y])\n\t" "movq 0x68(%[x]),%%mm6\n\t" "movq %%mm2,0x60(%[y])\n\t" "movq 0x28(%[x]),%%mm2\n\t" "movq %%mm5,0x10(%[y])\n\t" "movq 0x58(%[x]),%%mm5\n\t" "movq %%mm3,0x70(%[y])\n\t" "movq 0x38(%[x]),%%mm3\n\t" /*And increase its working precision, too.*/ "psllw $2,%%mm0\n\t" "movq %%mm4,0x00(%[y])\n\t" "psllw $2,%%mm7\n\t" "movq 0x48(%[x]),%%mm4\n\t" /*We inline stage1 of the transform here so we can get better instruction scheduling with the shifts.*/ /*mm0=t7'=t0-t7*/ "psubw %%mm7,%%mm0\n\t" "psllw $2,%%mm1\n\t" "paddw %%mm7,%%mm7\n\t" "psllw $2,%%mm6\n\t" /*mm1=t6'=t1-t6*/ "psubw %%mm6,%%mm1\n\t" "psllw $2,%%mm2\n\t" "paddw %%mm6,%%mm6\n\t" "psllw $2,%%mm5\n\t" /*mm2=t5'=t2-t5*/ "psubw %%mm5,%%mm2\n\t" "psllw $2,%%mm3\n\t" "paddw %%mm5,%%mm5\n\t" "psllw $2,%%mm4\n\t" /*mm3=t4'=t3-t4*/ "psubw %%mm4,%%mm3\n\t" "paddw %%mm4,%%mm4\n\t" /*mm7=t0'=t0+t7*/ "paddw %%mm0,%%mm7\n\t" /*mm6=t1'=t1+t6*/ "paddw %%mm1,%%mm6\n\t" /*mm5=t2'=t2+t5*/ "paddw %%mm2,%%mm5\n\t" /*mm4=t3'=t3+t4*/ "paddw %%mm3,%%mm4\n\t" OC_FDCT8x4("0x08","0x18","0x28","0x38","0x48","0x58","0x68","0x78") OC_TRANSPOSE8x4("0x08","0x18","0x28","0x38","0x48","0x58","0x68","0x78") /*Here the first 4x4 block of output from the last transpose is the second 4x4 block of input for the next transform. We have cleverly arranged that it already be in the appropriate place, so we only have to do half the stores and loads.*/ "movq 0x00(%[y]),%%mm0\n\t" "movq %%mm1,0x58(%[y])\n\t" "movq 0x10(%[y]),%%mm1\n\t" "movq %%mm2,0x68(%[y])\n\t" "movq 0x20(%[y]),%%mm2\n\t" "movq %%mm3,0x78(%[y])\n\t" "movq 0x30(%[y]),%%mm3\n\t" OC_FDCT_STAGE1_8x4 OC_FDCT8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38") OC_TRANSPOSE8x4("0x00","0x10","0x20","0x30","0x08","0x18","0x28","0x38") /*mm0={-2}x4*/ "pcmpeqw %%mm0,%%mm0\n\t" "paddw %%mm0,%%mm0\n\t" /*Round the results.*/ "psubw %%mm0,%%mm1\n\t" "psubw %%mm0,%%mm2\n\t" "psraw $2,%%mm1\n\t" "psubw %%mm0,%%mm3\n\t" "movq %%mm1,0x18(%[y])\n\t" "psraw $2,%%mm2\n\t" "psubw %%mm0,%%mm4\n\t" "movq 0x08(%[y]),%%mm1\n\t" "psraw $2,%%mm3\n\t" "psubw %%mm0,%%mm5\n\t" "psraw $2,%%mm4\n\t" "psubw %%mm0,%%mm6\n\t" "psraw $2,%%mm5\n\t" "psubw %%mm0,%%mm7\n\t" "psraw $2,%%mm6\n\t" "psubw %%mm0,%%mm1\n\t" "psraw $2,%%mm7\n\t" "movq 0x40(%[y]),%%mm0\n\t" "psraw $2,%%mm1\n\t" "movq %%mm7,0x30(%[y])\n\t" "movq 0x78(%[y]),%%mm7\n\t" "movq %%mm1,0x08(%[y])\n\t" "movq 0x50(%[y]),%%mm1\n\t" "movq %%mm6,0x20(%[y])\n\t" "movq 0x68(%[y]),%%mm6\n\t" "movq %%mm2,0x28(%[y])\n\t" "movq 0x60(%[y]),%%mm2\n\t" "movq %%mm5,0x10(%[y])\n\t" "movq 0x58(%[y]),%%mm5\n\t" "movq %%mm3,0x38(%[y])\n\t" "movq 0x70(%[y]),%%mm3\n\t" "movq %%mm4,0x00(%[y])\n\t" "movq 0x48(%[y]),%%mm4\n\t" OC_FDCT_STAGE1_8x4 OC_FDCT8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78") OC_TRANSPOSE8x4("0x40","0x50","0x60","0x70","0x48","0x58","0x68","0x78") /*mm0={-2}x4*/ "pcmpeqw %%mm0,%%mm0\n\t" "paddw %%mm0,%%mm0\n\t" /*Round the results.*/ "psubw %%mm0,%%mm1\n\t" "psubw %%mm0,%%mm2\n\t" "psraw $2,%%mm1\n\t" "psubw %%mm0,%%mm3\n\t" "movq %%mm1,0x58(%[y])\n\t" "psraw $2,%%mm2\n\t" "psubw %%mm0,%%mm4\n\t" "movq 0x48(%[y]),%%mm1\n\t" "psraw $2,%%mm3\n\t" "psubw %%mm0,%%mm5\n\t" "movq %%mm2,0x68(%[y])\n\t" "psraw $2,%%mm4\n\t" "psubw %%mm0,%%mm6\n\t" "movq %%mm3,0x78(%[y])\n\t" "psraw $2,%%mm5\n\t" "psubw %%mm0,%%mm7\n\t" "movq %%mm4,0x40(%[y])\n\t" "psraw $2,%%mm6\n\t" "psubw %%mm0,%%mm1\n\t" "movq %%mm5,0x50(%[y])\n\t" "psraw $2,%%mm7\n\t" "movq %%mm6,0x60(%[y])\n\t" "psraw $2,%%mm1\n\t" "movq %%mm7,0x70(%[y])\n\t" "movq %%mm1,0x48(%[y])\n\t" :[a]"=&r"(a) :[y]"r"(_y),[x]"r"(_x) :"memory" ); } #endif