3 ## Copyright (c) 2017, Alliance for Open Media. All rights reserved
5 ## This source code is subject to the terms of the BSD 2 Clause License and
6 ## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7 ## was not distributed with this source code in the LICENSE file, you can
8 ## obtain it at www.aomedia.org/license/software. If the Alliance for Open
9 ## Media Patent License 1.0 was not distributed with this source code in the
10 ## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
15 Getopt
::Long
::Configure
("auto_help") if $Getopt::Long
::VERSION
> 2.32;
19 my @ALL_FORWARD_DECLS;
28 $disabled{$1} = 1, next if /--disable-(.*)/;
29 $required{$1} = 1, next if /--require-(.*)/;
33 # NB: use GetOptions() instead of GetOptionsFromArray() for compatibility.
42 foreach my $opt (qw
/arch config/) {
43 if (!defined($opts{$opt})) {
44 warn "--$opt is required!\n";
45 Getopt
::Long
::HelpMessage
('-exit' => 1);
49 foreach my $defs_file (@ARGV) {
51 warn "$defs_file: $!\n";
52 Getopt
::Long
::HelpMessage
('-exit' => 1);
56 open CONFIG_FILE
, $opts{config
} or
57 die "Error opening config file '$opts{config}': $!\n";
60 while (<CONFIG_FILE
>) {
61 next if !/^(?:CONFIG_|HAVE_)/;
65 $config{$pair[0]} = $pair[1];
70 # Routines for the RTCD DSL to call
73 return (defined $config{$_[0]}) ?
$config{$_[0]} : "";
78 die "'specialize' must be called with a function name and at least one ",
79 "architecture ('C' is implied): \n@_\n";
83 foreach my $opt (@_) {
84 eval "\$${fn}_${opt}=${fn}_${opt}";
89 my $fn = splice(@_, -2, 1);
90 $ALL_FUNCS{$fn} = \
@_;
95 foreach my $fn (keys %ALL_FUNCS) {
96 foreach my $opt (@_) {
97 my $ofn = eval "\$${fn}_${opt}";
100 # if we already have a default, then we can disable it, as we know
102 my $best = eval "\$${fn}_default";
104 my $best_ofn = eval "\$${best}";
105 if ($best_ofn && "$best_ofn" ne "$ofn") {
106 eval "\$${best}_link = 'false'";
109 eval "\$${fn}_default=${fn}_${opt}";
110 eval "\$${fn}_${opt}_link='true'";
116 push @ALL_FORWARD_DECLS, @_;
120 # Include the user's directives
122 foreach my $f (@ARGV) {
123 open FILE
, "<", $f or die "cannot open $f: $!\n";
124 my $contents = join('', <FILE
>);
126 eval $contents or warn "eval failed: $@\n";
130 # Process the directives according to the command line
132 sub process_forward_decls
() {
133 foreach (@ALL_FORWARD_DECLS) {
138 sub determine_indirection
{
139 aom_config
("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS);
140 foreach my $fn (keys %ALL_FUNCS) {
142 my @val = @
{$ALL_FUNCS{$fn}};
145 my $dfn = eval "\$${fn}_default";
146 $dfn = eval "\$${dfn}";
147 foreach my $opt (@_) {
148 my $ofn = eval "\$${fn}_${opt}";
150 my $link = eval "\$${fn}_${opt}_link";
151 next if $link && $link eq "false";
155 eval "\$${fn}_indirect = 'false'";
157 eval "\$${fn}_indirect = 'true'";
162 sub declare_function_pointers
{
163 foreach my $fn (sort keys %ALL_FUNCS) {
164 my @val = @
{$ALL_FUNCS{$fn}};
167 my $dfn = eval "\$${fn}_default";
168 $dfn = eval "\$${dfn}";
169 foreach my $opt (@_) {
170 my $ofn = eval "\$${fn}_${opt}";
172 print "$rtyp ${ofn}($args);\n";
174 if (eval "\$${fn}_indirect" eq "false") {
175 print "#define ${fn} ${dfn}\n";
177 print "RTCD_EXTERN $rtyp (*${fn})($args);\n";
183 sub set_function_pointers
{
184 foreach my $fn (sort keys %ALL_FUNCS) {
185 my @val = @
{$ALL_FUNCS{$fn}};
188 my $dfn = eval "\$${fn}_default";
189 $dfn = eval "\$${dfn}";
190 if (eval "\$${fn}_indirect" eq "true") {
191 print " $fn = $dfn;\n";
192 foreach my $opt (@_) {
193 my $ofn = eval "\$${fn}_${opt}";
195 next if "$ofn" eq "$dfn";
196 my $link = eval "\$${fn}_${opt}_link";
197 next if $link && $link eq "false";
198 my $cond = eval "\$have_${opt}";
199 print " if (${cond}) $fn = $ofn;\n"
207 foreach (@_) { push @filtered, $_ unless $disabled{$_}; }
212 # Helper functions for generating the arch specific RTCD files
215 my $include_guard = uc($opts{sym
})."_H_";
217 // This file is generated. Do not edit.
218 #ifndef ${include_guard}
219 #define ${include_guard}
224 #define RTCD_EXTERN extern
229 process_forward_decls
();
237 declare_function_pointers
("c", @ALL_ARCHS);
240 void $opts{sym}(void);
245 sub common_bottom
() {
257 determine_indirection
("c", @ALL_ARCHS);
259 # Assign the helper variable for each enabled extension
260 foreach my $opt (@ALL_ARCHS) {
261 my $opt_uc = uc $opt;
262 eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
268 #include "aom_ports/x86.h"
269 static void setup_rtcd_internal(void)
271 int flags = x86_simd_caps();
277 set_function_pointers
("c", @ALL_ARCHS);
287 determine_indirection
("c", @ALL_ARCHS);
289 # Assign the helper variable for each enabled extension
290 foreach my $opt (@ALL_ARCHS) {
291 my $opt_uc = uc $opt;
292 eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
297 #include "config/aom_config.h"
300 #include "aom_ports/arm.h"
301 static void setup_rtcd_internal(void)
303 int flags = arm_cpu_caps();
309 set_function_pointers
("c", @ALL_ARCHS);
319 determine_indirection
("c", @ALL_ARCHS);
321 # Assign the helper variable for each enabled extension
322 foreach my $opt (@ALL_ARCHS) {
323 my $opt_uc = uc $opt;
324 eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
330 #include "config/aom_config.h"
333 static void setup_rtcd_internal(void)
337 set_function_pointers
("c", @ALL_ARCHS);
341 void aom_dsputil_static_init();
342 aom_dsputil_static_init();
351 determine_indirection
("c", @ALL_ARCHS);
353 # Assign the helper variable for each enabled extension
354 foreach my $opt (@ALL_ARCHS) {
355 my $opt_uc = uc $opt;
356 eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
362 #include "config/aom_config.h"
365 #include "aom_ports/ppc.h"
366 static void setup_rtcd_internal(void)
368 int flags = ppc_simd_caps();
374 set_function_pointers
("c", @ALL_ARCHS);
384 determine_indirection
"c";
387 #include "config/aom_config.h"
390 static void setup_rtcd_internal(void)
394 set_function_pointers
"c";
408 if ($opts{arch
} eq 'x86') {
409 @ALL_ARCHS = filter
(qw
/mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2/);
411 } elsif ($opts{arch
} eq 'x86_64') {
412 @ALL_ARCHS = filter
(qw
/mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 avx avx2/);
413 @REQUIRES = filter
(keys %required ?
keys %required : qw
/mmx sse sse2/);
416 } elsif ($opts{arch
} eq 'mips32' || $opts{arch
} eq 'mips64') {
417 @ALL_ARCHS = filter
("$opts{arch}");
418 open CONFIG_FILE
, $opts{config
} or
419 die "Error opening config file '$opts{config}': $!\n";
420 while (<CONFIG_FILE
>) {
421 if (/HAVE_DSPR2=yes/) {
422 @ALL_ARCHS = filter
("$opts{arch}", qw
/dspr2/);
425 if (/HAVE_MSA=yes/) {
426 @ALL_ARCHS = filter
("$opts{arch}", qw
/msa/);
432 } elsif ($opts{arch
} =~ /armv7\w?/) {
433 @ALL_ARCHS = filter
(qw
/neon/);
435 } elsif ($opts{arch
} eq 'armv8' || $opts{arch
} eq 'arm64' ) {
436 @ALL_ARCHS = filter
(qw
/neon/);
438 } elsif ($opts{arch
} eq 'ppc') {
439 @ALL_ARCHS = filter
(qw
/vsx/);
453 Usage: rtcd.pl [options] FILE
455 See 'perldoc rtcd.pl' for more details.
459 Reads the Run Time CPU Detections definitions from FILE and generates a
460 C header file on stdout.
465 --arch=ARCH Architecture to generate defs for (required)
466 --disable-EXT Disable support for EXT extensions
467 --require-EXT Require support for EXT extensions
468 --sym=SYMBOL Unique symbol to use for RTCD initialization function
469 --config=FILE File with CONFIG_FOO=yes lines to parse