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