--- /dev/null
+#!/bin/sh
+self=$0
+
+usage() {
+ cat <<EOF >&2
+Usage: $self [options] FILE
+
+Reads the Run Time CPU Detections definitions from FILE and generates a
+C header file on stdout.
+
+Options:
+ --arch=ARCH Architecture to generate defs for (required)
+ --disable-EXT Disable support for EXT extensions
+ --require-EXT Require support for EXT extensions
+ --sym=SYMBOL Unique symbol to use for RTCD initialization function
+ --config=FILE File with CONFIG_FOO=yes lines to parse
+EOF
+ exit 1
+}
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+die_argument_required() {
+ die "Option $opt requires argument"
+}
+
+for opt; do
+ optval="${opt#*=}"
+ case "$opt" in
+ --arch) die_argument_required;;
+ --arch=*) arch=${optval};;
+ --disable-*) eval "disable_${opt#--disable-}=true";;
+ --require-*) REQUIRES="${REQUIRES}${opt#--require-} ";;
+ --sym) die_argument_required;;
+ --sym=*) symbol=${optval};;
+ --config=*) config_file=${optval};;
+ -h|--help)
+ usage
+ ;;
+ -*)
+ die "Unrecognized option: ${opt%%=*}"
+ ;;
+ *)
+ defs_file="$defs_file $opt"
+ ;;
+ esac
+ shift
+done
+for f in $defs_file; do [ -f "$f" ] || usage; done
+[ -n "$arch" ] || usage
+
+# Import the configuration
+[ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file")
+
+#
+# Routines for the RTCD DSL to call
+#
+prototype() {
+ local rtyp
+ case "$1" in
+ unsigned) rtyp="$1 "; shift;;
+ esac
+ rtyp="${rtyp}$1"
+ local fn="$2"
+ local args="$3"
+
+ eval "${2}_rtyp='$rtyp'"
+ eval "${2}_args='$3'"
+ ALL_FUNCS="$ALL_FUNCS $fn"
+ specialize $fn c
+}
+
+specialize() {
+ local fn="$1"
+ shift
+ for opt in "$@"; do
+ eval "${fn}_${opt}=${fn}_${opt}"
+ done
+}
+
+require() {
+ for fn in $ALL_FUNCS; do
+ for opt in "$@"; do
+ local ofn=$(eval "echo \$${fn}_${opt}")
+ [ -z "$ofn" ] && continue
+
+ # if we already have a default, then we can disable it, as we know
+ # we can do better.
+ local best=$(eval "echo \$${fn}_default")
+ local best_ofn=$(eval "echo \$${best}")
+ [ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false"
+ eval "${fn}_default=${fn}_${opt}"
+ eval "${fn}_${opt}_link=true"
+ done
+ done
+}
+
+forward_decls() {
+ ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1"
+}
+
+#
+# Include the user's directives
+#
+for f in $defs_file; do
+ . $f
+done
+
+#
+# Process the directives according to the command line
+#
+process_forward_decls() {
+ for fn in $ALL_FORWARD_DECLS; do
+ eval $fn
+ done
+}
+
+determine_indirection() {
+ [ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS
+ for fn in $ALL_FUNCS; do
+ local n=""
+ local rtyp="$(eval "echo \$${fn}_rtyp")"
+ local args="$(eval "echo \"\$${fn}_args\"")"
+ local dfn="$(eval "echo \$${fn}_default")"
+ dfn=$(eval "echo \$${dfn}")
+ for opt in "$@"; do
+ local ofn=$(eval "echo \$${fn}_${opt}")
+ [ -z "$ofn" ] && continue
+ local link=$(eval "echo \$${fn}_${opt}_link")
+ [ "$link" = "false" ] && continue
+ n="${n}x"
+ done
+ if [ "$n" = "x" ]; then
+ eval "${fn}_indirect=false"
+ else
+ eval "${fn}_indirect=true"
+ fi
+ done
+}
+
+declare_function_pointers() {
+ for fn in $ALL_FUNCS; do
+ local rtyp="$(eval "echo \$${fn}_rtyp")"
+ local args="$(eval "echo \"\$${fn}_args\"")"
+ local dfn="$(eval "echo \$${fn}_default")"
+ dfn=$(eval "echo \$${dfn}")
+ for opt in "$@"; do
+ local ofn=$(eval "echo \$${fn}_${opt}")
+ [ -z "$ofn" ] && continue
+ echo "$rtyp ${ofn}($args);"
+ done
+ if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then
+ echo "#define ${fn} ${dfn}"
+ else
+ echo "RTCD_EXTERN $rtyp (*${fn})($args);"
+ fi
+ echo
+ done
+}
+
+set_function_pointers() {
+ for fn in $ALL_FUNCS; do
+ local n=""
+ local rtyp="$(eval "echo \$${fn}_rtyp")"
+ local args="$(eval "echo \"\$${fn}_args\"")"
+ local dfn="$(eval "echo \$${fn}_default")"
+ dfn=$(eval "echo \$${dfn}")
+ if $(eval "echo \$${fn}_indirect"); then
+ echo " $fn = $dfn;"
+ for opt in "$@"; do
+ local ofn=$(eval "echo \$${fn}_${opt}")
+ [ -z "$ofn" ] && continue
+ [ "$ofn" = "$dfn" ] && continue;
+ local link=$(eval "echo \$${fn}_${opt}_link")
+ [ "$link" = "false" ] && continue
+ local cond="$(eval "echo \$have_${opt}")"
+ echo " if (${cond}) $fn = $ofn;"
+ done
+ fi
+ echo
+ done
+}
+
+filter() {
+ local filtered
+ for opt in "$@"; do
+ [ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt"
+ done
+ echo $filtered
+}
+
+#
+# Helper functions for generating the arch specific RTCD files
+#
+common_top() {
+ local outfile_basename=$(basename ${symbol:-rtcd.h})
+ local include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | tr -c '[A-Z]' _)
+ cat <<EOF
+#ifndef ${include_guard}
+#define ${include_guard}
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+$(process_forward_decls)
+
+$(declare_function_pointers c $ALL_ARCHS)
+
+void ${symbol:-rtcd}(void);
+EOF
+}
+
+common_bottom() {
+ cat <<EOF
+#endif
+EOF
+}
+
+x86() {
+ determine_indirection c $ALL_ARCHS
+
+ # Assign the helper variable for each enabled extension
+ for opt in $ALL_ARCHS; do
+ local uc=$(echo $opt | tr '[a-z]' '[A-Z]')
+ eval "have_${opt}=\"flags & HAS_${uc}\""
+ done
+
+ cat <<EOF
+$(common_top)
+
+#ifdef RTCD_C
+#include "vpx_ports/x86.h"
+static void setup_rtcd_internal(void)
+{
+ int flags = x86_simd_caps();
+
+ (void)flags;
+
+$(set_function_pointers c $ALL_ARCHS)
+}
+#endif
+$(common_bottom)
+EOF
+}
+
+arm() {
+ determine_indirection c $ALL_ARCHS
+
+ # Assign the helper variable for each enabled extension
+ for opt in $ALL_ARCHS; do
+ local uc=$(echo $opt | tr '[a-z]' '[A-Z]')
+ eval "have_${opt}=\"flags & HAS_${uc}\""
+ done
+
+ cat <<EOF
+$(common_top)
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+ int flags = arm_cpu_caps();
+
+ (void)flags;
+
+$(set_function_pointers c $ALL_ARCHS)
+}
+#endif
+$(common_bottom)
+EOF
+}
+
+
+mips() {
+ determine_indirection c $ALL_ARCHS
+ cat <<EOF
+$(common_top)
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+static void setup_rtcd_internal(void)
+{
+$(set_function_pointers c $ALL_ARCHS)
+#if HAVE_DSPR2
+void dsputil_static_init();
+dsputil_static_init();
+#endif
+}
+#endif
+$(common_bottom)
+EOF
+}
+
+unoptimized() {
+ determine_indirection c
+ cat <<EOF
+$(common_top)
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+static void setup_rtcd_internal(void)
+{
+$(set_function_pointers c)
+}
+#endif
+$(common_bottom)
+EOF
+
+}
+#
+# Main Driver
+#
+require c
+case $arch in
+ x86)
+ ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1)
+ x86
+ ;;
+ x86_64)
+ ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1)
+ REQUIRES=${REQUIRES:-mmx sse sse2}
+ require $(filter $REQUIRES)
+ x86
+ ;;
+ mips32)
+ ALL_ARCHS=$(filter mips32)
+ dspr2=$([ -f "$config_file" ] && eval echo $(grep HAVE_DSPR2 "$config_file"))
+ HAVE_DSPR2="${dspr2#*=}"
+ if [ "$HAVE_DSPR2" = "yes" ]; then
+ ALL_ARCHS=$(filter mips32 dspr2)
+ fi
+ mips
+ ;;
+ armv5te)
+ ALL_ARCHS=$(filter edsp)
+ arm
+ ;;
+ armv6)
+ ALL_ARCHS=$(filter edsp media)
+ arm
+ ;;
+ armv7)
+ ALL_ARCHS=$(filter edsp media neon)
+ arm
+ ;;
+ *)
+ unoptimized
+ ;;
+esac
--- /dev/null
+/*
+ * Copyright (c) 2011 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "vpx_config.h"
+#define RTCD_C
+#include "vpx_rtcd.h"
+
+#if CONFIG_MULTITHREAD && HAVE_PTHREAD_H
+#include <pthread.h>
+static void once(void (*func)(void))
+{
+ static pthread_once_t lock = PTHREAD_ONCE_INIT;
+ pthread_once(&lock, func);
+}
+
+
+#elif CONFIG_MULTITHREAD && defined(_WIN32)
+#include <windows.h>
+static void once(void (*func)(void))
+{
+ /* Using a static initializer here rather than InitializeCriticalSection()
+ * since there's no race-free context in which to execute it. Protecting
+ * it with an atomic op like InterlockedCompareExchangePointer introduces
+ * an x86 dependency, and InitOnceExecuteOnce requires Vista.
+ */
+ static CRITICAL_SECTION lock = {(void *)-1, -1, 0, 0, 0, 0};
+ static int done;
+
+ EnterCriticalSection(&lock);
+
+ if (!done)
+ {
+ func();
+ done = 1;
+ }
+
+ LeaveCriticalSection(&lock);
+}
+
+
+#else
+/* No-op version that performs no synchronization. vpx_rtcd() is idempotent,
+ * so as long as your platform provides atomic loads/stores of pointers
+ * no synchronization is strictly necessary.
+ */
+
+static void once(void (*func)(void))
+{
+ static int done;
+
+ if(!done)
+ {
+ func();
+ done = 1;
+ }
+}
+#endif
+
+
+void vpx_rtcd()
+{
+ once(setup_rtcd_internal);
+}