Home | History | Annotate | Line # | Download | only in tune
many.pl revision 1.1.1.2
      1      1.1  mrg #! /usr/bin/perl -w
      2      1.1  mrg 
      3  1.1.1.2  mrg # Copyright 2000-2002 Free Software Foundation, Inc.
      4      1.1  mrg #
      5  1.1.1.2  mrg #  This file is part of the GNU MP Library.
      6      1.1  mrg #
      7  1.1.1.2  mrg #  The GNU MP Library is free software; you can redistribute it and/or modify
      8  1.1.1.2  mrg #  it under the terms of either:
      9      1.1  mrg #
     10  1.1.1.2  mrg #    * the GNU Lesser General Public License as published by the Free
     11  1.1.1.2  mrg #      Software Foundation; either version 3 of the License, or (at your
     12  1.1.1.2  mrg #      option) any later version.
     13  1.1.1.2  mrg #
     14  1.1.1.2  mrg #  or
     15  1.1.1.2  mrg #
     16  1.1.1.2  mrg #    * the GNU General Public License as published by the Free Software
     17  1.1.1.2  mrg #      Foundation; either version 2 of the License, or (at your option) any
     18  1.1.1.2  mrg #      later version.
     19  1.1.1.2  mrg #
     20  1.1.1.2  mrg #  or both in parallel, as here.
     21  1.1.1.2  mrg #
     22  1.1.1.2  mrg #  The GNU MP Library is distributed in the hope that it will be useful, but
     23  1.1.1.2  mrg #  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     24  1.1.1.2  mrg #  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     25  1.1.1.2  mrg #  for more details.
     26  1.1.1.2  mrg #
     27  1.1.1.2  mrg #  You should have received copies of the GNU General Public License and the
     28  1.1.1.2  mrg #  GNU Lesser General Public License along with the GNU MP Library.  If not,
     29  1.1.1.2  mrg #  see https://www.gnu.org/licenses/.
     30      1.1  mrg 
     31      1.1  mrg 
     32      1.1  mrg # Usage:  cd $builddir/tune
     33      1.1  mrg #	  perl $srcdir/tune/many.pl [-t] <files/dirs>...
     34      1.1  mrg #
     35      1.1  mrg # Output: speed-many.c
     36      1.1  mrg #         try-many.c
     37      1.1  mrg #         Makefile.many
     38      1.1  mrg #
     39      1.1  mrg # Make alternate versions of various mpn routines available for measuring
     40      1.1  mrg # and testing.
     41      1.1  mrg #
     42      1.1  mrg # The $srcdir and $builddir in the invocation above just means the script
     43      1.1  mrg # lives in the tune source directory, but should be run in the tune build
     44      1.1  mrg # directory.  When not using a separate object directory this just becomes
     45      1.1  mrg #
     46      1.1  mrg #	cd tune
     47      1.1  mrg #	perl many.pl [-t] <files/dirs>...
     48      1.1  mrg #
     49      1.1  mrg #
     50      1.1  mrg # SINGLE FILES
     51      1.1  mrg #
     52      1.1  mrg # Suppose $HOME/newcode/mul_1_experiment.asm is a new implementation of
     53      1.1  mrg # mpn_mul_1, then
     54      1.1  mrg #
     55      1.1  mrg #	cd $builddir/tune
     56      1.1  mrg #	perl $srcdir/tune/many.pl $HOME/newcode/mul_1_experiment.asm
     57      1.1  mrg #
     58      1.1  mrg # will produce rules and renaming so that a speed program incorporating it
     59      1.1  mrg # can be built,
     60      1.1  mrg #
     61      1.1  mrg #	make -f Makefile.many speed-many
     62      1.1  mrg #
     63      1.1  mrg # then for example it can be compared to the standard mul_1,
     64      1.1  mrg #
     65      1.1  mrg #	./speed-many -s 1-30 mpn_mul_1 mpn_mul_1_experiment
     66      1.1  mrg #
     67      1.1  mrg # An expanded try program can be used to check correctness,
     68      1.1  mrg #
     69      1.1  mrg #	make -f Makefile.many try-many
     70      1.1  mrg #
     71      1.1  mrg # and run
     72      1.1  mrg #
     73      1.1  mrg #	./try-many mpn_mul_1_experiment
     74      1.1  mrg #
     75      1.1  mrg # Files can be ".c", ".S" or ".asm".  ".s" files can't be used because they
     76      1.1  mrg # don't get any preprocessing so there's no way to do renaming of their
     77      1.1  mrg # functions.
     78      1.1  mrg #
     79      1.1  mrg #
     80      1.1  mrg # WHOLE DIRECTORIES
     81      1.1  mrg #
     82      1.1  mrg # If a directory is given, then all files in it will be made available.
     83      1.1  mrg # For example,
     84      1.1  mrg #
     85      1.1  mrg #	cd $builddir/tune
     86      1.1  mrg #	perl $srcdir/tune/many.pl $HOME/newcode
     87      1.1  mrg #
     88      1.1  mrg # Each file should have a suffix, like "_experiment" above.
     89      1.1  mrg #
     90      1.1  mrg #
     91      1.1  mrg # MPN DIRECTORIES
     92      1.1  mrg #
     93      1.1  mrg # mpn directories from the GMP source tree can be included, and this is a
     94      1.1  mrg # convenient way to compare multiple implementations suiting different chips
     95      1.1  mrg # in a CPU family.  For example the following would make all x86 routines
     96      1.1  mrg # available,
     97      1.1  mrg #
     98      1.1  mrg #	cd $builddir/tune
     99      1.1  mrg #	perl $srcdir/tune/many.pl `find $srcdir/mpn/x86 -type d`
    100      1.1  mrg #
    101      1.1  mrg # On a new x86 chip a comparison could then be made to see how existing code
    102      1.1  mrg # runs.  For example,
    103      1.1  mrg #
    104      1.1  mrg #	make -f Makefile.many speed-many
    105      1.1  mrg #	./speed-many -s 1-30 -c \
    106      1.1  mrg #		mpn_add_n_x86 mpn_add_n_pentium mpn_add_n_k6 mpn_add_n_k7
    107      1.1  mrg #
    108      1.1  mrg # Files in "mpn" subdirectories don't need the "_experiment" style suffix
    109      1.1  mrg # described above, instead a suffix is constructed from the subdirectory.
    110      1.1  mrg # For example "mpn/x86/k7/mmx/mod_1.asm" will generate a function
    111      1.1  mrg # mpn_mod_1_k7_mmx.  The rule is to take the last directory name after the
    112      1.1  mrg # "mpn", or the last two if there's three or more.  (Check the generated
    113      1.1  mrg # speed-many.c if in doubt.)
    114      1.1  mrg #
    115      1.1  mrg #
    116      1.1  mrg # GENERIC C
    117      1.1  mrg #
    118      1.1  mrg # The mpn/generic directory can be included too, just like any processor
    119      1.1  mrg # specific directory.  This is a good way to compare assembler and generic C
    120      1.1  mrg # implementations.  For example,
    121      1.1  mrg #
    122      1.1  mrg #	cd $builddir/tune
    123      1.1  mrg #	perl $srcdir/tune/many.pl $srcdir/mpn/generic
    124      1.1  mrg #
    125      1.1  mrg # or if just a few routines are of interest, then for example
    126      1.1  mrg #
    127      1.1  mrg #	cd $builddir/tune
    128      1.1  mrg #	perl $srcdir/tune/many.pl \
    129      1.1  mrg #		$srcdir/mpn/generic/lshift.c \
    130      1.1  mrg #		$srcdir/mpn/generic/mod_1.c \
    131      1.1  mrg #		$srcdir/mpn/generic/aorsmul_1.c
    132      1.1  mrg #
    133      1.1  mrg # giving mpn_lshift_generic etc.
    134      1.1  mrg #
    135      1.1  mrg #
    136      1.1  mrg # TESTS/DEVEL PROGRAMS
    137      1.1  mrg #
    138      1.1  mrg # Makefile.many also has rules to build the tests/devel programs with suitable
    139      1.1  mrg # renaming, and with some parameters for correctness or speed.  This is less
    140      1.1  mrg # convenient than the speed and try programs, but provides an independent
    141      1.1  mrg # check.  For example,
    142      1.1  mrg #
    143      1.1  mrg #	make -f Makefile.many tests_mul_1_experimental
    144      1.1  mrg #	./tests_mul_1_experimental
    145      1.1  mrg #
    146      1.1  mrg # and for speed
    147      1.1  mrg #
    148      1.1  mrg #	make -f Makefile.many tests_mul_1_experimental_sp
    149      1.1  mrg #	./tests_mul_1_experimental_sp
    150      1.1  mrg #
    151      1.1  mrg # Not all the programs support speed measuring, in which case only the
    152      1.1  mrg # correctness test will be useful.
    153      1.1  mrg #
    154      1.1  mrg # The parameters for repetitions and host clock speed are -D defines.  Some
    155      1.1  mrg # defaults are provided at the end of Makefile.many, but probably these will
    156      1.1  mrg # want to be overridden.  For example,
    157      1.1  mrg #
    158      1.1  mrg #	rm tests_mul_1_experimental.o
    159      1.1  mrg #	make -f Makefile.many \
    160      1.1  mrg #	   CFLAGS_TESTS="-DSIZE=50 -DTIMES=1000 -DRANDOM -DCLOCK=175000000" \
    161      1.1  mrg #	   tests_mul_1_experimental
    162      1.1  mrg #	./tests_mul_1_experimental
    163      1.1  mrg #
    164      1.1  mrg #
    165      1.1  mrg # OTHER NOTES
    166      1.1  mrg #
    167      1.1  mrg # The mappings of file names to functions, and the macros to then use for
    168      1.1  mrg # speed measuring etc are driven by @table below.  The scheme isn't
    169      1.1  mrg # completely general, it's only got as many variations as have been needed
    170      1.1  mrg # so far.
    171      1.1  mrg #
    172      1.1  mrg # Some functions are only made available in speed-many, or others only in
    173      1.1  mrg # try-many.  An @table entry speed=>none means no speed measuring is
    174      1.1  mrg # available, or try=>none no try program testing.  These can be removed
    175      1.1  mrg # if/when the respective programs get the necessary support.
    176      1.1  mrg #
    177      1.1  mrg # If a file has "1c" or "nc" carry-in entrypoints, they're renamed and made
    178      1.1  mrg # available too.  These are recognised from PROLOGUE or MULFUNC_PROLOGUE in
    179      1.1  mrg # .S and .asm files, or from a line starting with "mpn_foo_1c" in a .c file
    180      1.1  mrg # (possibly via a #define), and on that basis are entirely optional.  This
    181      1.1  mrg # entrypoint matching is done for the standard entrypoints too, but it would
    182      1.1  mrg # be very unusual to have for instance a mul_1c without a mul_1.
    183      1.1  mrg #
    184      1.1  mrg # Some mpz files are recognized.  For example an experimental copy of
    185      1.1  mrg # mpz/powm.c could be included as powm_new.c and would be called
    186      1.1  mrg # mpz_powm_new.  So far only speed measuring is available for these.
    187      1.1  mrg #
    188      1.1  mrg # For the ".S" and ".asm" files, both PIC and non-PIC objects are built.
    189      1.1  mrg # The PIC functions have a "_pic" suffix, for example "mpn_mod_1_k7_mmx_pic".
    190      1.1  mrg # This can be ignored for routines that don't differ for PIC, or for CPUs
    191      1.1  mrg # where everything is PIC anyway.
    192      1.1  mrg #
    193      1.1  mrg # K&R compilers are supported via the same ansi2knr mechanism used by
    194      1.1  mrg # automake, though it's hard to believe anyone will have much interest in
    195      1.1  mrg # measuring a compiler so old that it doesn't even have an ANSI mode.
    196      1.1  mrg #
    197      1.1  mrg # The "-t" option can be used to print a trace of the files found and what's
    198      1.1  mrg # done with them.  A great deal of obscure output is produced, but it can
    199      1.1  mrg # indicate where or why some files aren't being recognised etc.  For
    200      1.1  mrg # example,
    201      1.1  mrg #
    202      1.1  mrg #	cd $builddir/tune
    203      1.1  mrg #	perl $srcdir/tune/many.pl -t $HOME/newcode/add_n_weird.asm
    204      1.1  mrg #
    205      1.1  mrg # In general, when including new code, all that's really necessary is that
    206      1.1  mrg # it will compile or assemble under the current configuration.  It's fine if
    207      1.1  mrg # some code doesn't actually run due to bugs, or to needing a newer CPU or
    208      1.1  mrg # whatever, simply don't ask for the offending routines when invoking
    209      1.1  mrg # speed-many or try-many, or don't try to run them on sizes they don't yet
    210      1.1  mrg # support, or whatever.
    211      1.1  mrg #
    212      1.1  mrg #
    213      1.1  mrg # CPU SPECIFICS
    214      1.1  mrg #
    215      1.1  mrg # x86 - All the x86 code will assemble on any system, but code for newer
    216      1.1  mrg #       chips might not run on older chips.  Expect SIGILLs from new
    217      1.1  mrg #       instructions on old chips.
    218      1.1  mrg #
    219      1.1  mrg #       A few "new" instructions, like cmov for instance, are done as macros
    220      1.1  mrg #       and will generate some equivalent plain i386 code when HAVE_HOST_CPU
    221      1.1  mrg #       in config.m4 indicates an old CPU.  It won't run fast, but it does
    222      1.1  mrg #       make it possible to test correctness.
    223      1.1  mrg #
    224      1.1  mrg #
    225      1.1  mrg # INTERNALS
    226      1.1  mrg #
    227      1.1  mrg # The nonsense involving $ENV is some hooks used during development to add
    228      1.1  mrg # additional functions temporarily.
    229      1.1  mrg #
    230      1.1  mrg #
    231      1.1  mrg # FUTURE
    232      1.1  mrg #
    233      1.1  mrg # Maybe the C files should be compiled pic and non-pic too.  Wait until
    234      1.1  mrg # there's a difference that might be of interest.
    235      1.1  mrg #
    236      1.1  mrg # Warn if a file provides no functions.
    237      1.1  mrg #
    238      1.1  mrg # Allow mpz and mpn files of the same name.  Currently the mpn fib2_ui
    239      1.1  mrg # matching hides the mpz version of that.  Will need to check the file
    240      1.1  mrg # contents to see which it is.  Would be worth allowing an "mpz_" or "mpn_"
    241      1.1  mrg # prefix on the filenames to have working versions of both in one directory.
    242      1.1  mrg #
    243      1.1  mrg #
    244      1.1  mrg # LIMITATIONS
    245      1.1  mrg #
    246      1.1  mrg # Some of the command lines can become very long when a lot of files are
    247      1.1  mrg # included.  If this is a problem on a given system the only suggestion is
    248      1.1  mrg # to run many.pl for just those that are actually wanted at a particular
    249      1.1  mrg # time.
    250      1.1  mrg #
    251      1.1  mrg # DOS 8.3 or SysV 14 char filesystems won't work, since the long filenames
    252      1.1  mrg # generated will almost certainly fail to be unique.
    253      1.1  mrg 
    254      1.1  mrg 
    255      1.1  mrg use strict;
    256      1.1  mrg use File::Basename;
    257      1.1  mrg use Getopt::Std;
    258      1.1  mrg 
    259      1.1  mrg my %opt;
    260      1.1  mrg getopts('t', \%opt);
    261      1.1  mrg 
    262      1.1  mrg my @DIRECTORIES = @ARGV;
    263      1.1  mrg if (defined $ENV{directories}) { push @DIRECTORIES, @{$ENV{directories}} }
    264      1.1  mrg 
    265      1.1  mrg 
    266      1.1  mrg # regexp - matched against the start of the filename.  If a grouping "(...)"
    267      1.1  mrg #          is present then only the first such part is used.
    268      1.1  mrg #
    269      1.1  mrg # mulfunc - filenames to be generated from a multi-function file.
    270      1.1  mrg #
    271      1.1  mrg # funs - functions provided by the file, defaulting to the filename with mpn
    272      1.1  mrg #          (or mpX).
    273      1.1  mrg #
    274      1.1  mrg # mpX - prefix like "mpz", defaulting to "mpn".
    275      1.1  mrg #
    276      1.1  mrg # ret - return value type.
    277      1.1  mrg #
    278      1.1  mrg # args, args_<fun> - arguments for the given function.  If an args_<fun> is
    279      1.1  mrg #          set then it's used, otherwise plain args is used.  "mp_limb_t
    280      1.1  mrg #          carry" is appended for carry-in variants.
    281      1.1  mrg #
    282      1.1  mrg # try - try.c TYPE_ to use, defaulting to TYPE_fun with the function name
    283      1.1  mrg #          in upper case.  "C" is appended for carry-in variants.  Can be
    284      1.1  mrg #          'none' for no try program entry.
    285      1.1  mrg #
    286      1.1  mrg # speed - SPEED_ROUTINE_ to use, handled like "try".
    287      1.1  mrg #
    288      1.1  mrg # speed_flags - SPEED_ROUTINE_ to use, handled like "try".
    289      1.1  mrg 
    290      1.1  mrg 
    291      1.1  mrg my @table =
    292      1.1  mrg     (
    293      1.1  mrg      {
    294      1.1  mrg        'regexp'=> 'add_n|sub_n|addlsh1_n|sublsh1_n|rsh1add_n|rsh1sub_n',
    295      1.1  mrg        'ret'   => 'mp_limb_t',
    296      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    297      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
    298      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    299      1.1  mrg      },
    300      1.1  mrg      {
    301      1.1  mrg        'regexp'=> 'aors_n',
    302      1.1  mrg        'mulfunc'=> ['add_n','sub_n'],
    303      1.1  mrg        'ret'   => 'mp_limb_t',
    304      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    305      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
    306      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    307      1.1  mrg      },
    308      1.1  mrg 
    309      1.1  mrg      {
    310      1.1  mrg        'regexp'=> 'addmul_1|submul_1',
    311      1.1  mrg        'ret'   => 'mp_limb_t',
    312      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
    313      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
    314      1.1  mrg        'speed_flags'=> 'FLAG_R',
    315      1.1  mrg      },
    316      1.1  mrg      {
    317      1.1  mrg        'regexp'=> 'aorsmul_1',
    318      1.1  mrg        'mulfunc'=> ['addmul_1','submul_1'],
    319      1.1  mrg        'ret'   => 'mp_limb_t',
    320      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
    321      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
    322      1.1  mrg        'speed_flags'=> 'FLAG_R',
    323      1.1  mrg      },
    324      1.1  mrg 
    325      1.1  mrg      {
    326      1.1  mrg        'regexp'=> 'addmul_2|submul_2',
    327      1.1  mrg        'ret'   => 'mp_limb_t',
    328      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    329      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_2',
    330      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    331      1.1  mrg        'try-minsize' => 2,
    332      1.1  mrg      },
    333      1.1  mrg      {
    334      1.1  mrg        'regexp'=> 'addmul_3|submul_3',
    335      1.1  mrg        'ret'   => 'mp_limb_t',
    336      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    337      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_3',
    338      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    339      1.1  mrg        'try-minsize' => 3,
    340      1.1  mrg      },
    341      1.1  mrg      {
    342      1.1  mrg        'regexp'=> 'addmul_4|submul_4',
    343      1.1  mrg        'ret'   => 'mp_limb_t',
    344      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    345      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_4',
    346      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    347      1.1  mrg        'try-minsize' => 4,
    348      1.1  mrg      },
    349      1.1  mrg      {
    350      1.1  mrg        'regexp'=> 'addmul_5|submul_5',
    351      1.1  mrg        'ret'   => 'mp_limb_t',
    352      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    353      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_5',
    354      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    355      1.1  mrg        'try-minsize' => 5,
    356      1.1  mrg      },
    357      1.1  mrg      {
    358      1.1  mrg        'regexp'=> 'addmul_6|submul_6',
    359      1.1  mrg        'ret'   => 'mp_limb_t',
    360      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    361      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_6',
    362      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    363      1.1  mrg        'try-minsize' => 6,
    364      1.1  mrg      },
    365      1.1  mrg      {
    366      1.1  mrg        'regexp'=> 'addmul_7|submul_7',
    367      1.1  mrg        'ret'   => 'mp_limb_t',
    368      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    369      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_7',
    370      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    371      1.1  mrg        'try-minsize' => 7,
    372      1.1  mrg      },
    373      1.1  mrg      {
    374      1.1  mrg        'regexp'=> 'addmul_8|submul_8',
    375      1.1  mrg        'ret'   => 'mp_limb_t',
    376      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr yp',
    377      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_8',
    378      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    379      1.1  mrg        'try-minsize' => 8,
    380      1.1  mrg      },
    381      1.1  mrg 
    382      1.1  mrg      {
    383      1.1  mrg        'regexp'=> 'add_n_sub_n',
    384      1.1  mrg        'ret'   => 'mp_limb_t',
    385      1.1  mrg        'args'  => 'mp_ptr sum, mp_ptr diff, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    386      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    387      1.1  mrg      },
    388      1.1  mrg 
    389      1.1  mrg      {
    390      1.1  mrg        'regexp'=> 'com|copyi|copyd',
    391      1.1  mrg        'ret'   => 'void',
    392      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
    393      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_COPY',
    394      1.1  mrg      },
    395      1.1  mrg 
    396      1.1  mrg      {
    397      1.1  mrg        'regexp'=> 'dive_1',
    398      1.1  mrg        'funs'  => ['divexact_1'],
    399      1.1  mrg        'ret'   => 'void',
    400      1.1  mrg        'args'  => 'mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor',
    401      1.1  mrg        'speed_flags'=> 'FLAG_R',
    402      1.1  mrg      },
    403      1.1  mrg      {
    404      1.1  mrg        'regexp'=> 'diveby3',
    405      1.1  mrg        'funs'  => ['divexact_by3c'],
    406      1.1  mrg        'ret'   => 'mp_limb_t',
    407      1.1  mrg        'args'  => 'mp_ptr dst, mp_srcptr src, mp_size_t size',
    408      1.1  mrg        'carrys'=> [''],
    409      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_COPY',
    410      1.1  mrg      },
    411      1.1  mrg 
    412      1.1  mrg      # mpn_preinv_divrem_1 is an optional extra entrypoint
    413      1.1  mrg      {
    414      1.1  mrg        'regexp'=> 'divrem_1',
    415      1.1  mrg        'funs'  => ['divrem_1', 'preinv_divrem_1'],
    416      1.1  mrg        'ret'   => 'mp_limb_t',
    417      1.1  mrg        'args_divrem_1' => 'mp_ptr rp, mp_size_t xsize, mp_srcptr sp, mp_size_t size, mp_limb_t divisor',
    418      1.1  mrg        'args_preinv_divrem_1' => 'mp_ptr rp, mp_size_t xsize, mp_srcptr sp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse, unsigned shift',
    419      1.1  mrg        'speed_flags'=> 'FLAG_R',
    420      1.1  mrg        'speed_suffixes' => ['f'],
    421      1.1  mrg      },
    422      1.1  mrg      {
    423      1.1  mrg        'regexp'=> 'pre_divrem_1',
    424      1.1  mrg        'funs'  => ['preinv_divrem_1'],
    425      1.1  mrg        'ret'   => 'mp_limb_t',
    426      1.1  mrg        'args'  => 'mp_ptr qp, mp_size_t qxn, mp_srcptr ap, mp_size_t asize, mp_limb_t divisor, mp_limb_t inverse, int shift',
    427      1.1  mrg        'speed_flags' => 'FLAG_R',
    428      1.1  mrg      },
    429      1.1  mrg 
    430      1.1  mrg      {
    431      1.1  mrg        'regexp'=> 'divrem_2',
    432      1.1  mrg        'ret'   => 'mp_limb_t',
    433      1.1  mrg        'args'  => 'mp_ptr qp, mp_size_t qxn, mp_srcptr np, mp_size_t nsize, mp_srcptr dp',
    434      1.1  mrg        'try'   => 'none',
    435      1.1  mrg      },
    436      1.1  mrg 
    437      1.1  mrg      {
    438      1.1  mrg        'regexp'=> 'sb_divrem_mn',
    439      1.1  mrg        'ret'   => 'mp_limb_t',
    440      1.1  mrg        'args'  => 'mp_ptr qp, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
    441      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_DC_DIVREM_SB',
    442      1.1  mrg        'try-minsize' => 3,
    443      1.1  mrg      },
    444      1.1  mrg      {
    445      1.1  mrg        'regexp'=> 'tdiv_qr',
    446      1.1  mrg        'ret'   => 'void',
    447      1.1  mrg        'args'  => 'mp_ptr qp, mp_size_t qxn, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
    448      1.1  mrg        'speed' => 'none',
    449      1.1  mrg      },
    450      1.1  mrg 
    451      1.1  mrg      {
    452      1.1  mrg        'regexp'=> 'get_str',
    453      1.1  mrg        'ret'   => 'size_t',
    454      1.1  mrg        'args'  => 'unsigned char *str, int base, mp_ptr mptr, mp_size_t msize',
    455      1.1  mrg        'speed_flags' => 'FLAG_R_OPTIONAL',
    456      1.1  mrg        'try'   => 'none',
    457      1.1  mrg      },
    458      1.1  mrg      {
    459      1.1  mrg        'regexp'=> 'set_str',
    460      1.1  mrg        'ret'   => 'mp_size_t',
    461      1.1  mrg        'args'  => 'mp_ptr xp, const unsigned char *str, size_t str_len, int base',
    462      1.1  mrg        'speed_flags' => 'FLAG_R_OPTIONAL',
    463      1.1  mrg        'try'   => 'none',
    464      1.1  mrg      },
    465      1.1  mrg 
    466      1.1  mrg      {
    467      1.1  mrg        'regexp'=> 'fac_ui',
    468      1.1  mrg        'mpX'   => 'mpz',
    469      1.1  mrg        'ret'   => 'void',
    470      1.1  mrg        'args'  => 'mpz_ptr r, unsigned long n',
    471      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    472      1.1  mrg        'try'   => 'none',
    473      1.1  mrg      },
    474      1.1  mrg 
    475      1.1  mrg      {
    476      1.1  mrg        'regexp'=> 'fib2_ui',
    477      1.1  mrg        'ret'   => 'void',
    478      1.1  mrg        'args'  => 'mp_ptr fp, mp_ptr f1p, unsigned long n',
    479      1.1  mrg        'rename'=> ['__gmp_fib_table'],
    480      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    481      1.1  mrg        'try'   => 'none',
    482      1.1  mrg      },
    483      1.1  mrg      {
    484      1.1  mrg        'regexp'=> 'fib_ui',
    485      1.1  mrg        'mpX'   => 'mpz',
    486      1.1  mrg        'ret'   => 'void',
    487      1.1  mrg        'args'  => 'mpz_ptr fn, unsigned long n',
    488      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    489      1.1  mrg        'try'   => 'none',
    490      1.1  mrg      },
    491      1.1  mrg      {
    492      1.1  mrg        'regexp'=> 'fib2_ui',
    493      1.1  mrg        'mpX'   => 'mpz',
    494      1.1  mrg        'ret'   => 'void',
    495      1.1  mrg        'args'  => 'mpz_ptr fn, mpz_ptr fnsub1, unsigned long n',
    496      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    497      1.1  mrg        'try'   => 'none',
    498      1.1  mrg      },
    499      1.1  mrg 
    500      1.1  mrg      {
    501      1.1  mrg        'regexp'=> 'lucnum_ui',
    502      1.1  mrg        'mpX'   => 'mpz',
    503      1.1  mrg        'ret'   => 'void',
    504      1.1  mrg        'args'  => 'mpz_ptr ln, unsigned long n',
    505      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    506      1.1  mrg        'try'   => 'none',
    507      1.1  mrg      },
    508      1.1  mrg      {
    509      1.1  mrg        'regexp'=> 'lucnum2_ui',
    510      1.1  mrg        'mpX'   => 'mpz',
    511      1.1  mrg        'ret'   => 'void',
    512      1.1  mrg        'args'  => 'mpz_ptr ln, mpz_ptr lnsub1, unsigned long n',
    513      1.1  mrg        'speed_flags' => 'FLAG_NODATA',
    514      1.1  mrg        'try'   => 'none',
    515      1.1  mrg      },
    516      1.1  mrg 
    517      1.1  mrg      {
    518      1.1  mrg        'regexp'=> 'gcd_1',
    519      1.1  mrg        'ret'   => 'mp_limb_t',
    520      1.1  mrg        'args'  => 'mp_ptr xp, mp_size_t xsize, mp_limb_t y',
    521      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    522      1.1  mrg        'speed_suffixes' => ['N'],
    523      1.1  mrg      },
    524      1.1  mrg      {
    525      1.1  mrg        'regexp'=> '(gcd)(?!(_1|ext|_finda))',
    526      1.1  mrg        'ret'   => 'mp_size_t',
    527      1.1  mrg        'args'  => 'mp_ptr gp, mp_ptr up, mp_size_t usize, mp_ptr vp, mp_size_t vsize',
    528      1.1  mrg      },
    529      1.1  mrg      {
    530      1.1  mrg        'regexp'=> 'gcd_finda',
    531      1.1  mrg        'ret'   => 'mp_limb_t',
    532      1.1  mrg        'args'  => 'mp_srcptr cp',
    533      1.1  mrg      },
    534      1.1  mrg 
    535      1.1  mrg 
    536      1.1  mrg      {
    537      1.1  mrg        'regexp'=> 'jacobi',
    538      1.1  mrg        'funs'  => ['jacobi', 'legendre', 'kronecker'],
    539      1.1  mrg        'mpX'   => 'mpz',
    540      1.1  mrg        'ret'   => 'int',
    541      1.1  mrg        'args'  => 'mpz_srcptr a, mpz_srcptr b',
    542      1.1  mrg        'try-legendre' => 'TYPE_MPZ_JACOBI',
    543      1.1  mrg      },
    544      1.1  mrg      {
    545      1.1  mrg        'regexp'=> 'jacbase',
    546      1.1  mrg        'funs'  => ['jacobi_base'],
    547      1.1  mrg        'ret'   => 'mp_limb_t',
    548      1.1  mrg        'args'  => 'mp_limb_t a, mp_limb_t b, int bit1',
    549      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_JACBASE',
    550      1.1  mrg        'try'   => 'none',
    551      1.1  mrg      },
    552      1.1  mrg 
    553      1.1  mrg      {
    554      1.1  mrg        'regexp'=> 'logops_n',
    555      1.1  mrg        'mulfunc'=> ['and_n','andn_n','nand_n','ior_n','iorn_n','nior_n','xor_n','xnor_n'],
    556      1.1  mrg        'ret'   => 'void',
    557      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    558      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
    559      1.1  mrg      },
    560      1.1  mrg 
    561      1.1  mrg      {
    562      1.1  mrg        'regexp'=> '[lr]shift',
    563      1.1  mrg        'ret'   => 'mp_limb_t',
    564      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, unsigned shift',
    565      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
    566      1.1  mrg        'speed_flags'=> 'FLAG_R',
    567      1.1  mrg      },
    568      1.1  mrg 
    569      1.1  mrg      # mpn_preinv_mod_1 is an optional extra entrypoint
    570      1.1  mrg      {
    571      1.1  mrg        'regexp'=> '(mod_1)(?!_rs)',
    572      1.1  mrg        'funs'  => ['mod_1','preinv_mod_1'],
    573      1.1  mrg        'ret'   => 'mp_limb_t',
    574      1.1  mrg        'args_mod_1'       => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor',
    575      1.1  mrg        'args_preinv_mod_1'=> 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
    576      1.1  mrg        'speed_flags'=> 'FLAG_R',
    577      1.1  mrg      },
    578      1.1  mrg      {
    579      1.1  mrg        'regexp'=> 'pre_mod_1',
    580      1.1  mrg        'funs'  => ['preinv_mod_1'],
    581      1.1  mrg        'ret'   => 'mp_limb_t',
    582      1.1  mrg        'args'  => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
    583      1.1  mrg        'speed_flags'=> 'FLAG_R',
    584      1.1  mrg      },
    585      1.1  mrg      {
    586      1.1  mrg        'regexp'=> 'mod_34lsub1',
    587      1.1  mrg        'ret'   => 'mp_limb_t',
    588      1.1  mrg        'args'  => 'mp_srcptr src, mp_size_t len',
    589      1.1  mrg      },
    590      1.1  mrg      {
    591      1.1  mrg        'regexp'=> 'invert_limb',
    592      1.1  mrg        'ret'   => 'mp_limb_t',
    593      1.1  mrg        'args'  => 'mp_limb_t divisor',
    594      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    595      1.1  mrg        'try'   => 'none',
    596      1.1  mrg      },
    597      1.1  mrg 
    598      1.1  mrg      {
    599      1.1  mrg        # not for use with hppa reversed argument versions of mpn_umul_ppmm
    600      1.1  mrg        'regexp'=> 'udiv',
    601      1.1  mrg        'funs'  => ['udiv_qrnnd','udiv_qrnnd_r'],
    602      1.1  mrg        'ret'   => 'mp_limb_t',
    603      1.1  mrg        'args_udiv_qrnnd'   => 'mp_limb_t *, mp_limb_t, mp_limb_t, mp_limb_t',
    604      1.1  mrg        'args_udiv_qrnnd_r' => 'mp_limb_t, mp_limb_t, mp_limb_t, mp_limb_t *',
    605      1.1  mrg        'speed' => 'none',
    606      1.1  mrg        'try-minsize' => 2,
    607      1.1  mrg      },
    608      1.1  mrg 
    609      1.1  mrg      {
    610      1.1  mrg        'regexp'=> 'mode1o',
    611      1.1  mrg        'funs'  => ['modexact_1_odd'],
    612      1.1  mrg        'ret'   => 'mp_limb_t',
    613      1.1  mrg        'args'  => 'mp_srcptr src, mp_size_t size, mp_limb_t divisor',
    614      1.1  mrg        'speed_flags'=> 'FLAG_R',
    615      1.1  mrg      },
    616      1.1  mrg      {
    617      1.1  mrg        'regexp'=> 'modlinv',
    618      1.1  mrg        'funs'  => ['modlimb_invert'],
    619      1.1  mrg        'ret'   => 'mp_limb_t',
    620      1.1  mrg        'args'  => 'mp_limb_t v',
    621      1.1  mrg        'carrys'=> [''],
    622      1.1  mrg        'try'   => 'none',
    623      1.1  mrg      },
    624      1.1  mrg 
    625      1.1  mrg      {
    626      1.1  mrg        'regexp'=> 'mul_1',
    627      1.1  mrg        'ret'   => 'mp_limb_t',
    628      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
    629      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
    630      1.1  mrg        'speed_flags'=> 'FLAG_R',
    631      1.1  mrg      },
    632      1.1  mrg      {
    633      1.1  mrg        'regexp'=> 'mul_2',
    634      1.1  mrg        'ret'   => 'mp_limb_t',
    635      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_srcptr mult',
    636      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_UNARY_2',
    637      1.1  mrg        'speed_flags'=> 'FLAG_R',
    638      1.1  mrg      },
    639      1.1  mrg 
    640      1.1  mrg      {
    641      1.1  mrg        'regexp'=> 'mul_basecase',
    642      1.1  mrg        'ret'   => 'void',
    643      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t xsize, mp_srcptr yp, mp_size_t ysize',
    644      1.1  mrg        'speed_flags' => 'FLAG_R_OPTIONAL | FLAG_RSIZE',
    645      1.1  mrg      },
    646      1.1  mrg      {
    647      1.1  mrg        'regexp'=> '(mul_n)[_.]',
    648      1.1  mrg        'ret'   => 'void',
    649      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    650      1.1  mrg        'rename'=> ['kara_mul_n','kara_sqr_n','toom3_mul_n','toom3_sqr_n'],
    651      1.1  mrg      },
    652      1.1  mrg      {
    653      1.1  mrg        'regexp'=> 'umul',
    654      1.1  mrg        'funs'  => ['umul_ppmm','umul_ppmm_r'],
    655      1.1  mrg        'ret'   => 'mp_limb_t',
    656      1.1  mrg        'args_umul_ppmm'   => 'mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2',
    657      1.1  mrg        'args_umul_ppmm_r' => 'mp_limb_t m1, mp_limb_t m2, mp_limb_t *lowptr',
    658      1.1  mrg        'speed' => 'none',
    659      1.1  mrg        'try-minsize' => 3,
    660      1.1  mrg      },
    661      1.1  mrg 
    662      1.1  mrg 
    663      1.1  mrg      {
    664      1.1  mrg        'regexp'=> 'popham',
    665      1.1  mrg        'mulfunc'=> ['popcount','hamdist'],
    666      1.1  mrg        'ret'   => 'unsigned long',
    667      1.1  mrg        'args_popcount'=> 'mp_srcptr xp, mp_size_t size',
    668      1.1  mrg        'args_hamdist' => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    669      1.1  mrg      },
    670      1.1  mrg      {
    671      1.1  mrg        'regexp'=> 'popcount',
    672      1.1  mrg        'ret'   => 'unsigned long',
    673      1.1  mrg        'args'  => 'mp_srcptr xp, mp_size_t size',
    674      1.1  mrg      },
    675      1.1  mrg      {
    676      1.1  mrg        'regexp'=> 'hamdist',
    677      1.1  mrg        'ret'   => 'unsigned long',
    678      1.1  mrg        'args'  => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
    679      1.1  mrg        # extra renaming to support sharing a data table with mpn_popcount
    680      1.1  mrg        'rename'=> ['popcount'],
    681      1.1  mrg      },
    682      1.1  mrg 
    683      1.1  mrg      {
    684      1.1  mrg        'regexp'=> 'sqr_basecase',
    685      1.1  mrg        'ret'   => 'void',
    686      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
    687      1.1  mrg        'speed' => 'SPEED_ROUTINE_MPN_SQR',
    688      1.1  mrg        'try'   => 'TYPE_SQR',
    689      1.1  mrg      },
    690      1.1  mrg      {
    691      1.1  mrg        'regexp'=> 'sqr_diagonal',
    692      1.1  mrg        'ret'   => 'void',
    693      1.1  mrg        'args'  => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
    694      1.1  mrg        'try'   => 'none',
    695      1.1  mrg      },
    696      1.1  mrg 
    697      1.1  mrg      {
    698      1.1  mrg        'regexp'=> 'sqrtrem',
    699      1.1  mrg        'ret'   => 'mp_size_t',
    700      1.1  mrg        'args'  => 'mp_ptr root, mp_ptr rem, mp_srcptr src, mp_size_t size',
    701      1.1  mrg        'try'   => 'none',
    702      1.1  mrg      },
    703      1.1  mrg 
    704      1.1  mrg      {
    705      1.1  mrg        'regexp'=> 'cntlz',
    706      1.1  mrg        'funs'  => ['count_leading_zeros'],
    707      1.1  mrg        'ret'   => 'unsigned',
    708      1.1  mrg        'args'  => 'mp_limb_t',
    709      1.1  mrg        'macro-before' => "#undef COUNT_LEADING_ZEROS_0",
    710      1.1  mrg        'macro-speed'  =>
    711      1.1  mrg '#ifdef COUNT_LEADING_ZEROS_0
    712      1.1  mrg #define COUNT_LEADING_ZEROS_0_ALLOWED   1
    713      1.1  mrg #else
    714      1.1  mrg #define COUNT_LEADING_ZEROS_0_ALLOWED   0
    715      1.1  mrg #endif
    716      1.1  mrg   SPEED_ROUTINE_COUNT_ZEROS_A (1, COUNT_LEADING_ZEROS_0_ALLOWED);
    717      1.1  mrg   $fun (c, n);
    718      1.1  mrg   SPEED_ROUTINE_COUNT_ZEROS_B ()',
    719      1.1  mrg        'speed_flags'=> 'FLAG_R_OPTIONAL',
    720      1.1  mrg        'try'   => 'none',
    721      1.1  mrg      },
    722      1.1  mrg      {
    723      1.1  mrg        'regexp'=> 'cnttz',
    724      1.1  mrg        'funs'  => ['count_trailing_zeros'],
    725      1.1  mrg        'ret'   => 'unsigned',
    726      1.1  mrg        'args'  => 'mp_limb_t',
    727      1.1  mrg        'macro-speed' => '
    728      1.1  mrg   SPEED_ROUTINE_COUNT_ZEROS_A (0, 0);
    729      1.1  mrg   $fun (c, n);
    730      1.1  mrg   SPEED_ROUTINE_COUNT_ZEROS_B ()',
    731      1.1  mrg        'speed_flags' => 'FLAG_R_OPTIONAL',
    732      1.1  mrg        'try'   => 'none',
    733      1.1  mrg      },
    734      1.1  mrg 
    735      1.1  mrg      {
    736      1.1  mrg        'regexp'=> 'zero',
    737      1.1  mrg        'ret'   => 'void',
    738      1.1  mrg        'args'  => 'mp_ptr ptr, mp_size_t size',
    739      1.1  mrg      },
    740      1.1  mrg 
    741      1.1  mrg      {
    742      1.1  mrg        'regexp'=> '(powm)(?!_ui)',
    743      1.1  mrg        'mpX'   => 'mpz',
    744      1.1  mrg        'ret'   => 'void',
    745      1.1  mrg        'args'  => 'mpz_ptr r, mpz_srcptr b, mpz_srcptr e, mpz_srcptr m',
    746      1.1  mrg        'try'   => 'none',
    747      1.1  mrg      },
    748      1.1  mrg      {
    749      1.1  mrg        'regexp'=> 'powm_ui',
    750      1.1  mrg        'mpX'   => 'mpz',
    751      1.1  mrg        'ret'   => 'void',
    752      1.1  mrg        'args'  => 'mpz_ptr r, mpz_srcptr b, unsigned long e, mpz_srcptr m',
    753      1.1  mrg        'try'   => 'none',
    754      1.1  mrg      },
    755      1.1  mrg 
    756      1.1  mrg      # special for use during development
    757      1.1  mrg      {
    758      1.1  mrg        'regexp'=> 'back',
    759      1.1  mrg        'funs'  => ['back_to_back'],
    760      1.1  mrg        'ret'   => 'void',
    761      1.1  mrg        'args'  => 'void',
    762      1.1  mrg        'pic'   => 'no',
    763      1.1  mrg        'try'   => 'none',
    764      1.1  mrg        'speed_flags'=> 'FLAG_NODATA',
    765      1.1  mrg      },
    766      1.1  mrg      );
    767      1.1  mrg 
    768      1.1  mrg if (defined $ENV{table2}) {
    769      1.1  mrg   my @newtable = @{$ENV{table2}};
    770      1.1  mrg   push @newtable, @table;
    771      1.1  mrg   @table = @newtable;
    772      1.1  mrg }
    773      1.1  mrg 
    774      1.1  mrg 
    775      1.1  mrg my %pictable =
    776      1.1  mrg     (
    777      1.1  mrg      'yes' => {
    778      1.1  mrg        'suffix' =>  '_pic',
    779      1.1  mrg        'asmflags'=> '$(ASMFLAGS_PIC)',
    780      1.1  mrg        'cflags' =>  '$(CFLAGS_PIC)',
    781      1.1  mrg      },
    782      1.1  mrg      'no' => {
    783      1.1  mrg        'suffix' =>  '',
    784      1.1  mrg        'asmflags'=> '',
    785      1.1  mrg        'cflags' =>  '',
    786      1.1  mrg      },
    787      1.1  mrg      );
    788      1.1  mrg 
    789      1.1  mrg 
    790      1.1  mrg my $builddir = $ENV{builddir};
    791      1.1  mrg $builddir = "." if (! defined $builddir);
    792      1.1  mrg 
    793      1.1  mrg my $top_builddir = "${builddir}/..";
    794      1.1  mrg 
    795      1.1  mrg 
    796      1.1  mrg open(MAKEFILE, "<${builddir}/Makefile")
    797      1.1  mrg   or die "Cannot open ${builddir}/Makefile: $!\n"
    798      1.1  mrg        . "Is this a tune build directory?";
    799      1.1  mrg my ($srcdir, $top_srcdir);
    800      1.1  mrg while (<MAKEFILE>) {
    801      1.1  mrg   if (/^srcdir = (.*)/) {     $srcdir = $1;     }
    802      1.1  mrg   if (/^top_srcdir = (.*)/) { $top_srcdir = $1; }
    803      1.1  mrg }
    804      1.1  mrg die "Cannot find \$srcdir in Makefile\n" if (! defined $srcdir);
    805      1.1  mrg die "Cannot find \$top_srcdir in Makefile\n" if (! defined $top_srcdir);
    806      1.1  mrg print "srcdir $srcdir\n" if $opt{'t'};
    807      1.1  mrg print "top_srcdir $top_srcdir\n" if $opt{'t'};
    808      1.1  mrg close(MAKEFILE);
    809      1.1  mrg 
    810      1.1  mrg 
    811      1.1  mrg open(SPEED, ">speed-many.c") or die;
    812      1.1  mrg print SPEED
    813      1.1  mrg "/* speed-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
    814      1.1  mrg 
    815      1.1  mrg ";
    816      1.1  mrg my $SPEED_EXTRA_ROUTINES = "#define SPEED_EXTRA_ROUTINES \\\n";
    817      1.1  mrg my $SPEED_EXTRA_PROTOS = "#define SPEED_EXTRA_PROTOS \\\n";
    818      1.1  mrg my $SPEED_CODE = "";
    819      1.1  mrg 
    820      1.1  mrg open(TRY, ">try-many.c") or die;
    821      1.1  mrg print TRY
    822      1.1  mrg     "/* try-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */\n" .
    823      1.1  mrg     "\n";
    824      1.1  mrg my $TRY_EXTRA_ROUTINES = "#define EXTRA_ROUTINES \\\n";
    825      1.1  mrg my $TRY_EXTRA_PROTOS = "#define EXTRA_PROTOS \\\n";
    826      1.1  mrg 
    827      1.1  mrg open(FD,"<${top_builddir}/libtool") or die "Cannot open \"${top_builddir}/libtool\": $!\n";
    828      1.1  mrg my $pic_flag;
    829      1.1  mrg while (<FD>) {
    830      1.1  mrg   if (/^pic_flag="?([^"]*)"?$/) {
    831      1.1  mrg     $pic_flag=$1;
    832      1.1  mrg     last;
    833      1.1  mrg   }
    834      1.1  mrg }
    835      1.1  mrg close FD;
    836      1.1  mrg if (! defined $pic_flag) {
    837      1.1  mrg   die "Cannot find pic_flag in ${top_builddir}/libtool";
    838      1.1  mrg }
    839      1.1  mrg 
    840      1.1  mrg my $CFLAGS_PIC = $pic_flag;
    841      1.1  mrg 
    842      1.1  mrg my $ASMFLAGS_PIC = "";
    843      1.1  mrg foreach (split /[ \t]/, $pic_flag) {
    844      1.1  mrg   if (/^-D/) {
    845      1.1  mrg     $ASMFLAGS_PIC .= " " . $_;
    846      1.1  mrg   }
    847      1.1  mrg }
    848      1.1  mrg 
    849      1.1  mrg open(MAKEFILE, ">Makefile.many") or die;
    850      1.1  mrg print MAKEFILE
    851      1.1  mrg     "# Makefile.many generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST\n" .
    852      1.1  mrg     "\n" .
    853      1.1  mrg     "all: speed-many try-many\n" .
    854      1.1  mrg     "\n" .
    855      1.1  mrg     "#--------- begin included copy of basic Makefile ----------\n" .
    856      1.1  mrg     "\n";
    857      1.1  mrg open(FD,"<${builddir}/Makefile") or die "Cannot open \"${builddir}/Makefile\": $!\n";
    858      1.1  mrg print MAKEFILE <FD>;
    859      1.1  mrg close FD;
    860      1.1  mrg print MAKEFILE
    861      1.1  mrg     "\n" .
    862      1.1  mrg     "#--------- end included copy of basic Makefile ----------\n" .
    863      1.1  mrg     "\n" .
    864      1.1  mrg     "CFLAGS_PIC = $CFLAGS_PIC\n" .
    865      1.1  mrg     "ASMFLAGS_PIC = $ASMFLAGS_PIC\n" .
    866      1.1  mrg     "\n";
    867      1.1  mrg 
    868      1.1  mrg my $CLEAN="";
    869      1.1  mrg my $MANY_OBJS="";
    870      1.1  mrg 
    871      1.1  mrg 
    872      1.1  mrg sub print_ansi2knr {
    873      1.1  mrg   my ($base,$file,$includes) = @_;
    874      1.1  mrg   if (! defined $file)     { $file = "$base.c"; }
    875      1.1  mrg   if (! defined $includes) { $includes = ""; }
    876      1.1  mrg 
    877      1.1  mrg   print MAKEFILE <<EOF;
    878      1.1  mrg ${base}_.c: $file \$(ANSI2KNR)
    879      1.1  mrg 	\$(CPP) \$(DEFS) \$(INCLUDES) $includes \$(AM_CPPFLAGS) \$(CPPFLAGS) $file | sed 's/^# \([0-9]\)/#line \\1/' | \$(ANSI2KNR) >${base}_.c
    880      1.1  mrg 
    881      1.1  mrg EOF
    882      1.1  mrg }
    883      1.1  mrg 
    884      1.1  mrg 
    885      1.1  mrg # Spawning a glob is a touch slow when there's lots of files.
    886      1.1  mrg my @files = ();
    887      1.1  mrg foreach my $dir (@DIRECTORIES) {
    888      1.1  mrg   print "dir $dir\n" if $opt{'t'};
    889      1.1  mrg   if (-f $dir) {
    890      1.1  mrg     push @files,$dir;
    891      1.1  mrg   } else {
    892      1.1  mrg     if (! opendir DD,$dir) {
    893      1.1  mrg       print "Cannot open $dir: $!\n";
    894      1.1  mrg     } else {
    895      1.1  mrg       push @files, map {$_="$dir/$_"} grep /\.(c|asm|S|h)$/, readdir DD;
    896      1.1  mrg       closedir DD;
    897      1.1  mrg     }
    898      1.1  mrg   }
    899      1.1  mrg }
    900      1.1  mrg @files = sort @files;
    901      1.1  mrg print "@files ",join(" ",@files),"\n" if $opt{'t'};
    902      1.1  mrg 
    903      1.1  mrg my $count_files = 0;
    904      1.1  mrg my $count_functions = 0;
    905      1.1  mrg my %seen_obj;
    906      1.1  mrg my %seen_file;
    907      1.1  mrg 
    908      1.1  mrg foreach my $file_full (@files) {
    909      1.1  mrg   if (! -f $file_full) {
    910      1.1  mrg     print "Not a file: $file_full\n";
    911      1.1  mrg     next;
    912      1.1  mrg   }
    913      1.1  mrg   if (defined $seen_file{$file_full}) {
    914      1.1  mrg     print "Skipping duplicate file: $file_full\n";
    915      1.1  mrg     next;
    916      1.1  mrg   }
    917      1.1  mrg   $seen_file{$file_full} = 1;
    918      1.1  mrg 
    919      1.1  mrg   my ($FILE,$path,$lang) = fileparse($file_full,"\.[a-zA-Z]+");
    920      1.1  mrg   $path =~ s/\/$//;
    921      1.1  mrg   print "file $FILE path $path lang $lang\n" if $opt{'t'};
    922      1.1  mrg 
    923      1.1  mrg   my @pic_choices;
    924      1.1  mrg   if ($lang eq '.asm')  { @pic_choices=('no','yes'); }
    925      1.1  mrg   elsif ($lang eq '.c') { @pic_choices=('no'); }
    926      1.1  mrg   elsif ($lang eq '.S') { @pic_choices=('no','yes'); }
    927      1.1  mrg   elsif ($lang eq '.h') { @pic_choices=('no'); }
    928      1.1  mrg   else { next };
    929      1.1  mrg 
    930      1.1  mrg   my ($t, $file_match);
    931      1.1  mrg   foreach my $p (@table) {
    932      1.1  mrg     # print " ",$p->{'regexp'},"\n" if $opt{'t'};
    933      1.1  mrg     if ($FILE =~ "^($p->{'regexp'})") {
    934      1.1  mrg       $t = $p;
    935      1.1  mrg       $file_match = $1;
    936      1.1  mrg       $file_match = $2 if defined $2;
    937      1.1  mrg       last;
    938      1.1  mrg     }
    939      1.1  mrg   }
    940      1.1  mrg   next if ! defined $t;
    941      1.1  mrg   print "match $t->{'regexp'} $FILE ($file_full)\n" if $opt{'t'};
    942      1.1  mrg 
    943      1.1  mrg   if (! open FD,"<$file_full") { print "Can't open $file_full: $!\n"; next }
    944      1.1  mrg   my @file_contents = <FD>;
    945      1.1  mrg   close FD;
    946      1.1  mrg 
    947      1.1  mrg   my $objs;
    948      1.1  mrg   if (defined $t->{'mulfunc'}) { $objs = $t->{'mulfunc'}; }
    949      1.1  mrg   else                         { $objs = [$file_match]; }
    950      1.1  mrg   print "objs @$objs\n" if $opt{'t'};
    951      1.1  mrg 
    952      1.1  mrg   my $ret = $t->{'ret'};
    953      1.1  mrg   if (! defined $ret && $lang eq '.h') { $ret = ''; }
    954      1.1  mrg   if (! defined $ret) { die "$FILE return type not defined\n" };
    955      1.1  mrg   print "ret $ret\n" if $opt{'t'};
    956      1.1  mrg 
    957      1.1  mrg   my $mpX = $t->{'mpX'};
    958      1.1  mrg   if (! defined $mpX) { $mpX = ($lang eq '.h' ? '' : 'mpn'); }
    959      1.1  mrg   $mpX = "${mpX}_" if $mpX ne '';
    960      1.1  mrg   print "mpX $mpX\n" if $opt{'t'};
    961      1.1  mrg 
    962      1.1  mrg   my $carrys;
    963      1.1  mrg   if (defined $t->{'carrys'}) { $carrys = $t->{'carrys'}; }
    964      1.1  mrg   else                        { $carrys = ['','c'];       }
    965      1.1  mrg   print "carrys $carrys @$carrys\n" if $opt{'t'};
    966      1.1  mrg 
    967      1.1  mrg   # some restriction functions are implemented, but they're not very useful
    968      1.1  mrg   my $restriction='';
    969      1.1  mrg 
    970      1.1  mrg   my $suffix;
    971      1.1  mrg   if ($FILE =~ ("${file_match}_(.+)")) {
    972      1.1  mrg     $suffix = $1;
    973      1.1  mrg   } elsif ($path =~ /\/mp[zn]\/(.*)$/) {
    974      1.1  mrg     # derive the suffix from the path
    975      1.1  mrg     $suffix = $1;
    976      1.1  mrg     $suffix =~ s/\//_/g;
    977      1.1  mrg     # use last directory name, or if there's 3 or more then the last two
    978      1.1  mrg     if ($suffix =~ /([^_]*_)+([^_]+_[^_]+)$/) {
    979      1.1  mrg       $suffix = $2;
    980      1.1  mrg     } elsif ($suffix =~ /([^_]*_)*([^_]+)$/) {
    981      1.1  mrg       $suffix = $2;
    982      1.1  mrg     }
    983      1.1  mrg   } else {
    984      1.1  mrg     die "Can't determine suffix for: $file_full (path $path)\n";
    985      1.1  mrg   }
    986      1.1  mrg   print "suffix $suffix\n" if $opt{'t'};
    987      1.1  mrg 
    988      1.1  mrg   $count_files++;
    989      1.1  mrg 
    990      1.1  mrg   foreach my $obj (@{$objs}) {
    991      1.1  mrg     print "obj $obj\n" if $opt{'t'};
    992      1.1  mrg 
    993      1.1  mrg     my $obj_with_suffix = "${obj}_$suffix";
    994      1.1  mrg     if (defined $seen_obj{$obj_with_suffix}) {
    995      1.1  mrg       print "Skipping duplicate object: $obj_with_suffix\n";
    996      1.1  mrg       print "   first from: $seen_obj{$obj_with_suffix}\n";
    997      1.1  mrg       print "   now from:   $file_full\n";
    998      1.1  mrg       next;
    999      1.1  mrg     }
   1000      1.1  mrg     $seen_obj{$obj_with_suffix} = $file_full;
   1001      1.1  mrg 
   1002      1.1  mrg     my $funs = $t->{'funs'};
   1003      1.1  mrg     $funs = [$obj] if ! defined $funs;
   1004      1.1  mrg     print "funs @$funs\n" if $opt{'t'};
   1005      1.1  mrg 
   1006      1.1  mrg     if (defined $t->{'pic'}) { @pic_choices = ('no'); }
   1007      1.1  mrg 
   1008      1.1  mrg     foreach my $pic (map {$pictable{$_}} @pic_choices) {
   1009      1.1  mrg       print "pic $pic->{'suffix'}\n" if $opt{'t'};
   1010      1.1  mrg 
   1011      1.1  mrg       my $objbase = "${obj}_$suffix$pic->{'suffix'}";
   1012      1.1  mrg       print "objbase $objbase\n" if $opt{'t'};
   1013      1.1  mrg 
   1014      1.1  mrg       if ($path !~ "." && -f "${objbase}.c") {
   1015      1.1  mrg 	die "Already have ${objbase}.c";
   1016      1.1  mrg       }
   1017      1.1  mrg 
   1018      1.1  mrg       my $tmp_file = "tmp-$objbase.c";
   1019      1.1  mrg 
   1020      1.1  mrg       my $renaming;
   1021      1.1  mrg       foreach my $fun (@{$funs}) {
   1022      1.1  mrg         if ($mpX eq 'mpn_' && $lang eq '.c') {
   1023      1.1  mrg           $renaming .= "\t\t-DHAVE_NATIVE_mpn_$fun=1 \\\n";
   1024      1.1  mrg         }
   1025      1.1  mrg 
   1026      1.1  mrg         # The carry-in variant is with a "c" appended, unless there's a "_1"
   1027      1.1  mrg         # somewhere, eg. "modexact_1_odd", in which case that becomes "_1c".
   1028      1.1  mrg 	my $fun_carry = $fun;
   1029      1.1  mrg 	if (! ($fun_carry =~ s/_1/_1c/)) { $fun_carry = "${fun}c"; }
   1030      1.1  mrg 
   1031      1.1  mrg 	$renaming .=
   1032      1.1  mrg 	    "\t\t-D__g$mpX$fun=$mpX${fun}_$suffix$pic->{'suffix'} \\\n" .
   1033      1.1  mrg 	    "\t\t-D__g$mpX$fun_carry=$mpX${fun_carry}_$suffix$pic->{'suffix'} \\\n";
   1034      1.1  mrg       }
   1035      1.1  mrg       foreach my $r (@{$t->{'rename'}}) {
   1036      1.1  mrg 	if ($r =~ /^__gmp/) {
   1037      1.1  mrg 	  $renaming .= "\\\n" .
   1038      1.1  mrg 	      "\t\t-D$r=${r}_$suffix$pic->{'suffix'}";
   1039      1.1  mrg 	} else {
   1040      1.1  mrg 	  $renaming .= "\\\n" .
   1041      1.1  mrg 	      "\t\t-D__g$mpX$r=$mpX${r}_$suffix$pic->{'suffix'}";
   1042      1.1  mrg 	}
   1043      1.1  mrg       }
   1044      1.1  mrg       print "renaming $renaming\n" if $opt{'t'};
   1045      1.1  mrg 
   1046      1.1  mrg       print MAKEFILE "\n";
   1047      1.1  mrg       if ($lang eq '.asm') {
   1048      1.1  mrg 	print MAKEFILE
   1049      1.1  mrg 	    "$objbase.o: $file_full \$(ASM_HEADERS)\n" .
   1050      1.1  mrg 	    "	\$(M4) \$(M4FLAGS) -DOPERATION_$obj $pic->{'asmflags'} \\\n" .
   1051      1.1  mrg   	    "$renaming" .
   1052      1.1  mrg 	    "		$file_full >tmp-$objbase.s\n" .
   1053      1.1  mrg             "	\$(CCAS) \$(COMPILE_FLAGS) $pic->{'cflags'} tmp-$objbase.s -o $objbase.o\n" .
   1054      1.1  mrg             "	\$(RM_TMP) tmp-$objbase.s\n";
   1055      1.1  mrg 	$MANY_OBJS .= " $objbase.o";
   1056      1.1  mrg 
   1057      1.1  mrg       } elsif ($lang eq '.c') {
   1058      1.1  mrg 	print MAKEFILE
   1059      1.1  mrg 	    "$objbase.o: $file_full\n" .
   1060      1.1  mrg 	    "	\$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
   1061      1.1  mrg   	    "$renaming" .
   1062      1.1  mrg 	    "		-c $file_full -o $objbase.o\n";
   1063      1.1  mrg 	print_ansi2knr($objbase,
   1064      1.1  mrg 		       $file_full,
   1065      1.1  mrg 		       " -DOPERATION_$obj\\\n$renaming\t\t");
   1066      1.1  mrg 	$MANY_OBJS .= " $objbase\$U.o";
   1067      1.1  mrg 
   1068      1.1  mrg       } elsif ($lang eq '.S') {
   1069      1.1  mrg 	print MAKEFILE
   1070      1.1  mrg 	    "$objbase.o: $file_full\n" .
   1071      1.1  mrg             "	\$(COMPILE) -g $pic->{'asmflags'} \\\n" .
   1072      1.1  mrg   	    "$renaming" .
   1073      1.1  mrg             "	-c $file_full -o $objbase.o\n";
   1074      1.1  mrg 	$MANY_OBJS .= " $objbase.o";
   1075      1.1  mrg 
   1076      1.1  mrg       } elsif ($lang eq '.h') {
   1077      1.1  mrg 	print MAKEFILE
   1078      1.1  mrg 	    "$objbase.o: tmp-$objbase.c $file_full\n" .
   1079      1.1  mrg 	    "	\$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
   1080      1.1  mrg   	    "$renaming" .
   1081      1.1  mrg 	    "		-c tmp-$objbase.c -o $objbase.o\n";
   1082      1.1  mrg 	print_ansi2knr($objbase,
   1083      1.1  mrg 		       "tmp-$objbase.c",
   1084      1.1  mrg 		       " -DOPERATION_$obj\\\n$renaming\t\t");
   1085      1.1  mrg 	$MANY_OBJS .= " $objbase\$U.o";
   1086      1.1  mrg 
   1087      1.1  mrg         $CLEAN .= " tmp-$objbase.c";
   1088      1.1  mrg 	open(TMP_C,">tmp-$objbase.c")
   1089      1.1  mrg 	    or die "Can't create tmp-$objbase.c: $!\n";
   1090      1.1  mrg 	print TMP_C
   1091      1.1  mrg "/* tmp-$objbase.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
   1092      1.1  mrg 
   1093      1.1  mrg #include \"gmp.h\"
   1094      1.1  mrg #include \"gmp-impl.h\"
   1095      1.1  mrg #include \"longlong.h\"
   1096      1.1  mrg #include \"speed.h\"
   1097      1.1  mrg 
   1098      1.1  mrg ";
   1099      1.1  mrg       }
   1100      1.1  mrg 
   1101      1.1  mrg       my $tests_program = "$top_srcdir/tests/devel/$obj.c";
   1102      1.1  mrg       if (-f $tests_program) {
   1103      1.1  mrg 	$tests_program = "\$(top_srcdir)/tests/devel/$obj.c";
   1104      1.1  mrg 	print_ansi2knr("tests_${objbase}",
   1105      1.1  mrg 		       $tests_program,
   1106      1.1  mrg 		       "\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
   1107      1.1  mrg 	print_ansi2knr("tests_${objbase}_sp",
   1108      1.1  mrg 		       $tests_program,
   1109      1.1  mrg 		       "\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
   1110      1.1  mrg 
   1111      1.1  mrg 	print MAKEFILE <<EOF;
   1112      1.1  mrg tests_$objbase.o: $tests_program
   1113      1.1  mrg 	\$(COMPILE) \$(CFLAGS_TESTS) \\
   1114      1.1  mrg $renaming		-c $tests_program -o tests_$objbase.o
   1115      1.1  mrg 
   1116      1.1  mrg tests_$objbase: $objbase\$U.o tests_$objbase\$U.o ../libgmp.la
   1117      1.1  mrg 	\$(LINK) tests_$objbase\$U.o $objbase\$U.o ../libgmp.la -o tests_$objbase
   1118      1.1  mrg 
   1119      1.1  mrg tests_${objbase}_sp.o: $tests_program
   1120      1.1  mrg 	\$(COMPILE) \$(CFLAGS_TESTS_SP) \\
   1121      1.1  mrg $renaming		-c $tests_program -o tests_${objbase}_sp.o
   1122      1.1  mrg 
   1123      1.1  mrg tests_${objbase}_sp: $objbase\$U.o tests_${objbase}_sp\$U.o ../libgmp.la
   1124      1.1  mrg 	\$(LINK) tests_${objbase}_sp\$U.o $objbase\$U.o ../libgmp.la -o tests_${objbase}_sp
   1125      1.1  mrg 
   1126      1.1  mrg EOF
   1127      1.1  mrg         $CLEAN .= " tests_$objbase tests_${objbase}_sp";
   1128      1.1  mrg       }
   1129      1.1  mrg 
   1130      1.1  mrg       foreach my $fun (@{$funs}) {
   1131      1.1  mrg 	print "fun $fun\n" if $opt{'t'};
   1132      1.1  mrg 
   1133      1.1  mrg 	if ($lang eq '.h') {
   1134      1.1  mrg           my $macro_before = $t->{'macro_before'};
   1135      1.1  mrg           $macro_before = "" if ! defined $macro_before;
   1136      1.1  mrg 	  print TMP_C
   1137      1.1  mrg "$macro_before
   1138      1.1  mrg #undef $fun
   1139      1.1  mrg #include \"$file_full\"
   1140      1.1  mrg 
   1141      1.1  mrg ";
   1142      1.1  mrg 	}
   1143      1.1  mrg 
   1144      1.1  mrg 	my $args = $t->{"args_$fun"};
   1145      1.1  mrg 	if (! defined $args) { $args = $t->{'args'}; }
   1146      1.1  mrg 	if (! defined $args) { die "Need args for $fun\n"; }
   1147      1.1  mrg 	print "args $args\n" if $opt{'t'};
   1148      1.1  mrg 
   1149      1.1  mrg 	foreach my $carry (@$carrys) {
   1150      1.1  mrg 	  print "carry $carry\n" if $opt{'t'};
   1151      1.1  mrg 
   1152      1.1  mrg 	  my $fun_carry = $fun;
   1153      1.1  mrg 	  if (! ($fun_carry =~ s/_1/_1$carry/)) { $fun_carry = "$fun$carry"; }
   1154      1.1  mrg           print "fun_carry $fun_carry\n" if $opt{'t'};
   1155      1.1  mrg 
   1156      1.1  mrg 	  if ($lang =~ /\.(asm|S)/
   1157      1.1  mrg 	      && ! grep(m"PROLOGUE\((.* )?$mpX$fun_carry[ ,)]",@file_contents)) {
   1158      1.1  mrg 	    print "no PROLOGUE $mpX$fun_carry\n" if $opt{'t'};
   1159      1.1  mrg 	    next;
   1160      1.1  mrg 	  }
   1161      1.1  mrg 	  if ($lang eq '.c'
   1162      1.1  mrg 	      && ! grep(m"^(#define FUNCTION\s+)?$mpX$fun_carry\W", @file_contents)) {
   1163      1.1  mrg 	    print "no mention of $mpX$fun_carry\n" if $opt{'t'};
   1164      1.1  mrg 	    next;
   1165      1.1  mrg 	  }
   1166      1.1  mrg 	  if ($lang eq '.h'
   1167      1.1  mrg 	      && ! grep(m"^#define $fun_carry\W", @file_contents)) {
   1168      1.1  mrg 	    print "no mention of #define $fun_carry\n" if $opt{'t'};
   1169      1.1  mrg 	    next;
   1170      1.1  mrg 	  }
   1171      1.1  mrg 
   1172      1.1  mrg 	  $count_functions++;
   1173      1.1  mrg 
   1174      1.1  mrg 	  my $carryarg;
   1175      1.1  mrg 	  if (defined $t->{'carryarg'}) { $carryarg = $t->{'carryarg'}; }
   1176      1.1  mrg 	  if ($carry eq '')             { $carryarg = ''; }
   1177      1.1  mrg 	  else                          { $carryarg = ', mp_limb_t carry'; }
   1178      1.1  mrg 	  print "carryarg $carryarg\n" if $opt{'t'};
   1179      1.1  mrg 
   1180      1.1  mrg 	  my $funfull="$mpX${fun_carry}_$suffix$pic->{'suffix'}";
   1181      1.1  mrg 	  print "funfull $funfull\n" if $opt{'t'};
   1182      1.1  mrg 
   1183      1.1  mrg 	  if ($lang ne '.h') {
   1184      1.1  mrg 	    my $proto = "$t->{'ret'} $funfull _PROTO (($args$carryarg)); \\\n";
   1185      1.1  mrg 	    $SPEED_EXTRA_PROTOS .= $proto;
   1186      1.1  mrg 	    $TRY_EXTRA_PROTOS .= $proto;
   1187      1.1  mrg 	  }
   1188      1.1  mrg 
   1189      1.1  mrg 	  my $try_type = $t->{"try-$fun"};
   1190      1.1  mrg 	  $try_type = $t->{'try'} if ! defined $try_type;
   1191      1.1  mrg 	  if (! defined $try_type) {
   1192      1.1  mrg 	    if ($mpX eq 'mpn_') {
   1193      1.1  mrg 	      $try_type = "TYPE_\U$fun_carry";
   1194      1.1  mrg 	    } else {
   1195      1.1  mrg 	      $try_type = "TYPE_\U$mpX\U$fun_carry";
   1196      1.1  mrg 	    }
   1197      1.1  mrg 	  }
   1198      1.1  mrg 	  print "try_type $try_type\n" if $opt{'t'};
   1199      1.1  mrg 
   1200      1.1  mrg 	  my $try_minsize = $t->{'try-minsize'};
   1201      1.1  mrg 	  if (defined $try_minsize) {
   1202      1.1  mrg 	    $try_minsize = ", " . $try_minsize;
   1203      1.1  mrg 	  } else {
   1204      1.1  mrg 	    $try_minsize = "";
   1205      1.1  mrg 	  }
   1206      1.1  mrg 	  print "try_minsize $try_minsize\n" if $opt{'t'};
   1207      1.1  mrg 
   1208      1.1  mrg 	  if ($try_type ne 'none') {
   1209      1.1  mrg 	    $TRY_EXTRA_ROUTINES .=
   1210      1.1  mrg 		"  { TRY($mpX${fun_carry}_$suffix$pic->{'suffix'}), $try_type$try_minsize }, \\\n";
   1211      1.1  mrg 	  }
   1212      1.1  mrg 
   1213      1.1  mrg 	  my $speed_flags = $t->{'speed_flags'};
   1214      1.1  mrg 	  $speed_flags = '0' if ! defined $speed_flags;
   1215      1.1  mrg 	  print "speed_flags $speed_flags\n" if $opt{'t'};
   1216      1.1  mrg 
   1217      1.1  mrg 	  my $speed_routine = $t->{'speed'};
   1218      1.1  mrg 	  $speed_routine = "SPEED_ROUTINE_\U$mpX\U$fun"
   1219      1.1  mrg 	      if !defined $speed_routine;
   1220      1.1  mrg 	  if (! ($speed_routine =~ s/_1/_1\U$carry/)) {
   1221      1.1  mrg 	    $speed_routine = "$speed_routine\U$carry";
   1222      1.1  mrg 	  }
   1223      1.1  mrg 	  print "speed_routine $speed_routine\n" if $opt{'t'};
   1224      1.1  mrg 
   1225      1.1  mrg 	  my @speed_suffixes = ();
   1226      1.1  mrg 	  push (@speed_suffixes, '') if $speed_routine ne 'none';
   1227      1.1  mrg 	  push (@speed_suffixes, @{$t->{'speed_suffixes'}})
   1228      1.1  mrg 	      if defined $t->{'speed_suffixes'};
   1229      1.1  mrg 
   1230      1.1  mrg           my $macro_speed = $t->{'macro-speed'};
   1231      1.1  mrg           $macro_speed = "$speed_routine ($fun_carry)" if ! defined $macro_speed;
   1232      1.1  mrg           $macro_speed =~ s/\$fun/$fun_carry/g;
   1233      1.1  mrg 
   1234      1.1  mrg 	  foreach my $S (@speed_suffixes) {
   1235      1.1  mrg 	    my $Sfunfull="$mpX${fun_carry}${S}_$suffix$pic->{'suffix'}";
   1236      1.1  mrg 
   1237      1.1  mrg 	    $SPEED_EXTRA_PROTOS .=
   1238      1.1  mrg 	      "double speed_$Sfunfull _PROTO ((struct speed_params *s)); \\\n";
   1239      1.1  mrg 	    $SPEED_EXTRA_ROUTINES .=
   1240      1.1  mrg 	      "  { \"$Sfunfull\", speed_$Sfunfull, $speed_flags }, \\\n";
   1241      1.1  mrg 	    if ($lang eq '.h') {
   1242      1.1  mrg               print TMP_C
   1243      1.1  mrg "double
   1244      1.1  mrg speed_$Sfunfull (struct speed_params *s)
   1245      1.1  mrg {
   1246      1.1  mrg $macro_speed
   1247      1.1  mrg }
   1248      1.1  mrg 
   1249      1.1  mrg ";
   1250      1.1  mrg             } else {
   1251      1.1  mrg 	      $SPEED_CODE .=
   1252      1.1  mrg 	        "double\n" .
   1253      1.1  mrg 	        "speed_$Sfunfull (struct speed_params *s)\n" .
   1254      1.1  mrg                 "{\n" .
   1255      1.1  mrg                 "$restriction" .
   1256      1.1  mrg 	        "  $speed_routine\U$S\E ($funfull)\n" .
   1257      1.1  mrg                 "}\n";
   1258      1.1  mrg             }
   1259      1.1  mrg 	  }
   1260      1.1  mrg 	}
   1261      1.1  mrg       }
   1262      1.1  mrg     }
   1263      1.1  mrg   }
   1264      1.1  mrg }
   1265      1.1  mrg 
   1266      1.1  mrg 
   1267      1.1  mrg print SPEED $SPEED_EXTRA_PROTOS . "\n";
   1268      1.1  mrg print SPEED $SPEED_EXTRA_ROUTINES . "\n";
   1269      1.1  mrg if (defined $ENV{speedinc}) { print SPEED $ENV{speedinc} . "\n"; }
   1270      1.1  mrg print SPEED
   1271      1.1  mrg     "#include \"speed.c\"\n" .
   1272      1.1  mrg     "\n";
   1273      1.1  mrg print SPEED $SPEED_CODE;
   1274      1.1  mrg 
   1275      1.1  mrg print TRY $TRY_EXTRA_ROUTINES . "\n";
   1276      1.1  mrg print TRY $TRY_EXTRA_PROTOS . "\n";
   1277      1.1  mrg my $tryinc = "";
   1278      1.1  mrg if (defined $ENV{tryinc}) {
   1279      1.1  mrg   $tryinc = $ENV{tryinc};
   1280      1.1  mrg   print TRY "#include \"$tryinc\"\n";
   1281      1.1  mrg }
   1282      1.1  mrg print "tryinc $tryinc\n" if $opt{'t'};
   1283      1.1  mrg print TRY
   1284      1.1  mrg     "#include \"try.c\"\n" .
   1285      1.1  mrg     "\n";
   1286      1.1  mrg 
   1287      1.1  mrg my $extra_libraries = "";
   1288      1.1  mrg if (defined $ENV{extra_libraries}) { $extra_libraries = $ENV{extra_libraries};}
   1289      1.1  mrg 
   1290      1.1  mrg my $trydeps = "";
   1291      1.1  mrg if (defined $ENV{trydeps}) { $trydeps = $ENV{trydeps}; }
   1292      1.1  mrg $trydeps .= " $tryinc";
   1293      1.1  mrg print "trydeps $trydeps\n" if $opt{'t'};
   1294      1.1  mrg 
   1295      1.1  mrg print MAKEFILE <<EOF;
   1296      1.1  mrg 
   1297      1.1  mrg MANY_OBJS = $MANY_OBJS
   1298      1.1  mrg MANY_CLEAN = \$(MANY_OBJS) \\
   1299      1.1  mrg 	speed-many.c speed-many\$U.o speed-many\$(EXEEXT) \\
   1300      1.1  mrg 	try-many.c try-many\$U.o try-many \\
   1301      1.1  mrg 	$CLEAN
   1302      1.1  mrg MANY_DISTCLEAN = Makefile.many
   1303      1.1  mrg 
   1304      1.1  mrg speed-many: \$(MANY_OBJS) speed-many\$U.o libspeed.la $extra_libraries
   1305      1.1  mrg 	\$(LINK) \$(LDFLAGS) speed-many\$U.o \$(MANY_OBJS) \$(LDADD) \$(LIBS) $extra_libraries
   1306      1.1  mrg 
   1307      1.1  mrg try-many: \$(MANY_OBJS) try-many\$U.o libspeed.la $extra_libraries
   1308      1.1  mrg 	\$(LINK) \$(LDFLAGS) try-many\$U.o \$(MANY_OBJS)  \$(LDADD) \$(LIBS) $extra_libraries
   1309      1.1  mrg 
   1310      1.1  mrg try-many.o: try-many.c \$(top_srcdir)/tests/devel/try.c $trydeps
   1311      1.1  mrg 	\$(COMPILE) -I\$(top_srcdir)/tests/devel -c try-many.c
   1312      1.1  mrg 
   1313      1.1  mrg EOF
   1314      1.1  mrg 
   1315      1.1  mrg print_ansi2knr("speed-many");
   1316      1.1  mrg print_ansi2knr("try-many",
   1317      1.1  mrg 	       "\$(top_srcdir)/tests/devel/try.c",
   1318      1.1  mrg 	       "-I\$(top_srcdir)/tests/devel");
   1319      1.1  mrg 
   1320      1.1  mrg print MAKEFILE <<EOF;
   1321      1.1  mrg RM_TMP = rm -f
   1322      1.1  mrg CFLAGS_TESTS = -DSIZE=50 -DTIMES=1 -DRANDOM -DCLOCK=333000000
   1323      1.1  mrg CFLAGS_TESTS_SP = -DSIZE=1024 -DNOCHECK -DOPS=200000000 -DCLOCK=333000000
   1324      1.1  mrg EOF
   1325      1.1  mrg 
   1326      1.1  mrg close MAKEFILE or die;
   1327      1.1  mrg 
   1328      1.1  mrg print "Total $count_files files, $count_functions functions\n";
   1329      1.1  mrg 
   1330      1.1  mrg 
   1331      1.1  mrg 
   1332      1.1  mrg # Local variables:
   1333      1.1  mrg # perl-indent-level: 2
   1334      1.1  mrg # End:
   1335