[PATCH]: PPC/Altivec implementations of SAD and SSD

Venkatesh Srinivas <[email protected]> Tue, 29 Jun 2010 16:51:19 -0400
Newsgroups gmane.comp.multimedia.ogg.theora.devel
Message-ID <[email protected]>
Hi,

This patch adds Altivec-optimized implementations of oc_enc_frag_sad and
oc_enc_frag_ssd. This patch is against the latest svn revision of
theora-ptalarbvorm.

Speeds up encode on a plant stop-motion clip on a 1 GHz PPC  7447 by ~3%,
timewise. Time spent in oc_enc_frag_sad is reduced from 4.2% to 2.3% and
oc_enc_frag_ssd from 1.2% to 1.0%, as reported by Shark.

Currently this is only integrated into the Xcode build project and need
support for detecting Altivec on platforms other than OS X; on OS X it uses
the sysctl hw.vectorunit.

Thanks,
-- vs

_______________________________________________
theora-dev mailing list
[email protected]
http://lists.xiph.org/mailman/listinfo/theora-dev
ppcenc-draft-0.diff (application/octet-stream, 19.6 KB)
Index: macosx/Theora.xcodeproj/project.pbxproj
===================================================================
--- macosx/Theora.xcodeproj/project.pbxproj	(revision 17313)
+++ macosx/Theora.xcodeproj/project.pbxproj	(working copy)
@@ -128,6 +128,18 @@
 		084C32B70FE4E88300117FC9 /* mmxloop.h in Headers */ = {isa = PBXBuildFile; fileRef = 084C31F30FE4E5BD00117FC9 /* mmxloop.h */; };
 		097729950BCAC60000303091 /* codec.h in Headers */ = {isa = PBXBuildFile; fileRef = 097729930BCAC60000303091 /* codec.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		097729960BCAC60000303091 /* theoradec.h in Headers */ = {isa = PBXBuildFile; fileRef = 097729940BCAC60000303091 /* theoradec.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		14CFA62F11D9D265009E936A /* encfrag_altivec.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62B11D9D265009E936A /* encfrag_altivec.c */; };
+		14CFA63011D9D265009E936A /* ppcenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62C11D9D265009E936A /* ppcenc.c */; };
+		14CFA63111D9D265009E936A /* ppcext.h in Headers */ = {isa = PBXBuildFile; fileRef = 14CFA62D11D9D265009E936A /* ppcext.h */; };
+		14CFA63211D9D265009E936A /* ppcstate.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62E11D9D265009E936A /* ppcstate.c */; };
+		14CFA63311D9D265009E936A /* encfrag_altivec.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62B11D9D265009E936A /* encfrag_altivec.c */; };
+		14CFA63411D9D265009E936A /* ppcenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62C11D9D265009E936A /* ppcenc.c */; };
+		14CFA63511D9D265009E936A /* ppcext.h in Headers */ = {isa = PBXBuildFile; fileRef = 14CFA62D11D9D265009E936A /* ppcext.h */; };
+		14CFA63611D9D265009E936A /* ppcstate.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62E11D9D265009E936A /* ppcstate.c */; };
+		14CFA63711D9D265009E936A /* encfrag_altivec.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62B11D9D265009E936A /* encfrag_altivec.c */; };
+		14CFA63811D9D265009E936A /* ppcenc.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62C11D9D265009E936A /* ppcenc.c */; };
+		14CFA63911D9D265009E936A /* ppcext.h in Headers */ = {isa = PBXBuildFile; fileRef = 14CFA62D11D9D265009E936A /* ppcext.h */; };
+		14CFA63A11D9D265009E936A /* ppcstate.c in Sources */ = {isa = PBXBuildFile; fileRef = 14CFA62E11D9D265009E936A /* ppcstate.c */; };
 		37C9B0140EBB831F0046849C /* theoraenc.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C9B0130EBB831F0046849C /* theoraenc.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		37CA8E390DD747F1005C8CB6 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 37CA8E380DD747F1005C8CB6 /* internal.h */; };
 		734A751909D76ADD002D8FAE /* Ogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 734A751809D76ADD002D8FAE /* Ogg.framework */; };
