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