Home | History | Annotate | Download | only in make
      1 #!/bin/sh
      2 self=$0
      3 
      4 usage() {
      5   cat <<EOF >&2
      6 Usage: $self [options] FILE
      7 
      8 Reads the Run Time CPU Detections definitions from FILE and generates a
      9 C header file on stdout.
     10 
     11 Options:
     12   --arch=ARCH   Architecture to generate defs for (required)
     13   --disable-EXT Disable support for EXT extensions
     14   --require-EXT Require support for EXT extensions
     15   --sym=SYMBOL  Unique symbol to use for RTCD initialization function
     16   --config=FILE File with CONFIG_FOO=yes lines to parse
     17 EOF
     18   exit 1
     19 }
     20 
     21 die() {
     22   echo "$@" >&2
     23   exit 1
     24 }
     25 
     26 die_argument_required() {
     27   die "Option $opt requires argument"
     28 }
     29 
     30 for opt; do
     31   optval="${opt#*=}"
     32   case "$opt" in
     33     --arch) die_argument_required;;
     34     --arch=*) arch=${optval};;
     35     --disable-*) eval "disable_${opt#--disable-}=true";;
     36     --require-*) REQUIRES="${REQUIRES}${opt#--require-} ";;
     37     --sym) die_argument_required;;
     38     --sym=*) symbol=${optval};;
     39     --config=*) config_file=${optval};;
     40     -h|--help)
     41       usage
     42       ;;
     43     -*)
     44       die "Unrecognized option: ${opt%%=*}"
     45       ;;
     46     *)
     47       defs_file="$defs_file $opt"
     48       ;;
     49   esac
     50   shift
     51 done
     52 for f in $defs_file; do [ -f "$f" ] || usage; done
     53 [ -n "$arch" ] || usage
     54 
     55 # Import the configuration
     56 [ -f "$config_file" ] && eval $(grep CONFIG_ "$config_file")
     57 
     58 #
     59 # Routines for the RTCD DSL to call
     60 #
     61 prototype() {
     62   rtyp=""
     63   case "$1" in
     64     unsigned) rtyp="$1 "; shift;;
     65   esac
     66   rtyp="${rtyp}$1"
     67   fn="$2"
     68   args="$3"
     69 
     70   eval "${2}_rtyp='$rtyp'"
     71   eval "${2}_args='$3'"
     72   ALL_FUNCS="$ALL_FUNCS $fn"
     73   specialize $fn c
     74 }
     75 
     76 specialize() {
     77   fn="$1"
     78   shift
     79   for opt in "$@"; do
     80     eval "${fn}_${opt}=${fn}_${opt}"
     81   done
     82 }
     83 
     84 require() {
     85   for fn in $ALL_FUNCS; do
     86     for opt in "$@"; do
     87       ofn=$(eval "echo \$${fn}_${opt}")
     88       [ -z "$ofn" ] && continue
     89 
     90       # if we already have a default, then we can disable it, as we know
     91       # we can do better.
     92       best=$(eval "echo \$${fn}_default")
     93       best_ofn=$(eval "echo \$${best}")
     94       [ -n "$best" ] && [ "$best_ofn" != "$ofn" ] && eval "${best}_link=false"
     95       eval "${fn}_default=${fn}_${opt}"
     96       eval "${fn}_${opt}_link=true"
     97     done
     98   done
     99 }
    100 
    101 forward_decls() {
    102   ALL_FORWARD_DECLS="$ALL_FORWARD_DECLS $1"
    103 }
    104 
    105 #
    106 # Include the user's directives
    107 #
    108 for f in $defs_file; do
    109   . $f
    110 done
    111 
    112 #
    113 # Process the directives according to the command line
    114 #
    115 process_forward_decls() {
    116   for fn in $ALL_FORWARD_DECLS; do
    117     eval $fn
    118   done
    119 }
    120 
    121 determine_indirection() {
    122   [ "$CONFIG_RUNTIME_CPU_DETECT" = "yes" ] || require $ALL_ARCHS
    123   for fn in $ALL_FUNCS; do
    124     n=""
    125     rtyp="$(eval "echo \$${fn}_rtyp")"
    126     args="$(eval "echo \"\$${fn}_args\"")"
    127     dfn="$(eval "echo \$${fn}_default")"
    128     dfn=$(eval "echo \$${dfn}")
    129     for opt in "$@"; do
    130       ofn=$(eval "echo \$${fn}_${opt}")
    131       [ -z "$ofn" ] && continue
    132       link=$(eval "echo \$${fn}_${opt}_link")
    133       [ "$link" = "false" ] && continue
    134       n="${n}x"
    135     done
    136     if [ "$n" = "x" ]; then
    137       eval "${fn}_indirect=false"
    138     else
    139       eval "${fn}_indirect=true"
    140     fi
    141   done
    142 }
    143 
    144 declare_function_pointers() {
    145   for fn in $ALL_FUNCS; do
    146     rtyp="$(eval "echo \$${fn}_rtyp")"
    147     args="$(eval "echo \"\$${fn}_args\"")"
    148     dfn="$(eval "echo \$${fn}_default")"
    149     dfn=$(eval "echo \$${dfn}")
    150     for opt in "$@"; do
    151       ofn=$(eval "echo \$${fn}_${opt}")
    152       [ -z "$ofn" ] && continue
    153       echo "$rtyp ${ofn}($args);"
    154     done
    155     if [ "$(eval "echo \$${fn}_indirect")" = "false" ]; then
    156       echo "#define ${fn} ${dfn}"
    157     else
    158       echo "RTCD_EXTERN $rtyp (*${fn})($args);"
    159     fi
    160     echo
    161   done
    162 }
    163 
    164 set_function_pointers() {
    165   for fn in $ALL_FUNCS; do
    166     n=""
    167     rtyp="$(eval "echo \$${fn}_rtyp")"
    168     args="$(eval "echo \"\$${fn}_args\"")"
    169     dfn="$(eval "echo \$${fn}_default")"
    170     dfn=$(eval "echo \$${dfn}")
    171     if $(eval "echo \$${fn}_indirect"); then
    172       echo "    $fn = $dfn;"
    173       for opt in "$@"; do
    174         ofn=$(eval "echo \$${fn}_${opt}")
    175         [ -z "$ofn" ] && continue
    176         [ "$ofn" = "$dfn" ] && continue;
    177         link=$(eval "echo \$${fn}_${opt}_link")
    178         [ "$link" = "false" ] && continue
    179         cond="$(eval "echo \$have_${opt}")"
    180         echo "    if (${cond}) $fn = $ofn;"
    181       done
    182     fi
    183     echo
    184   done
    185 }
    186 
    187 filter() {
    188   filtered=""
    189   for opt in "$@"; do
    190     [ -z $(eval "echo \$disable_${opt}") ] && filtered="$filtered $opt"
    191   done
    192   echo $filtered
    193 }
    194 
    195 #
    196 # Helper functions for generating the arch specific RTCD files
    197 #
    198 common_top() {
    199   outfile_basename=$(basename ${symbol:-rtcd})
    200   include_guard=$(echo $outfile_basename | tr '[a-z]' '[A-Z]' | \
    201     tr -c '[A-Z0-9]' _)H_
    202   cat <<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 $(process_forward_decls)
    213 
    214 $(declare_function_pointers c $ALL_ARCHS)
    215 
    216 void ${symbol:-rtcd}(void);
    217 EOF
    218 }
    219 
    220 common_bottom() {
    221   cat <<EOF
    222 #endif
    223 EOF
    224 }
    225 
    226 x86() {
    227   determine_indirection c $ALL_ARCHS
    228 
    229   # Assign the helper variable for each enabled extension
    230   for opt in $ALL_ARCHS; do
    231     uc=$(echo $opt | tr '[a-z]' '[A-Z]')
    232     eval "have_${opt}=\"flags & HAS_${uc}\""
    233   done
    234 
    235   cat <<EOF
    236 $(common_top)
    237 
    238 #ifdef RTCD_C
    239 #include "vpx_ports/x86.h"
    240 static void setup_rtcd_internal(void)
    241 {
    242     int flags = x86_simd_caps();
    243 
    244     (void)flags;
    245 
    246 $(set_function_pointers c $ALL_ARCHS)
    247 }
    248 #endif
    249 $(common_bottom)
    250 EOF
    251 }
    252 
    253 arm() {
    254   determine_indirection c $ALL_ARCHS
    255 
    256   # Assign the helper variable for each enabled extension
    257   for opt in $ALL_ARCHS; do
    258     uc=$(echo $opt | tr '[a-z]' '[A-Z]')
    259     eval "have_${opt}=\"flags & HAS_${uc}\""
    260   done
    261 
    262   cat <<EOF
    263 $(common_top)
    264 #include "vpx_config.h"
    265 
    266 #ifdef RTCD_C
    267 #include "vpx_ports/arm.h"
    268 static void setup_rtcd_internal(void)
    269 {
    270     int flags = arm_cpu_caps();
    271 
    272     (void)flags;
    273 
    274 $(set_function_pointers c $ALL_ARCHS)
    275 }
    276 #endif
    277 $(common_bottom)
    278 EOF
    279 }
    280 
    281 
    282 mips() {
    283   determine_indirection c $ALL_ARCHS
    284   cat <<EOF
    285 $(common_top)
    286 #include "vpx_config.h"
    287 
    288 #ifdef RTCD_C
    289 static void setup_rtcd_internal(void)
    290 {
    291 $(set_function_pointers c $ALL_ARCHS)
    292 #if HAVE_DSPR2
    293 #if CONFIG_VP8
    294 void dsputil_static_init();
    295 dsputil_static_init();
    296 #endif
    297 #if CONFIG_VP9
    298 void vp9_dsputil_static_init();
    299 vp9_dsputil_static_init();
    300 #endif
    301 #endif
    302 }
    303 #endif
    304 $(common_bottom)
    305 EOF
    306 }
    307 
    308 unoptimized() {
    309   determine_indirection c
    310   cat <<EOF
    311 $(common_top)
    312 #include "vpx_config.h"
    313 
    314 #ifdef RTCD_C
    315 static void setup_rtcd_internal(void)
    316 {
    317 $(set_function_pointers c)
    318 }
    319 #endif
    320 $(common_bottom)
    321 EOF
    322 
    323 }
    324 #
    325 # Main Driver
    326 #
    327 require c
    328 case $arch in
    329   x86)
    330     ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1 avx avx2)
    331     x86
    332     ;;
    333   x86_64)
    334     ALL_ARCHS=$(filter mmx sse sse2 sse3 ssse3 sse4_1 avx avx2)
    335     REQUIRES=${REQUIRES:-mmx sse sse2}
    336     require $(filter $REQUIRES)
    337     x86
    338     ;;
    339   mips32)
    340     ALL_ARCHS=$(filter mips32)
    341     dspr2=$([ -f "$config_file" ] && eval echo $(grep HAVE_DSPR2 "$config_file"))
    342     HAVE_DSPR2="${dspr2#*=}"
    343     if [ "$HAVE_DSPR2" = "yes" ]; then
    344         ALL_ARCHS=$(filter mips32 dspr2)
    345     fi
    346     mips
    347     ;;
    348   armv5te)
    349     ALL_ARCHS=$(filter edsp)
    350     arm
    351     ;;
    352   armv6)
    353     ALL_ARCHS=$(filter edsp media)
    354     arm
    355     ;;
    356   armv7)
    357     ALL_ARCHS=$(filter edsp media neon)
    358     arm
    359     ;;
    360   *)
    361     unoptimized
    362     ;;
    363 esac
    364