summaryrefslogtreecommitdiffstats
path: root/media/libtheora/lib/x86_vc
diff options
context:
space:
mode:
Diffstat (limited to 'media/libtheora/lib/x86_vc')
-rw-r--r--media/libtheora/lib/x86_vc/mmxfrag.c416
-rw-r--r--media/libtheora/lib/x86_vc/mmxidct.c597
-rw-r--r--media/libtheora/lib/x86_vc/mmxloop.h219
-rw-r--r--media/libtheora/lib/x86_vc/mmxstate.c176
-rw-r--r--media/libtheora/lib/x86_vc/x86cpu.c192
-rw-r--r--media/libtheora/lib/x86_vc/x86cpu.h36
-rw-r--r--media/libtheora/lib/x86_vc/x86int.h49
-rw-r--r--media/libtheora/lib/x86_vc/x86state.c61
8 files changed, 1746 insertions, 0 deletions
diff --git a/media/libtheora/lib/x86_vc/mmxfrag.c b/media/libtheora/lib/x86_vc/mmxfrag.c
new file mode 100644
index 000000000..c16b026ff
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/mmxfrag.c
@@ -0,0 +1,416 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxfrag.c 17446 2010-09-23 20:06:20Z tterribe $
+
+ ********************************************************************/
+
+/*MMX acceleration of fragment reconstruction for motion compensation.
+ Originally written by Rudolf Marek.
+ Additional optimization by Nils Pipenbrinck.
+ Note: Loops are unrolled for best performance.
+ The iteration each instruction belongs to is marked in the comments as #i.*/
+#include <stddef.h>
+#include "x86int.h"
+
+#if defined(OC_X86_ASM)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
+# define OC_FRAG_COPY_MMX(_dst,_src,_ystride) \
+ do{ \
+ const unsigned char *src; \
+ unsigned char *dst; \
+ src=(_src); \
+ dst=(_dst); \
+ __asm mov SRC,src \
+ __asm mov DST,dst \
+ __asm mov YSTRIDE,_ystride \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*ystride3=ystride*3*/ \
+ __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*Pointer to next 4.*/ \
+ __asm lea SRC,[SRC+YSTRIDE*4] \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ /*Pointer to next 4.*/ \
+ __asm lea DST,[DST+YSTRIDE*4] \
+ /*src+0*ystride*/ \
+ __asm movq mm0,[SRC] \
+ /*src+1*ystride*/ \
+ __asm movq mm1,[SRC+YSTRIDE] \
+ /*src+2*ystride*/ \
+ __asm movq mm2,[SRC+YSTRIDE*2] \
+ /*src+3*ystride*/ \
+ __asm movq mm3,[SRC+YSTRIDE3] \
+ /*dst+0*ystride*/ \
+ __asm movq [DST],mm0 \
+ /*dst+1*ystride*/ \
+ __asm movq [DST+YSTRIDE],mm1 \
+ /*dst+2*ystride*/ \
+ __asm movq [DST+YSTRIDE*2],mm2 \
+ /*dst+3*ystride*/ \
+ __asm movq [DST+YSTRIDE3],mm3 \
+ } \
+ while(0)
+
+/*Copies an 8x8 block of pixels from _src to _dst, assuming _ystride bytes
+ between rows.*/
+void oc_frag_copy_mmx(unsigned char *_dst,
+ const unsigned char *_src,int _ystride){
+#define SRC edx
+#define DST eax
+#define YSTRIDE ecx
+#define YSTRIDE3 esi
+ OC_FRAG_COPY_MMX(_dst,_src,_ystride);
+#undef SRC
+#undef DST
+#undef YSTRIDE
+#undef YSTRIDE3
+}
+
+/*Copies the fragments specified by the lists of fragment indices from one
+ frame to another.
+ _dst_frame: The reference frame to copy to.
+ _src_frame: The reference frame to copy from.
+ _ystride: The row stride of the reference frames.
+ _fragis: A pointer to a list of fragment indices.
+ _nfragis: The number of fragment indices to copy.
+ _frag_buf_offs: The offsets of fragments in the reference frames.*/
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs){
+ ptrdiff_t fragii;
+ for(fragii=0;fragii<_nfragis;fragii++){
+ ptrdiff_t frag_buf_off;
+ frag_buf_off=_frag_buf_offs[_fragis[fragii]];
+#define SRC edx
+#define DST eax
+#define YSTRIDE ecx
+#define YSTRIDE3 edi
+ OC_FRAG_COPY_MMX(_dst_frame+frag_buf_off,
+ _src_frame+frag_buf_off,_ystride);
+#undef SRC
+#undef DST
+#undef YSTRIDE
+#undef YSTRIDE3
+ }
+}
+
+void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
+ const ogg_int16_t *_residue){
+ __asm{
+#define DST edx
+#define DST4 esi
+#define YSTRIDE eax
+#define YSTRIDE3 edi
+#define RESIDUE ecx
+ mov DST,_dst
+ mov YSTRIDE,_ystride
+ mov RESIDUE,_residue
+ lea DST4,[DST+YSTRIDE*4]
+ lea YSTRIDE3,[YSTRIDE+YSTRIDE*2]
+ /*Set mm0 to 0xFFFFFFFFFFFFFFFF.*/
+ pcmpeqw mm0,mm0
+ /*#0 Load low residue.*/
+ movq mm1,[0*8+RESIDUE]
+ /*#0 Load high residue.*/
+ movq mm2,[1*8+RESIDUE]
+ /*Set mm0 to 0x8000800080008000.*/
+ psllw mm0,15
+ /*#1 Load low residue.*/
+ movq mm3,[2*8+RESIDUE]
+ /*#1 Load high residue.*/
+ movq mm4,[3*8+RESIDUE]
+ /*Set mm0 to 0x0080008000800080.*/
+ psrlw mm0,8
+ /*#2 Load low residue.*/
+ movq mm5,[4*8+RESIDUE]
+ /*#2 Load high residue.*/
+ movq mm6,[5*8+RESIDUE]
+ /*#0 Bias low residue.*/
+ paddsw mm1,mm0
+ /*#0 Bias high residue.*/
+ paddsw mm2,mm0
+ /*#0 Pack to byte.*/
+ packuswb mm1,mm2
+ /*#1 Bias low residue.*/
+ paddsw mm3,mm0
+ /*#1 Bias high residue.*/
+ paddsw mm4,mm0
+ /*#1 Pack to byte.*/
+ packuswb mm3,mm4
+ /*#2 Bias low residue.*/
+ paddsw mm5,mm0
+ /*#2 Bias high residue.*/
+ paddsw mm6,mm0
+ /*#2 Pack to byte.*/
+ packuswb mm5,mm6
+ /*#0 Write row.*/
+ movq [DST],mm1
+ /*#1 Write row.*/
+ movq [DST+YSTRIDE],mm3
+ /*#2 Write row.*/
+ movq [DST+YSTRIDE*2],mm5
+ /*#3 Load low residue.*/
+ movq mm1,[6*8+RESIDUE]
+ /*#3 Load high residue.*/
+ movq mm2,[7*8+RESIDUE]
+ /*#4 Load high residue.*/
+ movq mm3,[8*8+RESIDUE]
+ /*#4 Load high residue.*/
+ movq mm4,[9*8+RESIDUE]
+ /*#5 Load high residue.*/
+ movq mm5,[10*8+RESIDUE]
+ /*#5 Load high residue.*/
+ movq mm6,[11*8+RESIDUE]
+ /*#3 Bias low residue.*/
+ paddsw mm1,mm0
+ /*#3 Bias high residue.*/
+ paddsw mm2,mm0
+ /*#3 Pack to byte.*/
+ packuswb mm1,mm2
+ /*#4 Bias low residue.*/
+ paddsw mm3,mm0
+ /*#4 Bias high residue.*/
+ paddsw mm4,mm0
+ /*#4 Pack to byte.*/
+ packuswb mm3,mm4
+ /*#5 Bias low residue.*/
+ paddsw mm5,mm0
+ /*#5 Bias high residue.*/
+ paddsw mm6,mm0
+ /*#5 Pack to byte.*/
+ packuswb mm5,mm6
+ /*#3 Write row.*/
+ movq [DST+YSTRIDE3],mm1
+ /*#4 Write row.*/
+ movq [DST4],mm3
+ /*#5 Write row.*/
+ movq [DST4+YSTRIDE],mm5
+ /*#6 Load low residue.*/
+ movq mm1,[12*8+RESIDUE]
+ /*#6 Load high residue.*/
+ movq mm2,[13*8+RESIDUE]
+ /*#7 Load low residue.*/
+ movq mm3,[14*8+RESIDUE]
+ /*#7 Load high residue.*/
+ movq mm4,[15*8+RESIDUE]
+ /*#6 Bias low residue.*/
+ paddsw mm1,mm0
+ /*#6 Bias high residue.*/
+ paddsw mm2,mm0
+ /*#6 Pack to byte.*/
+ packuswb mm1,mm2
+ /*#7 Bias low residue.*/
+ paddsw mm3,mm0
+ /*#7 Bias high residue.*/
+ paddsw mm4,mm0
+ /*#7 Pack to byte.*/
+ packuswb mm3,mm4
+ /*#6 Write row.*/
+ movq [DST4+YSTRIDE*2],mm1
+ /*#7 Write row.*/
+ movq [DST4+YSTRIDE3],mm3
+#undef DST
+#undef DST4
+#undef YSTRIDE
+#undef YSTRIDE3
+#undef RESIDUE
+ }
+}
+
+void oc_frag_recon_inter_mmx(unsigned char *_dst,const unsigned char *_src,
+ int _ystride,const ogg_int16_t *_residue){
+ int i;
+ /*Zero mm0.*/
+ __asm pxor mm0,mm0;
+ for(i=4;i-->0;){
+ __asm{
+#define DST edx
+#define SRC ecx
+#define YSTRIDE edi
+#define RESIDUE eax
+ mov DST,_dst
+ mov SRC,_src
+ mov YSTRIDE,_ystride
+ mov RESIDUE,_residue
+ /*#0 Load source.*/
+ movq mm3,[SRC]
+ /*#1 Load source.*/
+ movq mm7,[SRC+YSTRIDE]
+ /*#0 Get copy of src.*/
+ movq mm4,mm3
+ /*#0 Expand high source.*/
+ punpckhbw mm4,mm0
+ /*#0 Expand low source.*/
+ punpcklbw mm3,mm0
+ /*#0 Add residue high.*/
+ paddsw mm4,[8+RESIDUE]
+ /*#1 Get copy of src.*/
+ movq mm2,mm7
+ /*#0 Add residue low.*/
+ paddsw mm3,[RESIDUE]
+ /*#1 Expand high source.*/
+ punpckhbw mm2,mm0
+ /*#0 Pack final row pixels.*/
+ packuswb mm3,mm4
+ /*#1 Expand low source.*/
+ punpcklbw mm7,mm0
+ /*#1 Add residue low.*/
+ paddsw mm7,[16+RESIDUE]
+ /*#1 Add residue high.*/
+ paddsw mm2,[24+RESIDUE]
+ /*Advance residue.*/
+ lea RESIDUE,[32+RESIDUE]
+ /*#1 Pack final row pixels.*/
+ packuswb mm7,mm2
+ /*Advance src.*/
+ lea SRC,[SRC+YSTRIDE*2]
+ /*#0 Write row.*/
+ movq [DST],mm3
+ /*#1 Write row.*/
+ movq [DST+YSTRIDE],mm7
+ /*Advance dst.*/
+ lea DST,[DST+YSTRIDE*2]
+ mov _residue,RESIDUE
+ mov _dst,DST
+ mov _src,SRC
+#undef DST
+#undef SRC
+#undef YSTRIDE
+#undef RESIDUE
+ }
+ }
+}
+
+void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue){
+ int i;
+ /*Zero mm7.*/
+ __asm pxor mm7,mm7;
+ for(i=4;i-->0;){
+ __asm{
+#define SRC1 ecx
+#define SRC2 edi
+#define YSTRIDE esi
+#define RESIDUE edx
+#define DST eax
+ mov YSTRIDE,_ystride
+ mov DST,_dst
+ mov RESIDUE,_residue
+ mov SRC1,_src1
+ mov SRC2,_src2
+ /*#0 Load src1.*/
+ movq mm0,[SRC1]
+ /*#0 Load src2.*/
+ movq mm2,[SRC2]
+ /*#0 Copy src1.*/
+ movq mm1,mm0
+ /*#0 Copy src2.*/
+ movq mm3,mm2
+ /*#1 Load src1.*/
+ movq mm4,[SRC1+YSTRIDE]
+ /*#0 Unpack lower src1.*/
+ punpcklbw mm0,mm7
+ /*#1 Load src2.*/
+ movq mm5,[SRC2+YSTRIDE]
+ /*#0 Unpack higher src1.*/
+ punpckhbw mm1,mm7
+ /*#0 Unpack lower src2.*/
+ punpcklbw mm2,mm7
+ /*#0 Unpack higher src2.*/
+ punpckhbw mm3,mm7
+ /*Advance src1 ptr.*/
+ lea SRC1,[SRC1+YSTRIDE*2]
+ /*Advance src2 ptr.*/
+ lea SRC2,[SRC2+YSTRIDE*2]
+ /*#0 Lower src1+src2.*/
+ paddsw mm0,mm2
+ /*#0 Higher src1+src2.*/
+ paddsw mm1,mm3
+ /*#1 Copy src1.*/
+ movq mm2,mm4
+ /*#0 Build lo average.*/
+ psraw mm0,1
+ /*#1 Copy src2.*/
+ movq mm3,mm5
+ /*#1 Unpack lower src1.*/
+ punpcklbw mm4,mm7
+ /*#0 Build hi average.*/
+ psraw mm1,1
+ /*#1 Unpack higher src1.*/
+ punpckhbw mm2,mm7
+ /*#0 low+=residue.*/
+ paddsw mm0,[RESIDUE]
+ /*#1 Unpack lower src2.*/
+ punpcklbw mm5,mm7
+ /*#0 high+=residue.*/
+ paddsw mm1,[8+RESIDUE]
+ /*#1 Unpack higher src2.*/
+ punpckhbw mm3,mm7
+ /*#1 Lower src1+src2.*/
+ paddsw mm5,mm4
+ /*#0 Pack and saturate.*/
+ packuswb mm0,mm1
+ /*#1 Higher src1+src2.*/
+ paddsw mm3,mm2
+ /*#0 Write row.*/
+ movq [DST],mm0
+ /*#1 Build lo average.*/
+ psraw mm5,1
+ /*#1 Build hi average.*/
+ psraw mm3,1
+ /*#1 low+=residue.*/
+ paddsw mm5,[16+RESIDUE]
+ /*#1 high+=residue.*/
+ paddsw mm3,[24+RESIDUE]
+ /*#1 Pack and saturate.*/
+ packuswb mm5,mm3
+ /*#1 Write row ptr.*/
+ movq [DST+YSTRIDE],mm5
+ /*Advance residue ptr.*/
+ add RESIDUE,32
+ /*Advance dest ptr.*/
+ lea DST,[DST+YSTRIDE*2]
+ mov _dst,DST
+ mov _residue,RESIDUE
+ mov _src1,SRC1
+ mov _src2,SRC2
+#undef SRC1
+#undef SRC2
+#undef YSTRIDE
+#undef RESIDUE
+#undef DST
+ }
+ }
+}
+
+void oc_restore_fpu_mmx(void){
+ __asm emms;
+}
+
+#endif
diff --git a/media/libtheora/lib/x86_vc/mmxidct.c b/media/libtheora/lib/x86_vc/mmxidct.c
new file mode 100644
index 000000000..53a9ac7f3
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/mmxidct.c
@@ -0,0 +1,597 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxidct.c 17446 2010-09-23 20:06:20Z tterribe $
+
+ ********************************************************************/
+
+/*MMX acceleration of Theora's iDCT.
+ Originally written by Rudolf Marek, based on code from On2's VP3.*/
+#include "x86int.h"
+#include "../dct.h"
+
+#if defined(OC_X86_ASM)
+
+/*These are offsets into the table of constants below.*/
+/*7 rows of cosines, in order: pi/16 * (1 ... 7).*/
+#define OC_COSINE_OFFSET (8)
+/*A row of 8's.*/
+#define OC_EIGHT_OFFSET (0)
+
+
+
+/*A table of constants used by the MMX routines.*/
+static const OC_ALIGN16(ogg_uint16_t) OC_IDCT_CONSTS[(1+7)*4]={
+ 8, 8, 8, 8,
+ (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
+ (ogg_uint16_t)OC_C1S7,(ogg_uint16_t)OC_C1S7,
+ (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
+ (ogg_uint16_t)OC_C2S6,(ogg_uint16_t)OC_C2S6,
+ (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
+ (ogg_uint16_t)OC_C3S5,(ogg_uint16_t)OC_C3S5,
+ (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
+ (ogg_uint16_t)OC_C4S4,(ogg_uint16_t)OC_C4S4,
+ (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
+ (ogg_uint16_t)OC_C5S3,(ogg_uint16_t)OC_C5S3,
+ (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
+ (ogg_uint16_t)OC_C6S2,(ogg_uint16_t)OC_C6S2,
+ (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1,
+ (ogg_uint16_t)OC_C7S1,(ogg_uint16_t)OC_C7S1
+};
+
+/*38 cycles*/
+#define OC_IDCT_BEGIN(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
+ __asm movq mm6,OC_C(3) \
+ __asm movq mm4,mm2 \
+ __asm movq mm7,OC_J(5,_x) \
+ __asm pmulhw mm4,mm6 \
+ __asm movq mm1,OC_C(5) \
+ __asm pmulhw mm6,mm7 \
+ __asm movq mm5,mm1 \
+ __asm pmulhw mm1,mm2 \
+ __asm movq mm3,OC_I(1,_x) \
+ __asm pmulhw mm5,mm7 \
+ __asm movq mm0,OC_C(1) \
+ __asm paddw mm4,mm2 \
+ __asm paddw mm6,mm7 \
+ __asm paddw mm2,mm1 \
+ __asm movq mm1,OC_J(7,_x) \
+ __asm paddw mm7,mm5 \
+ __asm movq mm5,mm0 \
+ __asm pmulhw mm0,mm3 \
+ __asm paddw mm4,mm7 \
+ __asm pmulhw mm5,mm1 \
+ __asm movq mm7,OC_C(7) \
+ __asm psubw mm6,mm2 \
+ __asm paddw mm0,mm3 \
+ __asm pmulhw mm3,mm7 \
+ __asm movq mm2,OC_I(2,_x) \
+ __asm pmulhw mm7,mm1 \
+ __asm paddw mm5,mm1 \
+ __asm movq mm1,mm2 \
+ __asm pmulhw mm2,OC_C(2) \
+ __asm psubw mm3,mm5 \
+ __asm movq mm5,OC_J(6,_x) \
+ __asm paddw mm0,mm7 \
+ __asm movq mm7,mm5 \
+ __asm psubw mm0,mm4 \
+ __asm pmulhw mm5,OC_C(2) \
+ __asm paddw mm2,mm1 \
+ __asm pmulhw mm1,OC_C(6) \
+ __asm paddw mm4,mm4 \
+ __asm paddw mm4,mm0 \
+ __asm psubw mm3,mm6 \
+ __asm paddw mm5,mm7 \
+ __asm paddw mm6,mm6 \
+ __asm pmulhw mm7,OC_C(6) \
+ __asm paddw mm6,mm3 \
+ __asm movq OC_I(1,_y),mm4 \
+ __asm psubw mm1,mm5 \
+ __asm movq mm4,OC_C(4) \
+ __asm movq mm5,mm3 \
+ __asm pmulhw mm3,mm4 \
+ __asm paddw mm7,mm2 \
+ __asm movq OC_I(2,_y),mm6 \
+ __asm movq mm2,mm0 \
+ __asm movq mm6,OC_I(0,_x) \
+ __asm pmulhw mm0,mm4 \
+ __asm paddw mm5,mm3 \
+ __asm movq mm3,OC_J(4,_x) \
+ __asm psubw mm5,mm1 \
+ __asm paddw mm2,mm0 \
+ __asm psubw mm6,mm3 \
+ __asm movq mm0,mm6 \
+ __asm pmulhw mm6,mm4 \
+ __asm paddw mm3,mm3 \
+ __asm paddw mm1,mm1 \
+ __asm paddw mm3,mm0 \
+ __asm paddw mm1,mm5 \
+ __asm pmulhw mm4,mm3 \
+ __asm paddw mm6,mm0 \
+ __asm psubw mm6,mm2 \
+ __asm paddw mm2,mm2 \
+ __asm movq mm0,OC_I(1,_y) \
+ __asm paddw mm2,mm6 \
+ __asm paddw mm4,mm3 \
+ __asm psubw mm2,mm1 \
+}
+
+/*38+8=46 cycles.*/
+#define OC_ROW_IDCT(_y,_x) __asm{ \
+ OC_IDCT_BEGIN(_y,_x) \
+ /*r3=D'*/ \
+ __asm movq mm3,OC_I(2,_y) \
+ /*r4=E'=E-G*/ \
+ __asm psubw mm4,mm7 \
+ /*r1=H'+H'*/ \
+ __asm paddw mm1,mm1 \
+ /*r7=G+G*/ \
+ __asm paddw mm7,mm7 \
+ /*r1=R1=A''+H'*/ \
+ __asm paddw mm1,mm2 \
+ /*r7=G'=E+G*/ \
+ __asm paddw mm7,mm4 \
+ /*r4=R4=E'-D'*/ \
+ __asm psubw mm4,mm3 \
+ __asm paddw mm3,mm3 \
+ /*r6=R6=F'-B''*/ \
+ __asm psubw mm6,mm5 \
+ __asm paddw mm5,mm5 \
+ /*r3=R3=E'+D'*/ \
+ __asm paddw mm3,mm4 \
+ /*r5=R5=F'+B''*/ \
+ __asm paddw mm5,mm6 \
+ /*r7=R7=G'-C'*/ \
+ __asm psubw mm7,mm0 \
+ __asm paddw mm0,mm0 \
+ /*Save R1.*/ \
+ __asm movq OC_I(1,_y),mm1 \
+ /*r0=R0=G.+C.*/ \
+ __asm paddw mm0,mm7 \
+}
+
+/*The following macro does two 4x4 transposes in place.
+ At entry, we assume:
+ r0 = a3 a2 a1 a0
+ I(1) = b3 b2 b1 b0
+ r2 = c3 c2 c1 c0
+ r3 = d3 d2 d1 d0
+
+ r4 = e3 e2 e1 e0
+ r5 = f3 f2 f1 f0
+ r6 = g3 g2 g1 g0
+ r7 = h3 h2 h1 h0
+
+ At exit, we have:
+ I(0) = d0 c0 b0 a0
+ I(1) = d1 c1 b1 a1
+ I(2) = d2 c2 b2 a2
+ I(3) = d3 c3 b3 a3
+
+ J(4) = h0 g0 f0 e0
+ J(5) = h1 g1 f1 e1
+ J(6) = h2 g2 f2 e2
+ J(7) = h3 g3 f3 e3
+
+ I(0) I(1) I(2) I(3) is the transpose of r0 I(1) r2 r3.
+ J(4) J(5) J(6) J(7) is the transpose of r4 r5 r6 r7.
+
+ Since r1 is free at entry, we calculate the Js first.*/
+/*19 cycles.*/
+#define OC_TRANSPOSE(_y) __asm{ \
+ __asm movq mm1,mm4 \
+ __asm punpcklwd mm4,mm5 \
+ __asm movq OC_I(0,_y),mm0 \
+ __asm punpckhwd mm1,mm5 \
+ __asm movq mm0,mm6 \
+ __asm punpcklwd mm6,mm7 \
+ __asm movq mm5,mm4 \
+ __asm punpckldq mm4,mm6 \
+ __asm punpckhdq mm5,mm6 \
+ __asm movq mm6,mm1 \
+ __asm movq OC_J(4,_y),mm4 \
+ __asm punpckhwd mm0,mm7 \
+ __asm movq OC_J(5,_y),mm5 \
+ __asm punpckhdq mm6,mm0 \
+ __asm movq mm4,OC_I(0,_y) \
+ __asm punpckldq mm1,mm0 \
+ __asm movq mm5,OC_I(1,_y) \
+ __asm movq mm0,mm4 \
+ __asm movq OC_J(7,_y),mm6 \
+ __asm punpcklwd mm0,mm5 \
+ __asm movq OC_J(6,_y),mm1 \
+ __asm punpckhwd mm4,mm5 \
+ __asm movq mm5,mm2 \
+ __asm punpcklwd mm2,mm3 \
+ __asm movq mm1,mm0 \
+ __asm punpckldq mm0,mm2 \
+ __asm punpckhdq mm1,mm2 \
+ __asm movq mm2,mm4 \
+ __asm movq OC_I(0,_y),mm0 \
+ __asm punpckhwd mm5,mm3 \
+ __asm movq OC_I(1,_y),mm1 \
+ __asm punpckhdq mm4,mm5 \
+ __asm punpckldq mm2,mm5 \
+ __asm movq OC_I(3,_y),mm4 \
+ __asm movq OC_I(2,_y),mm2 \
+}
+
+/*38+19=57 cycles.*/
+#define OC_COLUMN_IDCT(_y) __asm{ \
+ OC_IDCT_BEGIN(_y,_y) \
+ __asm paddw mm2,OC_8 \
+ /*r1=H'+H'*/ \
+ __asm paddw mm1,mm1 \
+ /*r1=R1=A''+H'*/ \
+ __asm paddw mm1,mm2 \
+ /*r2=NR2*/ \
+ __asm psraw mm2,4 \
+ /*r4=E'=E-G*/ \
+ __asm psubw mm4,mm7 \
+ /*r1=NR1*/ \
+ __asm psraw mm1,4 \
+ /*r3=D'*/ \
+ __asm movq mm3,OC_I(2,_y) \
+ /*r7=G+G*/ \
+ __asm paddw mm7,mm7 \
+ /*Store NR2 at I(2).*/ \
+ __asm movq OC_I(2,_y),mm2 \
+ /*r7=G'=E+G*/ \
+ __asm paddw mm7,mm4 \
+ /*Store NR1 at I(1).*/ \
+ __asm movq OC_I(1,_y),mm1 \
+ /*r4=R4=E'-D'*/ \
+ __asm psubw mm4,mm3 \
+ __asm paddw mm4,OC_8 \
+ /*r3=D'+D'*/ \
+ __asm paddw mm3,mm3 \
+ /*r3=R3=E'+D'*/ \
+ __asm paddw mm3,mm4 \
+ /*r4=NR4*/ \
+ __asm psraw mm4,4 \
+ /*r6=R6=F'-B''*/ \
+ __asm psubw mm6,mm5 \
+ /*r3=NR3*/ \
+ __asm psraw mm3,4 \
+ __asm paddw mm6,OC_8 \
+ /*r5=B''+B''*/ \
+ __asm paddw mm5,mm5 \
+ /*r5=R5=F'+B''*/ \
+ __asm paddw mm5,mm6 \
+ /*r6=NR6*/ \
+ __asm psraw mm6,4 \
+ /*Store NR4 at J(4).*/ \
+ __asm movq OC_J(4,_y),mm4 \
+ /*r5=NR5*/ \
+ __asm psraw mm5,4 \
+ /*Store NR3 at I(3).*/ \
+ __asm movq OC_I(3,_y),mm3 \
+ /*r7=R7=G'-C'*/ \
+ __asm psubw mm7,mm0 \
+ __asm paddw mm7,OC_8 \
+ /*r0=C'+C'*/ \
+ __asm paddw mm0,mm0 \
+ /*r0=R0=G'+C'*/ \
+ __asm paddw mm0,mm7 \
+ /*r7=NR7*/ \
+ __asm psraw mm7,4 \
+ /*Store NR6 at J(6).*/ \
+ __asm movq OC_J(6,_y),mm6 \
+ /*r0=NR0*/ \
+ __asm psraw mm0,4 \
+ /*Store NR5 at J(5).*/ \
+ __asm movq OC_J(5,_y),mm5 \
+ /*Store NR7 at J(7).*/ \
+ __asm movq OC_J(7,_y),mm7 \
+ /*Store NR0 at I(0).*/ \
+ __asm movq OC_I(0,_y),mm0 \
+}
+
+#define OC_MID(_m,_i) [CONSTS+_m+(_i)*8]
+#define OC_C(_i) OC_MID(OC_COSINE_OFFSET,_i-1)
+#define OC_8 OC_MID(OC_EIGHT_OFFSET,0)
+
+static void oc_idct8x8_slow(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ int i;
+ /*This routine accepts an 8x8 matrix, but in partially transposed form.
+ Every 4x4 block is transposed.*/
+ __asm{
+#define CONSTS eax
+#define Y edx
+#define X ecx
+ mov CONSTS,offset OC_IDCT_CONSTS
+ mov Y,_y
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
+#undef OC_I
+#undef OC_J
+#define OC_I(_k,_y) [(_y)+(_k)*16+64]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+72]
+ OC_ROW_IDCT(Y,X)
+ OC_TRANSPOSE(Y)
+#undef OC_I
+#undef OC_J
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
+#undef OC_I
+#undef OC_J
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT(Y)
+#undef OC_I
+#undef OC_J
+#undef CONSTS
+#undef Y
+#undef X
+ }
+ if(_x!=_y){
+ int i;
+ __asm pxor mm0,mm0;
+ for(i=0;i<4;i++){
+ ogg_int16_t *x;
+ x=_x+16*i;
+#define X ecx
+ __asm{
+ mov X,x
+ movq [X+0x00],mm0
+ movq [X+0x08],mm0
+ movq [X+0x10],mm0
+ movq [X+0x18],mm0
+ }
+#undef X
+ }
+ }
+}
+
+/*25 cycles.*/
+#define OC_IDCT_BEGIN_10(_y,_x) __asm{ \
+ __asm movq mm2,OC_I(3,_x) \
+ __asm nop \
+ __asm movq mm6,OC_C(3) \
+ __asm movq mm4,mm2 \
+ __asm movq mm1,OC_C(5) \
+ __asm pmulhw mm4,mm6 \
+ __asm movq mm3,OC_I(1,_x) \
+ __asm pmulhw mm1,mm2 \
+ __asm movq mm0,OC_C(1) \
+ __asm paddw mm4,mm2 \
+ __asm pxor mm6,mm6 \
+ __asm paddw mm2,mm1 \
+ __asm movq mm5,OC_I(2,_x) \
+ __asm pmulhw mm0,mm3 \
+ __asm movq mm1,mm5 \
+ __asm paddw mm0,mm3 \
+ __asm pmulhw mm3,OC_C(7) \
+ __asm psubw mm6,mm2 \
+ __asm pmulhw mm5,OC_C(2) \
+ __asm psubw mm0,mm4 \
+ __asm movq mm7,OC_I(2,_x) \
+ __asm paddw mm4,mm4 \
+ __asm paddw mm7,mm5 \
+ __asm paddw mm4,mm0 \
+ __asm pmulhw mm1,OC_C(6) \
+ __asm psubw mm3,mm6 \
+ __asm movq OC_I(1,_y),mm4 \
+ __asm paddw mm6,mm6 \
+ __asm movq mm4,OC_C(4) \
+ __asm paddw mm6,mm3 \
+ __asm movq mm5,mm3 \
+ __asm pmulhw mm3,mm4 \
+ __asm movq OC_I(2,_y),mm6 \
+ __asm movq mm2,mm0 \
+ __asm movq mm6,OC_I(0,_x) \
+ __asm pmulhw mm0,mm4 \
+ __asm paddw mm5,mm3 \
+ __asm paddw mm2,mm0 \
+ __asm psubw mm5,mm1 \
+ __asm pmulhw mm6,mm4 \
+ __asm paddw mm6,OC_I(0,_x) \
+ __asm paddw mm1,mm1 \
+ __asm movq mm4,mm6 \
+ __asm paddw mm1,mm5 \
+ __asm psubw mm6,mm2 \
+ __asm paddw mm2,mm2 \
+ __asm movq mm0,OC_I(1,_y) \
+ __asm paddw mm2,mm6 \
+ __asm psubw mm2,mm1 \
+ __asm nop \
+}
+
+/*25+8=33 cycles.*/
+#define OC_ROW_IDCT_10(_y,_x) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_x) \
+ /*r3=D'*/ \
+ __asm movq mm3,OC_I(2,_y) \
+ /*r4=E'=E-G*/ \
+ __asm psubw mm4,mm7 \
+ /*r1=H'+H'*/ \
+ __asm paddw mm1,mm1 \
+ /*r7=G+G*/ \
+ __asm paddw mm7,mm7 \
+ /*r1=R1=A''+H'*/ \
+ __asm paddw mm1,mm2 \
+ /*r7=G'=E+G*/ \
+ __asm paddw mm7,mm4 \
+ /*r4=R4=E'-D'*/ \
+ __asm psubw mm4,mm3 \
+ __asm paddw mm3,mm3 \
+ /*r6=R6=F'-B''*/ \
+ __asm psubw mm6,mm5 \
+ __asm paddw mm5,mm5 \
+ /*r3=R3=E'+D'*/ \
+ __asm paddw mm3,mm4 \
+ /*r5=R5=F'+B''*/ \
+ __asm paddw mm5,mm6 \
+ /*r7=R7=G'-C'*/ \
+ __asm psubw mm7,mm0 \
+ __asm paddw mm0,mm0 \
+ /*Save R1.*/ \
+ __asm movq OC_I(1,_y),mm1 \
+ /*r0=R0=G'+C'*/ \
+ __asm paddw mm0,mm7 \
+}
+
+/*25+19=44 cycles'*/
+#define OC_COLUMN_IDCT_10(_y) __asm{ \
+ OC_IDCT_BEGIN_10(_y,_y) \
+ __asm paddw mm2,OC_8 \
+ /*r1=H'+H'*/ \
+ __asm paddw mm1,mm1 \
+ /*r1=R1=A''+H'*/ \
+ __asm paddw mm1,mm2 \
+ /*r2=NR2*/ \
+ __asm psraw mm2,4 \
+ /*r4=E'=E-G*/ \
+ __asm psubw mm4,mm7 \
+ /*r1=NR1*/ \
+ __asm psraw mm1,4 \
+ /*r3=D'*/ \
+ __asm movq mm3,OC_I(2,_y) \
+ /*r7=G+G*/ \
+ __asm paddw mm7,mm7 \
+ /*Store NR2 at I(2).*/ \
+ __asm movq OC_I(2,_y),mm2 \
+ /*r7=G'=E+G*/ \
+ __asm paddw mm7,mm4 \
+ /*Store NR1 at I(1).*/ \
+ __asm movq OC_I(1,_y),mm1 \
+ /*r4=R4=E'-D'*/ \
+ __asm psubw mm4,mm3 \
+ __asm paddw mm4,OC_8 \
+ /*r3=D'+D'*/ \
+ __asm paddw mm3,mm3 \
+ /*r3=R3=E'+D'*/ \
+ __asm paddw mm3,mm4 \
+ /*r4=NR4*/ \
+ __asm psraw mm4,4 \
+ /*r6=R6=F'-B''*/ \
+ __asm psubw mm6,mm5 \
+ /*r3=NR3*/ \
+ __asm psraw mm3,4 \
+ __asm paddw mm6,OC_8 \
+ /*r5=B''+B''*/ \
+ __asm paddw mm5,mm5 \
+ /*r5=R5=F'+B''*/ \
+ __asm paddw mm5,mm6 \
+ /*r6=NR6*/ \
+ __asm psraw mm6,4 \
+ /*Store NR4 at J(4).*/ \
+ __asm movq OC_J(4,_y),mm4 \
+ /*r5=NR5*/ \
+ __asm psraw mm5,4 \
+ /*Store NR3 at I(3).*/ \
+ __asm movq OC_I(3,_y),mm3 \
+ /*r7=R7=G'-C'*/ \
+ __asm psubw mm7,mm0 \
+ __asm paddw mm7,OC_8 \
+ /*r0=C'+C'*/ \
+ __asm paddw mm0,mm0 \
+ /*r0=R0=G'+C'*/ \
+ __asm paddw mm0,mm7 \
+ /*r7=NR7*/ \
+ __asm psraw mm7,4 \
+ /*Store NR6 at J(6).*/ \
+ __asm movq OC_J(6,_y),mm6 \
+ /*r0=NR0*/ \
+ __asm psraw mm0,4 \
+ /*Store NR5 at J(5).*/ \
+ __asm movq OC_J(5,_y),mm5 \
+ /*Store NR7 at J(7).*/ \
+ __asm movq OC_J(7,_y),mm7 \
+ /*Store NR0 at I(0).*/ \
+ __asm movq OC_I(0,_y),mm0 \
+}
+
+static void oc_idct8x8_10(ogg_int16_t _y[64],ogg_int16_t _x[64]){
+ __asm{
+#define CONSTS eax
+#define Y edx
+#define X ecx
+ mov CONSTS,offset OC_IDCT_CONSTS
+ mov Y,_y
+ mov X,_x
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) [(_y)+((_k)-4)*16+8]
+ /*Done with dequant, descramble, and partial transpose.
+ Now do the iDCT itself.*/
+ OC_ROW_IDCT_10(Y,X)
+ OC_TRANSPOSE(Y)
+#undef OC_I
+#undef OC_J
+#define OC_I(_k,_y) [(_y)+(_k)*16]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
+#undef OC_I
+#undef OC_J
+#define OC_I(_k,_y) [(_y)+(_k)*16+8]
+#define OC_J(_k,_y) OC_I(_k,_y)
+ OC_COLUMN_IDCT_10(Y)
+#undef OC_I
+#undef OC_J
+#undef CONSTS
+#undef Y
+#undef X
+ }
+ if(_x!=_y){
+#define X ecx
+ __asm{
+ pxor mm0,mm0;
+ mov X,_x
+ movq [X+0x00],mm0
+ movq [X+0x10],mm0
+ movq [X+0x20],mm0
+ movq [X+0x30],mm0
+ }
+#undef X
+ }
+}
+
+/*Performs an inverse 8x8 Type-II DCT transform.
+ The input is assumed to be scaled by a factor of 4 relative to orthonormal
+ version of the transform.*/
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi){
+ /*_last_zzi is subtly different from an actual count of the number of
+ coefficients we decoded for this block.
+ It contains the value of zzi BEFORE the final token in the block was
+ decoded.
+ In most cases this is an EOB token (the continuation of an EOB run from a
+ previous block counts), and so this is the same as the coefficient count.
+ However, in the case that the last token was NOT an EOB token, but filled
+ the block up with exactly 64 coefficients, _last_zzi will be less than 64.
+ Provided the last token was not a pure zero run, the minimum value it can
+ be is 46, and so that doesn't affect any of the cases in this routine.
+ However, if the last token WAS a pure zero run of length 63, then _last_zzi
+ will be 1 while the number of coefficients decoded is 64.
+ Thus, we will trigger the following special case, where the real
+ coefficient count would not.
+ Note also that a zero run of length 64 will give _last_zzi a value of 0,
+ but we still process the DC coefficient, which might have a non-zero value
+ due to DC prediction.
+ Although convoluted, this is arguably the correct behavior: it allows us to
+ use a smaller transform when the block ends with a long zero run instead
+ of a normal EOB token.
+ It could be smarter... multiple separate zero runs at the end of a block
+ will fool it, but an encoder that generates these really deserves what it
+ gets.
+ Needless to say we inherited this approach from VP3.*/
+ /*Perform the iDCT.*/
+ if(_last_zzi<=10)oc_idct8x8_10(_y,_x);
+ else oc_idct8x8_slow(_y,_x);
+}
+
+#endif
diff --git a/media/libtheora/lib/x86_vc/mmxloop.h b/media/libtheora/lib/x86_vc/mmxloop.h
new file mode 100644
index 000000000..2561fca2a
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/mmxloop.h
@@ -0,0 +1,219 @@
+#if !defined(_x86_vc_mmxloop_H)
+# define _x86_vc_mmxloop_H (1)
+# include <stddef.h>
+# include "x86int.h"
+
+#if defined(OC_X86_ASM)
+
+/*On entry, mm0={a0,...,a7}, mm1={b0,...,b7}, mm2={c0,...,c7}, mm3={d0,...d7}.
+ On exit, mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)} and
+ mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}; mm0 and mm3 are clobbered.*/
+#define OC_LOOP_FILTER8_MMX __asm{ \
+ /*mm7=0*/ \
+ __asm pxor mm7,mm7 \
+ /*mm6:mm0={a0,...,a7}*/ \
+ __asm movq mm6,mm0 \
+ __asm punpcklbw mm0,mm7 \
+ __asm punpckhbw mm6,mm7 \
+ /*mm3:mm5={d0,...,d7}*/ \
+ __asm movq mm5,mm3 \
+ __asm punpcklbw mm3,mm7 \
+ __asm punpckhbw mm5,mm7 \
+ /*mm6:mm0={a0-d0,...,a7-d7}*/ \
+ __asm psubw mm0,mm3 \
+ __asm psubw mm6,mm5 \
+ /*mm3:mm1={b0,...,b7}*/ \
+ __asm movq mm3,mm1 \
+ __asm punpcklbw mm1,mm7 \
+ __asm movq mm4,mm2 \
+ __asm punpckhbw mm3,mm7 \
+ /*mm5:mm4={c0,...,c7}*/ \
+ __asm movq mm5,mm2 \
+ __asm punpcklbw mm4,mm7 \
+ __asm punpckhbw mm5,mm7 \
+ /*mm7={3}x4 \
+ mm5:mm4={c0-b0,...,c7-b7}*/ \
+ __asm pcmpeqw mm7,mm7 \
+ __asm psubw mm4,mm1 \
+ __asm psrlw mm7,14 \
+ __asm psubw mm5,mm3 \
+ /*Scale by 3.*/ \
+ __asm pmullw mm4,mm7 \
+ __asm pmullw mm5,mm7 \
+ /*mm7={4}x4 \
+ mm5:mm4=f={a0-d0+3*(c0-b0),...,a7-d7+3*(c7-b7)}*/ \
+ __asm psrlw mm7,1 \
+ __asm paddw mm4,mm0 \
+ __asm psllw mm7,2 \
+ __asm movq mm0,[LL] \
+ __asm paddw mm5,mm6 \
+ /*R_i has the range [-127,128], so we compute -R_i instead. \
+ mm4=-R_i=-(f+4>>3)=0xFF^(f-4>>3)*/ \
+ __asm psubw mm4,mm7 \
+ __asm psubw mm5,mm7 \
+ __asm psraw mm4,3 \
+ __asm psraw mm5,3 \
+ __asm pcmpeqb mm7,mm7 \
+ __asm packsswb mm4,mm5 \
+ __asm pxor mm6,mm6 \
+ __asm pxor mm4,mm7 \
+ __asm packuswb mm1,mm3 \
+ /*Now compute lflim of -mm4 cf. Section 7.10 of the sepc.*/ \
+ /*There's no unsigned byte+signed byte with unsigned saturation op code, so \
+ we have to split things by sign (the other option is to work in 16 bits, \
+ but working in 8 bits gives much better parallelism). \
+ We compute abs(R_i), but save a mask of which terms were negative in mm6. \
+ Then we compute mm4=abs(lflim(R_i,L))=min(abs(R_i),max(2*L-abs(R_i),0)). \
+ Finally, we split mm4 into positive and negative pieces using the mask in \
+ mm6, and add and subtract them as appropriate.*/ \
+ /*mm4=abs(-R_i)*/ \
+ /*mm7=255-2*L*/ \
+ __asm pcmpgtb mm6,mm4 \
+ __asm psubb mm7,mm0 \
+ __asm pxor mm4,mm6 \
+ __asm psubb mm7,mm0 \
+ __asm psubb mm4,mm6 \
+ /*mm7=255-max(2*L-abs(R_i),0)*/ \
+ __asm paddusb mm7,mm4 \
+ /*mm4=min(abs(R_i),max(2*L-abs(R_i),0))*/ \
+ __asm paddusb mm4,mm7 \
+ __asm psubusb mm4,mm7 \
+ /*Now split mm4 by the original sign of -R_i.*/ \
+ __asm movq mm5,mm4 \
+ __asm pand mm4,mm6 \
+ __asm pandn mm6,mm5 \
+ /*mm1={b0+lflim(R_0,L),...,b7+lflim(R_7,L)}*/ \
+ /*mm2={c0-lflim(R_0,L),...,c7-lflim(R_7,L)}*/ \
+ __asm paddusb mm1,mm4 \
+ __asm psubusb mm2,mm4 \
+ __asm psubusb mm1,mm6 \
+ __asm paddusb mm2,mm6 \
+}
+
+#define OC_LOOP_FILTER_V_MMX(_pix,_ystride,_ll) \
+ do{ \
+ /*Used local variable pix__ in order to fix compilation errors like: \
+ "error C2425: 'SHL' : non-constant expression in 'second operand'".*/ \
+ unsigned char *pix__; \
+ unsigned char *ll__; \
+ ll__=(_ll); \
+ pix__=(_pix); \
+ __asm mov YSTRIDE,_ystride \
+ __asm mov LL,ll__ \
+ __asm mov PIX,pix__ \
+ __asm sub PIX,YSTRIDE \
+ __asm sub PIX,YSTRIDE \
+ /*mm0={a0,...,a7}*/ \
+ __asm movq mm0,[PIX] \
+ /*ystride3=_ystride*3*/ \
+ __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
+ /*mm3={d0,...,d7}*/ \
+ __asm movq mm3,[PIX+YSTRIDE3] \
+ /*mm1={b0,...,b7}*/ \
+ __asm movq mm1,[PIX+YSTRIDE] \
+ /*mm2={c0,...,c7}*/ \
+ __asm movq mm2,[PIX+YSTRIDE*2] \
+ OC_LOOP_FILTER8_MMX \
+ /*Write it back out.*/ \
+ __asm movq [PIX+YSTRIDE],mm1 \
+ __asm movq [PIX+YSTRIDE*2],mm2 \
+ } \
+ while(0)
+
+#define OC_LOOP_FILTER_H_MMX(_pix,_ystride,_ll) \
+ do{ \
+ /*Used local variable ll__ in order to fix compilation errors like: \
+ "error C2443: operand size conflict".*/ \
+ unsigned char *ll__; \
+ unsigned char *pix__; \
+ ll__=(_ll); \
+ pix__=(_pix)-2; \
+ __asm mov PIX,pix__ \
+ __asm mov YSTRIDE,_ystride \
+ __asm mov LL,ll__ \
+ /*x x x x d0 c0 b0 a0*/ \
+ __asm movd mm0,[PIX] \
+ /*x x x x d1 c1 b1 a1*/ \
+ __asm movd mm1,[PIX+YSTRIDE] \
+ /*ystride3=_ystride*3*/ \
+ __asm lea YSTRIDE3,[YSTRIDE+YSTRIDE*2] \
+ /*x x x x d2 c2 b2 a2*/ \
+ __asm movd mm2,[PIX+YSTRIDE*2] \
+ /*x x x x d3 c3 b3 a3*/ \
+ __asm lea D,[PIX+YSTRIDE*4] \
+ __asm movd mm3,[PIX+YSTRIDE3] \
+ /*x x x x d4 c4 b4 a4*/ \
+ __asm movd mm4,[D] \
+ /*x x x x d5 c5 b5 a5*/ \
+ __asm movd mm5,[D+YSTRIDE] \
+ /*x x x x d6 c6 b6 a6*/ \
+ __asm movd mm6,[D+YSTRIDE*2] \
+ /*x x x x d7 c7 b7 a7*/ \
+ __asm movd mm7,[D+YSTRIDE3] \
+ /*mm0=d1 d0 c1 c0 b1 b0 a1 a0*/ \
+ __asm punpcklbw mm0,mm1 \
+ /*mm2=d3 d2 c3 c2 b3 b2 a3 a2*/ \
+ __asm punpcklbw mm2,mm3 \
+ /*mm3=d1 d0 c1 c0 b1 b0 a1 a0*/ \
+ __asm movq mm3,mm0 \
+ /*mm0=b3 b2 b1 b0 a3 a2 a1 a0*/ \
+ __asm punpcklwd mm0,mm2 \
+ /*mm3=d3 d2 d1 d0 c3 c2 c1 c0*/ \
+ __asm punpckhwd mm3,mm2 \
+ /*mm1=b3 b2 b1 b0 a3 a2 a1 a0*/ \
+ __asm movq mm1,mm0 \
+ /*mm4=d5 d4 c5 c4 b5 b4 a5 a4*/ \
+ __asm punpcklbw mm4,mm5 \
+ /*mm6=d7 d6 c7 c6 b7 b6 a7 a6*/ \
+ __asm punpcklbw mm6,mm7 \
+ /*mm5=d5 d4 c5 c4 b5 b4 a5 a4*/ \
+ __asm movq mm5,mm4 \
+ /*mm4=b7 b6 b5 b4 a7 a6 a5 a4*/ \
+ __asm punpcklwd mm4,mm6 \
+ /*mm5=d7 d6 d5 d4 c7 c6 c5 c4*/ \
+ __asm punpckhwd mm5,mm6 \
+ /*mm2=d3 d2 d1 d0 c3 c2 c1 c0*/ \
+ __asm movq mm2,mm3 \
+ /*mm0=a7 a6 a5 a4 a3 a2 a1 a0*/ \
+ __asm punpckldq mm0,mm4 \
+ /*mm1=b7 b6 b5 b4 b3 b2 b1 b0*/ \
+ __asm punpckhdq mm1,mm4 \
+ /*mm2=c7 c6 c5 c4 c3 c2 c1 c0*/ \
+ __asm punpckldq mm2,mm5 \
+ /*mm3=d7 d6 d5 d4 d3 d2 d1 d0*/ \
+ __asm punpckhdq mm3,mm5 \
+ OC_LOOP_FILTER8_MMX \
+ /*mm2={b0+R_0'',...,b7+R_7''}*/ \
+ __asm movq mm0,mm1 \
+ /*mm1={b0+R_0'',c0-R_0'',...,b3+R_3'',c3-R_3''}*/ \
+ __asm punpcklbw mm1,mm2 \
+ /*mm2={b4+R_4'',c4-R_4'',...,b7+R_7'',c7-R_7''}*/ \
+ __asm punpckhbw mm0,mm2 \
+ /*[d]=c1 b1 c0 b0*/ \
+ __asm movd D,mm1 \
+ __asm mov [PIX+1],D_WORD \
+ __asm psrlq mm1,32 \
+ __asm shr D,16 \
+ __asm mov [PIX+YSTRIDE+1],D_WORD \
+ /*[d]=c3 b3 c2 b2*/ \
+ __asm movd D,mm1 \
+ __asm mov [PIX+YSTRIDE*2+1],D_WORD \
+ __asm shr D,16 \
+ __asm mov [PIX+YSTRIDE3+1],D_WORD \
+ __asm lea PIX,[PIX+YSTRIDE*4] \
+ /*[d]=c5 b5 c4 b4*/ \
+ __asm movd D,mm0 \
+ __asm mov [PIX+1],D_WORD \
+ __asm psrlq mm0,32 \
+ __asm shr D,16 \
+ __asm mov [PIX+YSTRIDE+1],D_WORD \
+ /*[d]=c7 b7 c6 b6*/ \
+ __asm movd D,mm0 \
+ __asm mov [PIX+YSTRIDE*2+1],D_WORD \
+ __asm shr D,16 \
+ __asm mov [PIX+YSTRIDE3+1],D_WORD \
+ } \
+ while(0)
+
+# endif
+#endif
diff --git a/media/libtheora/lib/x86_vc/mmxstate.c b/media/libtheora/lib/x86_vc/mmxstate.c
new file mode 100644
index 000000000..d3d468d5f
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/mmxstate.c
@@ -0,0 +1,176 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: mmxstate.c 17563 2010-10-25 17:40:54Z tterribe $
+
+ ********************************************************************/
+
+/*MMX acceleration of complete fragment reconstruction algorithm.
+ Originally written by Rudolf Marek.*/
+#include <string.h>
+#include "x86int.h"
+#include "mmxloop.h"
+
+#if defined(OC_X86_ASM)
+
+void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant){
+ unsigned char *dst;
+ ptrdiff_t frag_buf_off;
+ int ystride;
+ int refi;
+ /*Apply the inverse transform.*/
+ /*Special case only having a DC component.*/
+ if(_last_zzi<2){
+ /*Note that this value must be unsigned, to keep the __asm__ block from
+ sign-extending it when it puts it in a register.*/
+ ogg_uint16_t p;
+ /*We round this dequant product (and not any of the others) because there's
+ no iDCT rounding.*/
+ p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
+ /*Fill _dct_coeffs with p.*/
+ __asm{
+#define Y eax
+#define P ecx
+ mov Y,_dct_coeffs
+ movzx P,p
+ lea Y,[Y+128]
+ /*mm0=0000 0000 0000 AAAA*/
+ movd mm0,P
+ /*mm0=0000 0000 AAAA AAAA*/
+ punpcklwd mm0,mm0
+ /*mm0=AAAA AAAA AAAA AAAA*/
+ punpckldq mm0,mm0
+ movq [Y],mm0
+ movq [8+Y],mm0
+ movq [16+Y],mm0
+ movq [24+Y],mm0
+ movq [32+Y],mm0
+ movq [40+Y],mm0
+ movq [48+Y],mm0
+ movq [56+Y],mm0
+ movq [64+Y],mm0
+ movq [72+Y],mm0
+ movq [80+Y],mm0
+ movq [88+Y],mm0
+ movq [96+Y],mm0
+ movq [104+Y],mm0
+ movq [112+Y],mm0
+ movq [120+Y],mm0
+#undef Y
+#undef P
+ }
+ }
+ else{
+ /*Dequantize the DC coefficient.*/
+ _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
+ oc_idct8x8_mmx(_dct_coeffs+64,_dct_coeffs,_last_zzi);
+ }
+ /*Fill in the target buffer.*/
+ frag_buf_off=_state->frag_buf_offs[_fragi];
+ refi=_state->frags[_fragi].refi;
+ ystride=_state->ref_ystride[_pli];
+ dst=_state->ref_frame_data[OC_FRAME_SELF]+frag_buf_off;
+ if(refi==OC_FRAME_SELF)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs+64);
+ else{
+ const unsigned char *ref;
+ int mvoffsets[2];
+ ref=_state->ref_frame_data[refi]+frag_buf_off;
+ if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
+ _state->frag_mvs[_fragi])>1){
+ oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
+ _dct_coeffs+64);
+ }
+ else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs+64);
+ }
+}
+
+/*We copy these entire function to inline the actual MMX routines so that we
+ use only a single indirect call.*/
+
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit){
+ memset(_bv,~(_flimit<<1),8);
+}
+
+/*Apply the loop filter to a given set of fragment rows in the given plane.
+ The filter may be run on the bottom edge, affecting pixels in the next row of
+ fragments, so this row also needs to be available.
+ _bv: The bounding values array.
+ _refi: The index of the frame buffer to filter.
+ _pli: The color plane to filter.
+ _fragy0: The Y coordinate of the first fragment row to filter.
+ _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
+void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
+ const oc_fragment_plane *fplane;
+ const oc_fragment *frags;
+ const ptrdiff_t *frag_buf_offs;
+ unsigned char *ref_frame_data;
+ ptrdiff_t fragi_top;
+ ptrdiff_t fragi_bot;
+ ptrdiff_t fragi0;
+ ptrdiff_t fragi0_end;
+ int ystride;
+ int nhfrags;
+ fplane=_state->fplanes+_pli;
+ nhfrags=fplane->nhfrags;
+ fragi_top=fplane->froffset;
+ fragi_bot=fragi_top+fplane->nfrags;
+ fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
+ fragi0_end=fragi_top+_fragy_end*(ptrdiff_t)nhfrags;
+ ystride=_state->ref_ystride[_pli];
+ frags=_state->frags;
+ frag_buf_offs=_state->frag_buf_offs;
+ ref_frame_data=_state->ref_frame_data[_refi];
+ /*The following loops are constructed somewhat non-intuitively on purpose.
+ The main idea is: if a block boundary has at least one coded fragment on
+ it, the filter is applied to it.
+ However, the order that the filters are applied in matters, and VP3 chose
+ the somewhat strange ordering used below.*/
+ while(fragi0<fragi0_end){
+ ptrdiff_t fragi;
+ ptrdiff_t fragi_end;
+ fragi=fragi0;
+ fragi_end=fragi+nhfrags;
+ while(fragi<fragi_end){
+ if(frags[fragi].coded){
+ unsigned char *ref;
+ ref=ref_frame_data+frag_buf_offs[fragi];
+#define PIX eax
+#define YSTRIDE3 edi
+#define YSTRIDE ecx
+#define LL edx
+#define D esi
+#define D_WORD si
+ if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,_bv);
+ if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,_bv);
+ if(fragi+1<fragi_end&&!frags[fragi+1].coded){
+ OC_LOOP_FILTER_H_MMX(ref+8,ystride,_bv);
+ }
+ if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
+ OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,_bv);
+ }
+#undef PIX
+#undef YSTRIDE3
+#undef YSTRIDE
+#undef LL
+#undef D
+#undef D_WORD
+ }
+ fragi++;
+ }
+ fragi0+=nhfrags;
+ }
+}
+
+#endif
diff --git a/media/libtheora/lib/x86_vc/x86cpu.c b/media/libtheora/lib/x86_vc/x86cpu.c
new file mode 100644
index 000000000..41f4bcba9
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/x86cpu.c
@@ -0,0 +1,192 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ CPU capability detection for x86 processors.
+ Originally written by Rudolf Marek.
+
+ function:
+ last mod: $Id: x86cpu.c 17410 2010-09-21 21:53:48Z tterribe $
+
+ ********************************************************************/
+
+#include "x86cpu.h"
+
+#if !defined(OC_X86_ASM)
+ogg_uint32_t oc_cpu_flags_get(void){
+ return 0;
+}
+#else
+/*Why does MSVC need this complicated rigamarole?
+ At this point I honestly do not care.*/
+
+/*Visual C cpuid helper function.
+ For VS2005 we could as well use the _cpuid builtin, but that wouldn't work
+ for VS2003 users, so we do it in inline assembler.*/
+static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){
+ _asm{
+ mov eax,[_op]
+ mov esi,_cpu_info
+ cpuid
+ mov [esi+0],eax
+ mov [esi+4],ebx
+ mov [esi+8],ecx
+ mov [esi+12],edx
+ }
+}
+
+# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
+ do{ \
+ ogg_uint32_t cpu_info[4]; \
+ oc_cpuid_helper(cpu_info,_op); \
+ (_eax)=cpu_info[0]; \
+ (_ebx)=cpu_info[1]; \
+ (_ecx)=cpu_info[2]; \
+ (_edx)=cpu_info[3]; \
+ }while(0)
+
+static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
+ _asm{
+ pushfd
+ pushfd
+ pop eax
+ mov ebx,eax
+ xor eax,200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ popfd
+ mov ecx,_eax
+ mov [ecx],eax
+ mov ecx,_ebx
+ mov [ecx],ebx
+ }
+}
+
+static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
+ if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
+ if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
+ if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
+ if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
+ if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
+ return flags;
+}
+
+static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
+ ogg_uint32_t flags;
+ /*If there isn't even MMX, give up.*/
+ if(!(_edx&0x00800000))return 0;
+ flags=OC_CPU_X86_MMX;
+ if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
+ if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
+ if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
+ if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
+ if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
+ return flags;
+}
+
+ogg_uint32_t oc_cpu_flags_get(void){
+ ogg_uint32_t flags;
+ ogg_uint32_t eax;
+ ogg_uint32_t ebx;
+ ogg_uint32_t ecx;
+ ogg_uint32_t edx;
+# if !defined(__amd64__)&&!defined(__x86_64__)
+ /*Not all x86-32 chips support cpuid, so we have to check.*/
+ oc_detect_cpuid_helper(&eax,&ebx);
+ /*No cpuid.*/
+ if(eax==ebx)return 0;
+# endif
+ cpuid(0,eax,ebx,ecx,edx);
+ /* l e t n I e n i u n e G*/
+ if(ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547||
+ /* 6 8 x M T e n i u n e G*/
+ ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547){
+ int family;
+ int model;
+ /*Intel, Transmeta (tested with Crusoe TM5800):*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ family=(eax>>8)&0xF;
+ model=(eax>>4)&0xF;
+ /*The SSE unit on the Pentium M and Core Duo is much slower than the MMX
+ unit, so don't use it.*/
+ if(family==6&&(model==9||model==13||model==14)){
+ flags&=~(OC_CPU_X86_SSE2|OC_CPU_X86_PNI);
+ }
+ }
+ /* D M A c i t n e h t u A*/
+ else if(ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541||
+ /* C S N y b e d o e G*/
+ ecx==0x43534e20&&edx==0x79622065&&ebx==0x646f6547){
+ /*AMD, Geode:*/
+ cpuid(0x80000000,eax,ebx,ecx,edx);
+ if(eax<0x80000001)flags=0;
+ else{
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ flags=oc_parse_amd_flags(edx,ecx);
+ }
+ /*Also check for SSE.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags|=oc_parse_intel_flags(edx,ecx);
+ }
+ /*Technically some VIA chips can be configured in the BIOS to return any
+ string here the user wants.
+ There is a special detection method that can be used to identify such
+ processors, but in my opinion, if the user really wants to change it, they
+ deserve what they get.*/
+ /* s l u a H r u a t n e C*/
+ else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
+ /*VIA:*/
+ /*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
+ chips (thanks to the engineers from Centaur Technology who provided it).
+ These chips support Intel-like cpuid info.
+ The C3-2 (Nehemiah) cores appear to, as well.*/
+ cpuid(1,eax,ebx,ecx,edx);
+ flags=oc_parse_intel_flags(edx,ecx);
+ if(eax>=0x80000001){
+ /*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
+ We need to check this even if the Intel test succeeds to pick up 3DNow!
+ support on these processors.
+ Unlike actual AMD processors, we cannot _rely_ on this info, since
+ some cores (e.g., the 693 stepping of the Nehemiah) claim to support
+ this function, yet return edx=0, despite the Intel test indicating
+ MMX support.
+ Therefore the features detected here are strictly added to those
+ detected by the Intel test.*/
+ /*TODO: How about earlier chips?*/
+ cpuid(0x80000001,eax,ebx,ecx,edx);
+ /*Note: As of the C7, this function returns Intel-style extended feature
+ flags, not AMD-style.
+ Currently, this only defines bits 11, 20, and 29 (0x20100800), which
+ do not conflict with any of the AMD flags we inspect.
+ For the remaining bits, Intel tells us, "Do not count on their value",
+ but VIA assures us that they will all be zero (at least on the C7 and
+ Isaiah chips).
+ In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
+ (0xC0C00000) for something else, we will have to add code to detect
+ the model to decide when it is appropriate to inspect them.*/
+ flags|=oc_parse_amd_flags(edx,ecx);
+ }
+ }
+ else{
+ /*Implement me.*/
+ flags=0;
+ }
+ return flags;
+}
+#endif
diff --git a/media/libtheora/lib/x86_vc/x86cpu.h b/media/libtheora/lib/x86_vc/x86cpu.h
new file mode 100644
index 000000000..327d93246
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/x86cpu.h
@@ -0,0 +1,36 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+ function:
+ last mod: $Id: x86cpu.h 17410 2010-09-21 21:53:48Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86cpu_H)
+# define _x86_vc_x86cpu_H (1)
+#include "../internal.h"
+
+#define OC_CPU_X86_MMX (1<<0)
+#define OC_CPU_X86_3DNOW (1<<1)
+#define OC_CPU_X86_3DNOWEXT (1<<2)
+#define OC_CPU_X86_MMXEXT (1<<3)
+#define OC_CPU_X86_SSE (1<<4)
+#define OC_CPU_X86_SSE2 (1<<5)
+#define OC_CPU_X86_PNI (1<<6)
+#define OC_CPU_X86_SSSE3 (1<<7)
+#define OC_CPU_X86_SSE4_1 (1<<8)
+#define OC_CPU_X86_SSE4_2 (1<<9)
+#define OC_CPU_X86_SSE4A (1<<10)
+#define OC_CPU_X86_SSE5 (1<<11)
+
+ogg_uint32_t oc_cpu_flags_get(void);
+
+#endif
diff --git a/media/libtheora/lib/x86_vc/x86int.h b/media/libtheora/lib/x86_vc/x86int.h
new file mode 100644
index 000000000..bc4c54a2f
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/x86int.h
@@ -0,0 +1,49 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: x86int.h 17410 2010-09-21 21:53:48Z tterribe $
+
+ ********************************************************************/
+
+#if !defined(_x86_vc_x86int_H)
+# define _x86_vc_x86int_H (1)
+# include "../internal.h"
+# if defined(OC_X86_ASM)
+# define oc_state_accel_init oc_state_accel_init_x86
+# define OC_STATE_USE_VTABLE (1)
+# endif
+# include "../state.h"
+# include "x86cpu.h"
+
+void oc_state_accel_init_x86(oc_theora_state *_state);
+
+void oc_frag_copy_mmx(unsigned char *_dst,
+ const unsigned char *_src,int _ystride);
+void oc_frag_copy_list_mmx(unsigned char *_dst_frame,
+ const unsigned char *_src_frame,int _ystride,
+ const ptrdiff_t *_fragis,ptrdiff_t _nfragis,const ptrdiff_t *_frag_buf_offs);
+void oc_frag_recon_intra_mmx(unsigned char *_dst,int _ystride,
+ const ogg_int16_t *_residue);
+void oc_frag_recon_inter_mmx(unsigned char *_dst,
+ const unsigned char *_src,int _ystride,const ogg_int16_t *_residue);
+void oc_frag_recon_inter2_mmx(unsigned char *_dst,const unsigned char *_src1,
+ const unsigned char *_src2,int _ystride,const ogg_int16_t *_residue);
+void oc_idct8x8_mmx(ogg_int16_t _y[64],ogg_int16_t _x[64],int _last_zzi);
+void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
+ int _pli,ogg_int16_t _dct_coeffs[128],int _last_zzi,ogg_uint16_t _dc_quant);
+void oc_loop_filter_init_mmx(signed char _bv[256],int _flimit);
+void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
+ signed char _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end);
+void oc_restore_fpu_mmx(void);
+
+#endif
diff --git a/media/libtheora/lib/x86_vc/x86state.c b/media/libtheora/lib/x86_vc/x86state.c
new file mode 100644
index 000000000..7aa73deae
--- /dev/null
+++ b/media/libtheora/lib/x86_vc/x86state.c
@@ -0,0 +1,61 @@
+/********************************************************************
+ * *
+ * 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) 2002-2009 *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function:
+ last mod: $Id: x86state.c 17410 2010-09-21 21:53:48Z tterribe $
+
+ ********************************************************************/
+
+#include "x86int.h"
+
+#if defined(OC_X86_ASM)
+
+/*This table has been modified from OC_FZIG_ZAG by baking a 4x4 transpose into
+ each quadrant of the destination.*/
+static const unsigned char OC_FZIG_ZAG_MMX[128]={
+ 0, 8, 1, 2, 9,16,24,17,
+ 10, 3,32,11,18,25, 4,12,
+ 5,26,19,40,33,34,41,48,
+ 27, 6,13,20,28,21,14, 7,
+ 56,49,42,35,43,50,57,36,
+ 15,22,29,30,23,44,37,58,
+ 51,59,38,45,52,31,60,53,
+ 46,39,47,54,61,62,55,63,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+ 64,64,64,64,64,64,64,64,
+};
+
+void oc_state_accel_init_x86(oc_theora_state *_state){
+ _state->cpu_flags=oc_cpu_flags_get();
+ if(_state->cpu_flags&OC_CPU_X86_MMX){
+ _state->opt_vtable.frag_copy=oc_frag_copy_mmx;
+ _state->opt_vtable.frag_copy_list=oc_frag_copy_list_mmx;
+ _state->opt_vtable.frag_recon_intra=oc_frag_recon_intra_mmx;
+ _state->opt_vtable.frag_recon_inter=oc_frag_recon_inter_mmx;
+ _state->opt_vtable.frag_recon_inter2=oc_frag_recon_inter2_mmx;
+ _state->opt_vtable.idct8x8=oc_idct8x8_mmx;
+ _state->opt_vtable.state_frag_recon=oc_state_frag_recon_mmx;
+ _state->opt_vtable.loop_filter_init=oc_loop_filter_init_mmx;
+ _state->opt_vtable.state_loop_filter_frag_rows=
+ oc_state_loop_filter_frag_rows_mmx;
+ _state->opt_vtable.restore_fpu=oc_restore_fpu_mmx;
+ _state->opt_data.dct_fzig_zag=OC_FZIG_ZAG_MMX;
+ }
+ else oc_state_accel_init_c(_state);
+}
+#endif