| Index: source/libvpx/build/make/rtcd.pl
 | 
| ===================================================================
 | 
| --- source/libvpx/build/make/rtcd.pl	(revision 0)
 | 
| +++ source/libvpx/build/make/rtcd.pl	(revision 0)
 | 
| @@ -0,0 +1,414 @@
 | 
| +#!/usr/bin/env perl
 | 
| +
 | 
| +no strict 'refs';
 | 
| +use warnings;
 | 
| +use Getopt::Long;
 | 
| +Getopt::Long::Configure("auto_help");
 | 
| +
 | 
| +my %ALL_FUNCS = ();
 | 
| +my @ALL_ARCHS;
 | 
| +my @ALL_FORWARD_DECLS;
 | 
| +my @REQUIRES;
 | 
| +
 | 
| +my %opts = ();
 | 
| +my %disabled = ();
 | 
| +my %required = ();
 | 
| +
 | 
| +my @argv;
 | 
| +foreach (@ARGV) {
 | 
| +  $disabled{$1} = 1, next if /--disable-(.*)/;
 | 
| +  $required{$1} = 1, next if /--require-(.*)/;
 | 
| +  push @argv, $_;
 | 
| +}
 | 
| +
 | 
| +# NB: use GetOptions() instead of GetOptionsFromArray() for compatibility.
 | 
| +@ARGV = @argv;
 | 
| +GetOptions(
 | 
| +  \%opts,
 | 
| +  'arch=s',
 | 
| +  'sym=s',
 | 
| +  'config=s',
 | 
| +);
 | 
| +
 | 
