| 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
|
| + *
|
|
|
|
|