| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 #!/usr/bin/env perl | 
|  | 2 | 
|  | 3 no strict 'refs'; | 
|  | 4 use warnings; | 
|  | 5 use Getopt::Long; | 
|  | 6 Getopt::Long::Configure("auto_help"); | 
|  | 7 | 
|  | 8 my %ALL_FUNCS = (); | 
|  | 9 my @ALL_ARCHS; | 
|  | 10 my @ALL_FORWARD_DECLS; | 
|  | 11 my @REQUIRES; | 
|  | 12 | 
|  | 13 my %opts = (); | 
|  | 14 my %disabled = (); | 
|  | 15 my %required = (); | 
|  | 16 | 
|  | 17 my @argv; | 
|  | 18 foreach (@ARGV) { | 
|  | 19   $disabled{$1} = 1, next if /--disable-(.*)/; | 
|  | 20   $required{$1} = 1, next if /--require-(.*)/; | 
|  | 21   push @argv, $_; | 
|  | 22 } | 
|  | 23 | 
|  | 24 # NB: use GetOptions() instead of GetOptionsFromArray() for compatibility. | 
|  | 25 @ARGV = @argv; | 
|  | 26 GetOptions( | 
|  | 27   \%opts, | 
|  | 28   'arch=s', | 
|  | 29   'sym=s', | 
|  | 30   'config=s', | 
|  | 31 ); | 
|  | 32 | 
|  | 33 foreach my $opt (qw/arch config/) { | 
|  | 34   if (!defined($opts{$opt})) { | 
|  | 35     warn "--$opt is required!\n"; | 
|  | 36     Getopt::Long::HelpMessage('-exit' => 1); | 
|  | 37   } | 
|  | 38 } | 
|  | 39 | 
|  | 40 foreach my $defs_file (@ARGV) { | 
|  | 41   if (!-f $defs_file) { | 
|  | 42     warn "$defs_file: $!\n"; | 
|  | 43     Getopt::Long::HelpMessage('-exit' => 1); | 
|  | 44   } | 
|  | 45 } | 
|  | 46 | 
|  | 47 open CONFIG_FILE, $opts{config} or | 
|  | 48   die "Error opening config file '$opts{config}': $!\n"; | 
|  | 49 | 
|  | 50 my %config = (); | 
|  | 51 while (<CONFIG_FILE>) { | 
|  | 52   next if !/^CONFIG_/; | 
|  | 53   chomp; | 
|  | 54   my @pair = split /=/; | 
|  | 55   $config{$pair[0]} = $pair[1]; | 
|  | 56 } | 
|  | 57 close CONFIG_FILE; | 
|  | 58 | 
|  | 59 # | 
|  | 60 # Routines for the RTCD DSL to call | 
|  | 61 # | 
|  | 62 sub vpx_config($) { | 
|  | 63   return (defined $config{$_[0]}) ? $config{$_[0]} : ""; | 
|  | 64 } | 
|  | 65 | 
|  | 66 sub specialize { | 
|  | 67   my $fn=$_[0]; | 
|  | 68   shift; | 
|  | 69   foreach my $opt (@_) { | 
|  | 70     eval "\$${fn}_${opt}=${fn}_${opt}"; | 
|  | 71   } | 
|  | 72 } | 
|  | 73 | 
|  | 74 sub add_proto { | 
|  | 75   my $fn = splice(@_, -2, 1); | 
|  | 76   $ALL_FUNCS{$fn} = \@_; | 
|  | 77   specialize $fn, "c"; | 
|  | 78 } | 
|  | 79 | 
|  | 80 sub require { | 
|  | 81   foreach my $fn (keys %ALL_FUNCS) { | 
|  | 82     foreach my $opt (@_) { | 
|  | 83       my $ofn = eval "\$${fn}_${opt}"; | 
|  | 84       next if !$ofn; | 
|  | 85 | 
|  | 86       # if we already have a default, then we can disable it, as we know | 
|  | 87       # we can do better. | 
|  | 88       my $best = eval "\$${fn}_default"; | 
|  | 89       if ($best) { | 
|  | 90         my $best_ofn = eval "\$${best}"; | 
|  | 91         if ($best_ofn && "$best_ofn" ne "$ofn") { | 
|  | 92           eval "\$${best}_link = 'false'"; | 
|  | 93         } | 
|  | 94       } | 
|  | 95       eval "\$${fn}_default=${fn}_${opt}"; | 
|  | 96       eval "\$${fn}_${opt}_link='true'"; | 
|  | 97     } | 
|  | 98   } | 
|  | 99 } | 
|  | 100 | 
|  | 101 sub forward_decls { | 
|  | 102   push @ALL_FORWARD_DECLS, @_; | 
|  | 103 } | 
|  | 104 | 
|  | 105 # | 
|  | 106 # Include the user's directives | 
|  | 107 # | 
|  | 108 foreach my $f (@ARGV) { | 
|  | 109   open FILE, "<", $f or die "cannot open $f: $!\n"; | 
|  | 110   my $contents = join('', <FILE>); | 
|  | 111   close FILE; | 
|  | 112   eval $contents or warn "eval failed: $@\n"; | 
|  | 113 } | 
|  | 114 | 
|  | 115 # | 
|  | 116 # Process the directives according to the command line | 
|  | 117 # | 
|  | 118 sub process_forward_decls() { | 
|  | 119   foreach (@ALL_FORWARD_DECLS) { | 
|  | 120     $_->(); | 
|  | 121   } | 
|  | 122 } | 
|  | 123 | 
|  | 124 sub determine_indirection { | 
|  | 125   vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS); | 
|  | 126   foreach my $fn (keys %ALL_FUNCS) { | 
|  | 127     my $n = ""; | 
|  | 128     my @val = @{$ALL_FUNCS{$fn}}; | 
|  | 129     my $args = pop @val; | 
|  | 130     my $rtyp = "@val"; | 
|  | 131     my $dfn = eval "\$${fn}_default"; | 
|  | 132     $dfn = eval "\$${dfn}"; | 
|  | 133     foreach my $opt (@_) { | 
|  | 134       my $ofn = eval "\$${fn}_${opt}"; | 
|  | 135       next if !$ofn; | 
|  | 136       my $link = eval "\$${fn}_${opt}_link"; | 
|  | 137       next if $link && $link eq "false"; | 
|  | 138       $n .= "x"; | 
|  | 139     } | 
|  | 140     if ($n eq "x") { | 
|  | 141       eval "\$${fn}_indirect = 'false'"; | 
|  | 142     } else { | 
|  | 143       eval "\$${fn}_indirect = 'true'"; | 
|  | 144     } | 
|  | 145   } | 
|  | 146 } | 
|  | 147 | 
|  | 148 sub declare_function_pointers { | 
|  | 149   foreach my $fn (sort keys %ALL_FUNCS) { | 
|  | 150     my @val = @{$ALL_FUNCS{$fn}}; | 
|  | 151     my $args = pop @val; | 
|  | 152     my $rtyp = "@val"; | 
|  | 153     my $dfn = eval "\$${fn}_default"; | 
|  | 154     $dfn = eval "\$${dfn}"; | 
|  | 155     foreach my $opt (@_) { | 
|  | 156       my $ofn = eval "\$${fn}_${opt}"; | 
|  | 157       next if !$ofn; | 
|  | 158       print "$rtyp ${ofn}($args);\n"; | 
|  | 159     } | 
|  | 160     if (eval "\$${fn}_indirect" eq "false") { | 
|  | 161       print "#define ${fn} ${dfn}\n"; | 
|  | 162     } else { | 
|  | 163       print "RTCD_EXTERN $rtyp (*${fn})($args);\n"; | 
|  | 164     } | 
|  | 165     print "\n"; | 
|  | 166   } | 
|  | 167 } | 
|  | 168 | 
|  | 169 sub set_function_pointers { | 
|  | 170   foreach my $fn (sort keys %ALL_FUNCS) { | 
|  | 171     my @val = @{$ALL_FUNCS{$fn}}; | 
|  | 172     my $args = pop @val; | 
|  | 173     my $rtyp = "@val"; | 
|  | 174     my $dfn = eval "\$${fn}_default"; | 
|  | 175     $dfn = eval "\$${dfn}"; | 
|  | 176     if (eval "\$${fn}_indirect" eq "true") { | 
|  | 177       print "    $fn = $dfn;\n"; | 
|  | 178       foreach my $opt (@_) { | 
|  | 179         my $ofn = eval "\$${fn}_${opt}"; | 
|  | 180         next if !$ofn; | 
|  | 181         next if "$ofn" eq "$dfn"; | 
|  | 182         my $link = eval "\$${fn}_${opt}_link"; | 
|  | 183         next if $link && $link eq "false"; | 
|  | 184         my $cond = eval "\$have_${opt}"; | 
|  | 185         print "    if (${cond}) $fn = $ofn;\n" | 
|  | 186       } | 
|  | 187     } | 
|  | 188   } | 
|  | 189 } | 
|  | 190 | 
|  | 191 sub filter { | 
|  | 192   my @filtered; | 
|  | 193   foreach (@_) { push @filtered, $_ unless $disabled{$_}; } | 
|  | 194   return @filtered; | 
|  | 195 } | 
|  | 196 | 
|  | 197 # | 
|  | 198 # Helper functions for generating the arch specific RTCD files | 
|  | 199 # | 
|  | 200 sub common_top() { | 
|  | 201   my $include_guard = uc($opts{sym})."_H_"; | 
|  | 202   print <<EOF; | 
|  | 203 #ifndef ${include_guard} | 
|  | 204 #define ${include_guard} | 
|  | 205 | 
|  | 206 #ifdef RTCD_C | 
|  | 207 #define RTCD_EXTERN | 
|  | 208 #else | 
|  | 209 #define RTCD_EXTERN extern | 
|  | 210 #endif | 
|  | 211 | 
|  | 212 #ifdef __cplusplus | 
|  | 213 extern "C" { | 
|  | 214 #endif | 
|  | 215 | 
|  | 216 EOF | 
|  | 217 | 
|  | 218 process_forward_decls(); | 
|  | 219 print "\n"; | 
|  | 220 declare_function_pointers("c", @ALL_ARCHS); | 
|  | 221 | 
|  | 222 print <<EOF; | 
|  | 223 void $opts{sym}(void); | 
|  | 224 | 
|  | 225 EOF | 
|  | 226 } | 
|  | 227 | 
|  | 228 sub common_bottom() { | 
|  | 229   print <<EOF; | 
|  | 230 | 
|  | 231 #ifdef __cplusplus | 
|  | 232 }  // extern "C" | 
|  | 233 #endif | 
|  | 234 | 
|  | 235 #endif | 
|  | 236 EOF | 
|  | 237 } | 
|  | 238 | 
|  | 239 sub x86() { | 
|  | 240   determine_indirection("c", @ALL_ARCHS); | 
|  | 241 | 
|  | 242   # Assign the helper variable for each enabled extension | 
|  | 243   foreach my $opt (@ALL_ARCHS) { | 
|  | 244     my $opt_uc = uc $opt; | 
|  | 245     eval "\$have_${opt}=\"flags & HAS_${opt_uc}\""; | 
|  | 246   } | 
|  | 247 | 
|  | 248   common_top; | 
|  | 249   print <<EOF; | 
|  | 250 #ifdef RTCD_C | 
|  | 251 #include "vpx_ports/x86.h" | 
|  | 252 static void setup_rtcd_internal(void) | 
|  | 253 { | 
|  | 254     int flags = x86_simd_caps(); | 
|  | 255 | 
|  | 256     (void)flags; | 
|  | 257 | 
|  | 258 EOF | 
|  | 259 | 
|  | 260   set_function_pointers("c", @ALL_ARCHS); | 
|  | 261 | 
|  | 262   print <<EOF; | 
|  | 263 } | 
|  | 264 #endif | 
|  | 265 EOF | 
|  | 266   common_bottom; | 
|  | 267 } | 
|  | 268 | 
|  | 269 sub arm() { | 
|  | 270   determine_indirection("c", @ALL_ARCHS); | 
|  | 271 | 
|  | 272   # Assign the helper variable for each enabled extension | 
|  | 273   foreach my $opt (@ALL_ARCHS) { | 
|  | 274     my $opt_uc = uc $opt; | 
|  | 275     eval "\$have_${opt}=\"flags & HAS_${opt_uc}\""; | 
|  | 276   } | 
|  | 277 | 
|  | 278   common_top; | 
|  | 279   print <<EOF; | 
|  | 280 #include "vpx_config.h" | 
|  | 281 | 
|  | 282 #ifdef RTCD_C | 
|  | 283 #include "vpx_ports/arm.h" | 
|  | 284 static void setup_rtcd_internal(void) | 
|  | 285 { | 
|  | 286     int flags = arm_cpu_caps(); | 
|  | 287 | 
|  | 288     (void)flags; | 
|  | 289 | 
|  | 290 EOF | 
|  | 291 | 
|  | 292   set_function_pointers("c", @ALL_ARCHS); | 
|  | 293 | 
|  | 294   print <<EOF; | 
|  | 295 } | 
|  | 296 #endif | 
|  | 297 EOF | 
|  | 298   common_bottom; | 
|  | 299 } | 
|  | 300 | 
|  | 301 sub mips() { | 
|  | 302   determine_indirection("c", @ALL_ARCHS); | 
|  | 303   common_top; | 
|  | 304 | 
|  | 305   print <<EOF; | 
|  | 306 #include "vpx_config.h" | 
|  | 307 | 
|  | 308 #ifdef RTCD_C | 
|  | 309 static void setup_rtcd_internal(void) | 
|  | 310 { | 
|  | 311 EOF | 
|  | 312 | 
|  | 313   set_function_pointers("c", @ALL_ARCHS); | 
|  | 314 | 
|  | 315   print <<EOF; | 
|  | 316 #if HAVE_DSPR2 | 
|  | 317 #if CONFIG_VP8 | 
|  | 318 void dsputil_static_init(); | 
|  | 319 dsputil_static_init(); | 
|  | 320 #endif | 
|  | 321 #if CONFIG_VP9 | 
|  | 322 void vp9_dsputil_static_init(); | 
|  | 323 vp9_dsputil_static_init(); | 
|  | 324 #endif | 
|  | 325 #endif | 
|  | 326 } | 
|  | 327 #endif | 
|  | 328 EOF | 
|  | 329   common_bottom; | 
|  | 330 } | 
|  | 331 | 
|  | 332 sub unoptimized() { | 
|  | 333   determine_indirection "c"; | 
|  | 334   common_top; | 
|  | 335   print <<EOF; | 
|  | 336 #include "vpx_config.h" | 
|  | 337 | 
|  | 338 #ifdef RTCD_C | 
|  | 339 static void setup_rtcd_internal(void) | 
|  | 340 { | 
|  | 341 EOF | 
|  | 342 | 
|  | 343   set_function_pointers "c"; | 
|  | 344 | 
|  | 345   print <<EOF; | 
|  | 346 } | 
|  | 347 #endif | 
|  | 348 EOF | 
|  | 349   common_bottom; | 
|  | 350 } | 
|  | 351 | 
|  | 352 # | 
|  | 353 # Main Driver | 
|  | 354 # | 
|  | 355 | 
|  | 356 &require("c"); | 
|  | 357 if ($opts{arch} eq 'x86') { | 
|  | 358   @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/); | 
|  | 359   x86; | 
|  | 360 } elsif ($opts{arch} eq 'x86_64') { | 
|  | 361   @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/); | 
|  | 362   @REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/); | 
|  | 363   &require(@REQUIRES); | 
|  | 364   x86; | 
|  | 365 } elsif ($opts{arch} eq 'mips32') { | 
|  | 366   @ALL_ARCHS = filter(qw/mips32/); | 
|  | 367   open CONFIG_FILE, $opts{config} or | 
|  | 368     die "Error opening config file '$opts{config}': $!\n"; | 
|  | 369   while (<CONFIG_FILE>) { | 
|  | 370     if (/HAVE_DSPR2=yes/) { | 
|  | 371       @ALL_ARCHS = filter(qw/mips32 dspr2/); | 
|  | 372       last; | 
|  | 373     } | 
|  | 374   } | 
|  | 375   close CONFIG_FILE; | 
|  | 376   mips; | 
|  | 377 } elsif ($opts{arch} eq 'armv5te') { | 
|  | 378   @ALL_ARCHS = filter(qw/edsp/); | 
|  | 379   arm; | 
|  | 380 } elsif ($opts{arch} eq 'armv6') { | 
|  | 381   @ALL_ARCHS = filter(qw/edsp media/); | 
|  | 382   arm; | 
|  | 383 } elsif ($opts{arch} eq 'armv7') { | 
|  | 384   @ALL_ARCHS = filter(qw/edsp media neon/); | 
|  | 385   arm; | 
|  | 386 } else { | 
|  | 387   unoptimized; | 
|  | 388 } | 
|  | 389 | 
|  | 390 __END__ | 
|  | 391 | 
|  | 392 =head1 NAME | 
|  | 393 | 
|  | 394 rtcd - | 
|  | 395 | 
|  | 396 =head1 SYNOPSIS | 
|  | 397 | 
|  | 398 Usage: rtcd.pl [options] FILE | 
|  | 399 | 
|  | 400 See 'perldoc rtcd.pl' for more details. | 
|  | 401 | 
|  | 402 =head1 DESCRIPTION | 
|  | 403 | 
|  | 404 Reads the Run Time CPU Detections definitions from FILE and generates a | 
|  | 405 C header file on stdout. | 
|  | 406 | 
|  | 407 =head1 OPTIONS | 
|  | 408 | 
|  | 409 Options: | 
|  | 410   --arch=ARCH       Architecture to generate defs for (required) | 
|  | 411   --disable-EXT     Disable support for EXT extensions | 
|  | 412   --require-EXT     Require support for EXT extensions | 
|  | 413   --sym=SYMBOL      Unique symbol to use for RTCD initialization function | 
|  | 414   --config=FILE     File with CONFIG_FOO=yes lines to parse | 
| OLD | NEW | 
|---|