| +foreach my $opt (qw/arch config/) {
 | 
| +  if (!defined($opts{$opt})) {
 | 
| +    warn "--$opt is required!\n";
 | 
| +    Getopt::Long::HelpMessage('-exit' => 1);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +foreach my $defs_file (@ARGV) {
 | 
| +  if (!-f $defs_file) {
 | 
| +    warn "$defs_file: $!\n";
 | 
| +    Getopt::Long::HelpMessage('-exit' => 1);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +open CONFIG_FILE, $opts{config} or
 | 
| +  die "Error opening config file '$opts{config}': $!\n";
 | 
| +
 | 
| +my %config = ();
 | 
| +while (<CONFIG_FILE>) {
 | 
| +  next if !/^CONFIG_/;
 | 
| +  chomp;
 | 
| +  my @pair = split /=/;
 | 
| +  $config{$pair[0]} = $pair[1];
 | 
| +}
 | 
| +close CONFIG_FILE;
 | 
| +
 | 
| +#
 | 
| +# Routines for the RTCD DSL to call
 | 
| +#
 | 
| +sub vpx_config($) {
 | 
| +  return (defined $config{$_[0]}) ? $config{$_[0]} : "";
 | 
| +}
 | 
| +
 | 
| +sub specialize {
 | 
| +  my $fn=$_[0];
 | 
| +  shift;
 | 
| +  foreach my $opt (@_) {
 | 
| +    eval "\$${fn}_${opt}=${fn}_${opt}";
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub add_proto {
 | 
| +  my $fn = splice(@_, -2, 1);
 | 
| +  $ALL_FUNCS{$fn} = \@_;
 | 
| +  specialize $fn, "c";
 | 
| +}
 | 
| +
 | 
| +sub require {
 | 
| +  foreach my $fn (keys %ALL_FUNCS) {
 | 
| +    foreach my $opt (@_) {
 | 
| +      my $ofn = eval "\$${fn}_${opt}";
 | 
| +      next if !$ofn;
 | 
| +
 | 
| +      # if we already have a default, then we can disable it, as we know
 | 
| +      # we can do better.
 | 
| +      my $best = eval "\$${fn}_default";
 | 
| +      if ($best) {
 | 
| +        my $best_ofn = eval "\$${best}";
 | 
| +        if ($best_ofn && "$best_ofn" ne "$ofn") {
 | 
| +          eval "\$${best}_link = 'false'";
 | 
| +        }
 | 
| +      }
 | 
| +      eval "\$${fn}_default=${fn}_${opt}";
 | 
| +      eval "\$${fn}_${opt}_link='true'";
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub forward_decls {
 | 
| +  push @ALL_FORWARD_DECLS, @_;
 | 
| +}
 | 
| +
 | 
| +#
 | 
| +# Include the user's directives
 | 
| +#
 | 
| +foreach my $f (@ARGV) {
 | 
| +  open FILE, "<", $f or die "cannot open $f: $!\n";
 | 
| +  my $contents = join('', <FILE>);
 | 
| +  close FILE;
 | 
| +  eval $contents or warn "eval failed: $@\n";
 | 
| +}
 | 
| +
 | 
| +#
 | 
| +# Process the directives according to the command line
 | 
| +#
 | 
| +sub process_forward_decls() {
 | 
| +  foreach (@ALL_FORWARD_DECLS) {
 | 
| +    $_->();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub determine_indirection {
 | 
| +  vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS);
 | 
| +  foreach my $fn (keys %ALL_FUNCS) {
 | 
| +    my $n = "";
 | 
| +    my @val = @{$ALL_FUNCS{$fn}};
 | 
| +    my $args = pop @val;
 | 
| +    my $rtyp = "@val";
 | 
| +    my $dfn = eval "\$${fn}_default";
 | 
| +    $dfn = eval "\$${dfn}";
 | 
| +    foreach my $opt (@_) {
 | 
| +      my $ofn = eval "\$${fn}_${opt}";
 | 
| +      next if !$ofn;
 | 
| +      my $link = eval "\$${fn}_${opt}_link";
 | 
| +      next if $link && $link eq "false";
 | 
| +      $n .= "x";
 | 
| +    }
 | 
| +    if ($n eq "x") {
 | 
| +      eval "\$${fn}_indirect = 'false'";
 | 
| +    } else {
 | 
| +      eval "\$${fn}_indirect = 'true'";
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub declare_function_pointers {
 | 
| +  foreach my $fn (sort keys %ALL_FUNCS) {
 | 
| +    my @val = @{$ALL_FUNCS{$fn}};
 | 
| +    my $args = pop @val;
 | 
| +    my $rtyp = "@val";
 | 
| +    my $dfn = eval "\$${fn}_default";
 | 
| +    $dfn = eval "\$${dfn}";
 | 
| +    foreach my $opt (@_) {
 | 
| +      my $ofn = eval "\$${fn}_${opt}";
 | 
| +      next if !$ofn;
 | 
| +      print "$rtyp ${ofn}($args);\n";
 | 
| +    }
 | 
| +    if (eval "\$${fn}_indirect" eq "false") {
 | 
| +      print "#define ${fn} ${dfn}\n";
 | 
| +    } else {
 | 
| +      print "RTCD_EXTERN $rtyp (*${fn})($args);\n";
 | 
| +    }
 | 
| +    print "\n";
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub set_function_pointers {
 | 
| +  foreach my $fn (sort keys %ALL_FUNCS) {
 | 
| +    my @val = @{$ALL_FUNCS{$fn}};
 | 
| +    my $args = pop @val;
 | 
| +    my $rtyp = "@val";
 | 
| +    my $dfn = eval "\$${fn}_default";
 | 
| +    $dfn = eval "\$${dfn}";
 | 
| +    if (eval "\$${fn}_indirect" eq "true") {
 | 
| +      print "    $fn = $dfn;\n";
 | 
| +      foreach my $opt (@_) {
 | 
| +        my $ofn = eval "\$${fn}_${opt}";
 | 
| +        next if !$ofn;
 | 
| +        next if "$ofn" eq "$dfn";
 | 
| +        my $link = eval "\$${fn}_${opt}_link";
 | 
| +        next if $link && $link eq "false";
 | 
| +        my $cond = eval "\$have_${opt}";
 | 
| +        print "    if (${cond}) $fn = $ofn;\n"
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +sub filter {
 | 
| +  my @filtered;
 | 
| +  foreach (@_) { push @filtered, $_ unless $disabled{$_}; }
 | 
| +  return @filtered;
 | 
| +}
 | 
| +
 | 
| +#
 | 
| +# Helper functions for generating the arch specific RTCD files
 | 
| +#
 | 
| +sub common_top() {
 | 
| +  my $include_guard = uc($opts{sym})."_H_";
 | 
| +  print <<EOF;
 | 
| +#ifndef ${include_guard}
 | 
| +#define ${include_guard}
 | 
| +
 | 
| +#ifdef RTCD_C
 | 
| +#define RTCD_EXTERN
 | 
| +#else
 | 
| +#define RTCD_EXTERN extern
 | 
| +#endif
 | 
| +
 | 
| +#ifdef __cplusplus
 | 
| +extern "C" {
 | 
| +#endif
 | 
| +
 | 
| +EOF
 | 
| +
 | 
| +process_forward_decls();
 | 
| +print "\n";
 | 
| +declare_function_pointers("c", @ALL_ARCHS);
 | 
| +
 | 
| +print <<EOF;
 | 
| +void $opts{sym}(void);
 | 
| +
 | 
| +EOF
 | 
| +}
 | 
| +
 | 
| +sub common_bottom() {
 | 
| +  print <<EOF;
 | 
| +
 | 
| +#ifdef __cplusplus
 | 
| +}  // extern "C"
 | 
| +#endif
 | 
| +
 | 
| +#endif
 | 
| +EOF
 | 
| +}
 | 
| +
 | 
| +sub x86() {
 | 
| +  determine_indirection("c", @ALL_ARCHS);
 | 
| +
 | 
| +  # Assign the helper variable for each enabled extension
 | 
| +  foreach my $opt (@ALL_ARCHS) {
 | 
| +    my $opt_uc = uc $opt;
 | 
| +    eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
 | 
| +  }
 | 
| +
 | 
| +  common_top;
 | 
| +  print <<EOF;
 | 
| +#ifdef RTCD_C
 | 
| +#include "vpx_ports/x86.h"
 | 
| +static void setup_rtcd_internal(void)
 | 
| +{
 | 
| +    int flags = x86_simd_caps();
 | 
| +
 | 
| +    (void)flags;
 | 
| +
 | 
| +EOF
 | 
| +
 | 
| +  set_function_pointers("c", @ALL_ARCHS);
 | 
| +
 | 
| +  print <<EOF;
 | 
| +}
 | 
| +#endif
 | 
| +EOF
 | 
| +  common_bottom;
 | 
| +}
 | 
| +
 | 
| +sub arm() {
 | 
| +  determine_indirection("c", @ALL_ARCHS);
 | 
| +
 | 
| +  # Assign the helper variable for each enabled extension
 | 
| +  foreach my $opt (@ALL_ARCHS) {
 | 
| +    my $opt_uc = uc $opt;
 | 
| +    eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
 | 
| +  }
 | 
| +
 | 
| +  common_top;
 | 
| +  print <<EOF;
 | 
| +#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;
 | 
| +
 | 
| +EOF
 | 
| +
 | 
| +  set_function_pointers("c", @ALL_ARCHS);
 | 
| +
 | 
| +  print <<EOF;
 | 
| +}
 | 
| +#endif
 | 
| +EOF
 | 
| +  common_bottom;
 | 
| +}
 | 
| +
 | 
| +sub mips() {
 | 
| +  determine_indirection("c", @ALL_ARCHS);
 | 
| +  common_top;
 | 
| +
 | 
| +  print <<EOF;
 | 
| +#include "vpx_config.h"
 | 
| +
 | 
| +#ifdef RTCD_C
 | 
| +static void setup_rtcd_internal(void)
 | 
| +{
 | 
| +EOF
 | 
| +
 | 
| +  set_function_pointers("c", @ALL_ARCHS);
 | 
| +
 | 
| +  print <<EOF;
 | 
| +#if HAVE_DSPR2
 | 
| +#if CONFIG_VP8
 | 
| +void dsputil_static_init();
 | 
| +dsputil_static_init();
 | 
| +#endif
 | 
| +#if CONFIG_VP9
 | 
| +void vp9_dsputil_static_init();
 | 
| +vp9_dsputil_static_init();
 | 
| +#endif
 | 
| +#endif
 | 
| +}
 | 
| +#endif
 | 
| +EOF
 | 
| +  common_bottom;
 | 
| +}
 | 
| +
 | 
| +sub unoptimized() {
 | 
| +  determine_indirection "c";
 | 
| +  common_top;
 | 
| +  print <<EOF;
 | 
| +#include "vpx_config.h"
 | 
| +
 | 
| +#ifdef RTCD_C
 | 
| +static void setup_rtcd_internal(void)
 | 
| +{
 | 
| +EOF
 | 
| +
 | 
| +  set_function_pointers "c";
 | 
| +
 | 
| +  print <<EOF;
 | 
| +}
 | 
| +#endif
 | 
| +EOF
 | 
| +  common_bottom;
 | 
| +}
 | 
| +
 | 
| +#
 | 
| +# Main Driver
 | 
| +#
 | 
| +
 | 
| +&require("c");
 | 
| +if ($opts{arch} eq 'x86') {
 | 
| +  @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
 | 
| +  x86;
 | 
| +} elsif ($opts{arch} eq 'x86_64') {
 | 
| +  @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
 | 
| +  @REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/);
 | 
| +  &require(@REQUIRES);
 | 
| +  x86;
 | 
| +} elsif ($opts{arch} eq 'mips32') {
 | 
| +  @ALL_ARCHS = filter(qw/mips32/);
 | 
| +  open CONFIG_FILE, $opts{config} or
 | 
| +    die "Error opening config file '$opts{config}': $!\n";
 | 
| +  while (<CONFIG_FILE>) {
 | 
| +    if (/HAVE_DSPR2=yes/) {
 | 
| +      @ALL_ARCHS = filter(qw/mips32 dspr2/);
 | 
| +      last;
 | 
| +    }
 | 
| +  }
 | 
| +  close CONFIG_FILE;
 | 
| +  mips;
 | 
| +} elsif ($opts{arch} eq 'armv5te') {
 | 
| +  @ALL_ARCHS = filter(qw/edsp/);
 | 
| +  arm;
 | 
| +} elsif ($opts{arch} eq 'armv6') {
 | 
| +  @ALL_ARCHS = filter(qw/edsp media/);
 | 
| +  arm;
 | 
| +} elsif ($opts{arch} eq 'armv7') {
 | 
| +  @ALL_ARCHS = filter(qw/edsp media neon/);
 | 
| +  arm;
 | 
| +} else {
 | 
| +  unoptimized;
 | 
| +}
 | 
| +
 | 
| +__END__
 | 
| +
 | 
| +=head1 NAME
 | 
| +
 | 
| +rtcd -
 | 
| +
 | 
| +=head1 SYNOPSIS
 | 
| +
 | 
| +Usage: rtcd.pl [options] FILE
 | 
| +
 | 
| +See 'perldoc rtcd.pl' for more details.
 | 
| +
 | 
| +=head1 DESCRIPTION
 | 
| +
 | 
| +Reads the Run Time CPU Detections definitions from FILE and generates a
 | 
| +C header file on stdout.
 | 
| +
 | 
| +=head1 OPTIONS
 | 
| +
 | 
| +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
 | 
| 
 | 
| Property changes on: source/libvpx/build/make/rtcd.pl
 | 
| ___________________________________________________________________
 | 
| Added: svn:executable
 | 
|    + *
 | 
| 
 | 
| 
 |