@@ -195,6 +207,10 @@
 		097729930BCAC60000303091 /* codec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = codec.h; path = ../include/theora/codec.h; sourceTree = SOURCE_ROOT; };
 		097729940BCAC60000303091 /* theoradec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = theoradec.h; path = ../include/theora/theoradec.h; sourceTree = SOURCE_ROOT; };
 		09C8F6430C82FBE500F72188 /* libtheoradec.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtheoradec.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		14CFA62B11D9D265009E936A /* encfrag_altivec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = encfrag_altivec.c; sourceTree = "<group>"; };
+		14CFA62C11D9D265009E936A /* ppcenc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ppcenc.c; sourceTree = "<group>"; };
+		14CFA62D11D9D265009E936A /* ppcext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ppcext.h; sourceTree = "<group>"; };
+		14CFA62E11D9D265009E936A /* ppcstate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ppcstate.c; sourceTree = "<group>"; };
 		32BAE0B70371A74B00C91783 /* Theora_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Theora_Prefix.pch; sourceTree = "<group>"; };
 		37C9B0130EBB831F0046849C /* theoraenc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = theoraenc.h; path = ../include/theora/theoraenc.h; sourceTree = SOURCE_ROOT; };
 		37CA8E380DD747F1005C8CB6 /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = internal.h; path = ../lib/internal.h; sourceTree = SOURCE_ROOT; };
@@ -342,6 +358,7 @@
 		08FB77ACFE841707C02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				14CFA62A11D9D265009E936A /* ppc */,
 				084C31D80FE4E5BD00117FC9 /* lib */,
 				0844FE7E0FCCC99A004A99B0 /* cpu.c */,
 				73514EC70B0C7E5700CEC060 /* cpu.h */,
@@ -351,6 +368,18 @@
 			name = Source;
 			sourceTree = "<group>";
 		};
+		14CFA62A11D9D265009E936A /* ppc */ = {
+			isa = PBXGroup;
+			children = (
+				14CFA62B11D9D265009E936A /* encfrag_altivec.c */,
+				14CFA62C11D9D265009E936A /* ppcenc.c */,
+				14CFA62D11D9D265009E936A /* ppcext.h */,
+				14CFA62E11D9D265009E936A /* ppcstate.c */,
+			);
+			name = ppc;
+			path = ../lib/ppc;
+			sourceTree = SOURCE_ROOT;
+		};
 		734A75BD09D76B96002D8FAE /* Headers */ = {
 			isa = PBXGroup;
 			children = (
@@ -381,6 +410,7 @@
 				084C32380FE4E5BD00117FC9 /* mmxfrag.h in Headers */,
 				084C323A0FE4E5BD00117FC9 /* mmxloop.h in Headers */,
 				084C323C0FE4E5BD00117FC9 /* x86int.h in Headers */,
+				14CFA63911D9D265009E936A /* ppcext.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -401,6 +431,7 @@
 				084C32B10FE4E85300117FC9 /* x86int.h in Headers */,
 				084C32B50FE4E86B00117FC9 /* mmxfrag.h in Headers */,
 				084C32B70FE4E88300117FC9 /* mmxloop.h in Headers */,
+				14CFA63511D9D265009E936A /* ppcext.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -433,6 +464,7 @@
 				084C326F0FE4E5D500117FC9 /* mathops.h in Headers */,
 				084C32710FE4E5D500117FC9 /* modedec.h in Headers */,
 				084C32790FE4E5D500117FC9 /* x86enc.h in Headers */,
+				14CFA63111D9D265009E936A /* ppcext.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -556,6 +588,9 @@
 				084C32390FE4E5BD00117FC9 /* mmxidct.c in Sources */,
 				084C323B0FE4E5BD00117FC9 /* mmxstate.c in Sources */,
 				084C323D0FE4E5BD00117FC9 /* x86state.c in Sources */,
+				14CFA63711D9D265009E936A /* encfrag_altivec.c in Sources */,
+				14CFA63811D9D265009E936A /* ppcenc.c in Sources */,
+				14CFA63A11D9D265009E936A /* ppcstate.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -589,6 +624,9 @@
 				084C32B30FE4E85D00117FC9 /* mmxstate.c in Sources */,
 				084C32B40FE4E86A00117FC9 /* mmxfrag.c in Sources */,
 				084C32B60FE4E87200117FC9 /* mmxidct.c in Sources */,
+				14CFA63311D9D265009E936A /* encfrag_altivec.c in Sources */,
+				14CFA63411D9D265009E936A /* ppcenc.c in Sources */,
+				14CFA63611D9D265009E936A /* ppcstate.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -629,6 +667,9 @@
 				084C32760FE4E5D500117FC9 /* mmxfdct.c in Sources */,
 				084C32770FE4E5D500117FC9 /* sse2fdct.c in Sources */,
 				084C32780FE4E5D500117FC9 /* x86enc.c in Sources */,
+				14CFA62F11D9D265009E936A /* encfrag_altivec.c in Sources */,
+				14CFA63011D9D265009E936A /* ppcenc.c in Sources */,
+				14CFA63211D9D265009E936A /* ppcstate.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -745,7 +786,9 @@
 					"$(inherited)",
 					../include,
 					"../lib/**",
+					/usr/local/include,
 				);
+				ONLY_ACTIVE_ARCH = YES;
 				OTHER_CFLAGS = "";
 				PREBINDING = NO;
 				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
@@ -755,8 +798,7 @@
 		4FADC24808B4156D00ABE55E /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)";
-				ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386";
+				ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)";
 				GCC_OPTIMIZATION_LEVEL = 3;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(GCC_PREPROCESSOR_DEFINITIONS)",
@@ -768,7 +810,9 @@
 					"$(inherited)",
 					../include,
 					"../lib/**",
+					/usr/local/include,
 				);
+				ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH)";
 				OTHER_CFLAGS = (
 					"$(OTHER_CFLAGS)",
 					"-falign-loops=16",
@@ -778,6 +822,7 @@
 					"-funroll-loops",
 				);
 				PER_ARCH_CFLAGS_i386 = "-DOC_X86_ASM";
+				PER_ARCH_CFLAGS_ppc = "-faltivec -DOC_PPC_ASM";
 				PREBINDING = NO;
 				SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
 			};
Index: lib/ppc/ppcstate.c
===================================================================
--- lib/ppc/ppcstate.c	(revision 0)
+++ lib/ppc/ppcstate.c	(revision 0)
@@ -0,0 +1,31 @@
+/********************************************************************
+ *                                                                  *
+ * 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-2010                *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ *                                                                  *
+ ********************************************************************
+ 
+ function:
+   last mod: $Id$
+ 
+ ********************************************************************/
+
+#include <string.h>
+#include "ppcext.h"
+
+#if defined(OC_PPC_ASM)
+
+void oc_state_vtable_init_ppc(oc_theora_state *_state) {
+  oc_state_vtable_init_c(_state);
+ 
+  if(0 && have_altivec()) {
+
+  }   
+}
+
+#endif /* !OC_PPC_ASM */
Index: lib/ppc/ppcenc.c
===================================================================
--- lib/ppc/ppcenc.c	(revision 0)
+++ lib/ppc/ppcenc.c	(revision 0)
@@ -0,0 +1,32 @@
+/********************************************************************
+ *                                                                  *
+ * 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-2010                *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ *                                                                  *
+ ********************************************************************
+ 
+ function:
+   last mod: $Id$
+ 
+ ********************************************************************/
+
+#include <string.h>
+#include "ppcext.h"
+
+#if defined(OC_PPC_ASM)
+
+void oc_enc_vtable_init_ppc(oc_enc_ctx *_enc) {
+  oc_enc_vtable_init_c(_enc);
+    
+  if(have_altivec()) {
+      _enc->opt_vtable.frag_sad=oc_enc_frag_sad_altivec;
+      _enc->opt_vtable.frag_ssd=oc_enc_frag_ssd_altivec;
+  }
+}
+
+#endif /* !OC_PPC_ASM */
Index: lib/ppc/ppcext.h
===================================================================
--- lib/ppc/ppcext.h	(revision 0)
+++ lib/ppc/ppcext.h	(revision 0)
@@ -0,0 +1,104 @@
+/********************************************************************
+ *                                                                  *
+ * 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-2010                *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ *                                                                  *
+ ********************************************************************
+ 
+ function:
+   last mod: $Id$
+ 
+ ********************************************************************/
+
+#ifndef _PPCEXT_H
+#define _PPCEXT_H
+
+#if defined(OC_PPC_ASM)
+
+#include "../internal.h"
+#include "../encint.h"
+
+#if defined(__APPLE__)
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+/**** Common ****/
+
+/* Constant vectors */
+#define ZERO_U8         ((vector unsigned char) (0))
+#define ZERO_U16        ((vector unsigned short) (0))
+#define ZERO_U32        ((vector unsigned int) (0))
+#define ZERO_S32        ((vector signed int) (0))
+
+#define QLEFT_MASK_U8                                                          \
+     ((vector unsigned char) {                                                 \
+        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,                        \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00                         \
+     })
+
+#define LEFT_MASK_U8                                                           \
+    ((vector unsigned char) {                                                  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,                        \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00                         \
+    })
+
+#define C128_U16                                                               \
+    ((vector unsigned short) {                                                 \
+        128, 128, 128, 128, 128, 128, 128, 128,                                \
+    })
+
+static int have_altivec(void) {
+#if defined(__APPLE__)
+    int vectorunit, rc;
+    int name[] = { CTL_HW, HW_VECTORUNIT };
+    size_t len = sizeof(vectorunit);
+    
+    /* Check sysctl hw.vectorunit */
+    rc = sysctl(name, 2, &vectorunit, &len, NULL, 0);
+    if (rc == 0)
+        return (vectorunit > 0);
+    return 0;
+#endif /* !__APPLE__ */
+    
+    return 0;
+}
+
+static inline vector unsigned char load_unaligned(unsigned char *target) {
+  vector unsigned char h, l, mask;
+    
+  h = vec_ld(0, target);
+  l = vec_ld(15, target);
+    
+  mask = vec_lvsl(0, target);
+  return vec_perm(h, l, mask);
+}
+
+static inline void store_left_sub_u8(unsigned char *dst, int by,
+  vector unsigned char v) {
+    OC_ALIGN16(unsigned char tmp[16]);
+    
+    vec_st(v, 0, &tmp);
+    
+    memcpy(dst, tmp, by);
+}
+
+/**** Decoder ****/
+void oc_state_vtable_init_ppc(oc_theora_state *_state);
+
+/**** Encoder ****/
+void oc_enc_vtable_init_ppc(oc_enc_ctx *_enc);
+
+unsigned oc_enc_frag_sad_altivec(const unsigned char *_src, 
+  const unsigned char *_ref, int _ystride);
+unsigned oc_enc_frag_ssd_altivec(const unsigned char *_src, 
+  const unsigned char *_ref, int _ystride);
+
+#endif /* !OC_PPC_ASM */
+
+#endif /* !_PPCEXT_H */
Index: lib/ppc/encfrag_altivec.c
===================================================================
--- lib/ppc/encfrag_altivec.c	(revision 0)
+++ lib/ppc/encfrag_altivec.c	(revision 0)
@@ -0,0 +1,100 @@
+/********************************************************************
+ *                                                                  *
+ * 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-2010                *
+ * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
+ *                                                                  *
+ ********************************************************************
+ 
+ function:
+   last mod: $Id$
+ 
+ ********************************************************************/
+
+#if defined(OC_PPC_ASM)
+
+#include <string.h>
+#include "ppcext.h"
+
+/* Sum of absolute differences, 8x8 */
+unsigned oc_enc_frag_sad_altivec(const unsigned char *_src, 
+  const unsigned char *_ref, int _ystride) {
+    /* Ref: Freescale 'Altivec Sum of Absolute Differences' Application Note */
+    vector unsigned char t0, t1, t2, t3, t4;
+    vector unsigned int sad = ZERO_U32;
+    vector signed int sdiffs;
+    const vector unsigned char mask = LEFT_MASK_U8;
+    int i;
+    unsigned ret;
+    
+    for(i = 0; i < 8; i++) {
+        /* Load 8 bytes from _src and _ref by loading 16-bytes and masking */
+        t0 = load_unaligned(_src);
+        t1 = load_unaligned(_ref);
+        t0 = vec_and(t0, mask);
+        t1 = vec_and(t1, mask);
+        
+        /* Calculate abs(_src - _ref) */
+        t2 = vec_max(t0, t1);
+        t3 = vec_min(t0, t1);
+        t4 = vec_sub(t2, t3);
+        
+        /* sad[n] += t4[n]; elementwise by 32-bit fields */
+        sad = vec_sum4s(t4, sad);
+        
+        _src += _ystride;
+        _ref += _ystride;
+    }
+
+    /* Combine and expand partial sums */
+    sdiffs = vec_sums((vector signed int) sad, ZERO_S32);
+    sdiffs = vec_splat(sdiffs, 3);
+    vec_ste(sdiffs, 0, &ret);
+        
+    return ret;
+}
+
+/* Sum of squared differences, 8x8 */
+unsigned oc_enc_frag_ssd_altivec(const unsigned char *_src, 
+  const unsigned char *_ref, int _ystride) {
+    /* Ref: Freescale 'Altivec Sum of Absolute Differences' Application Note */
+    vector unsigned char t0, t1, t2, t3, t4;
+    vector unsigned int ssd = ZERO_U32;
+    vector signed int sdiffs;
+    const vector unsigned char mask = LEFT_MASK_U8;
+    int i;
+    unsigned ret;
+    
+    for(i = 0; i < 8; i++) {
+        /* Load 8 bytes from _src and _ref by loading 16-bytes and masking */
+        t0 = load_unaligned(_src);
+        t1 = load_unaligned(_ref);
+        t0 = vec_and(t0, mask);
+        t1 = vec_and(t1, mask);
+        
+        /* Calculate abs(_src - _ref) */
+        t2 = vec_max(t0, t1);
+        t3 = vec_min(t0, t1);
+        t4 = vec_sub(t2, t3);
+        
+        /* ssd[n] += t4[n] * t4[n]; elementwise by 32-bit fields */
+        ssd = vec_msum(t4, t4, ssd);
+        
+        _src += _ystride;
+        _ref += _ystride;
+    }
+    
+    /* Combine and expand partial sums */
+    sdiffs = vec_sums((vector signed int) ssd, ZERO_S32);
+    sdiffs = vec_splat(sdiffs, 3);
+    vec_ste(sdiffs, 0, &ret);
+    
+    return ret;
+    
+}
+
+#endif /* !OC_PPC_ASM */
Index: lib/state.c
===================================================================
--- lib/state.c	(revision 17313)
+++ lib/state.c	(working copy)
@@ -25,6 +25,9 @@
 # include "x86/x86int.h"
 #endif
 #endif
+#if defined(OC_PPC_ASM)
+# include "ppc/ppcext.h"
+#endif
 #if defined(OC_DUMP_IMAGES)
 # include <stdio.h>
 # include "png.h"
@@ -611,7 +614,11 @@
 #if defined(OC_X86_ASM)
   oc_state_vtable_init_x86(_state);
 #else
+# if defined (OC_PPC_ASM)
+  oc_state_vtable_init_ppc(_state);
+# else
   oc_state_vtable_init_c(_state);
+# endif
 #endif
 }
 
Index: lib/encode.c
===================================================================
--- lib/encode.c	(revision 17313)
+++ lib/encode.c	(working copy)
@@ -19,6 +19,10 @@
 #include "encint.h"
 #if defined(OC_X86_ASM)
 # include "x86/x86enc.h"
+#else
+# if defined(OC_PPC_ASM)
+#  include "ppc/ppcext.h"
+# endif
 #endif
 
 
@@ -1168,7 +1172,11 @@
 #if defined(OC_X86_ASM)
   oc_enc_vtable_init_x86(_enc);
 #else
+# if defined(OC_PPC_ASM)
+  oc_enc_vtable_init_ppc(_enc);
+# else
   oc_enc_vtable_init_c(_enc);
+# endif
 #endif
   _enc->enquant_table_data=(unsigned char *)_ogg_malloc(
    (64+3)*3*2*_enc->opt_data.enquant_table_size