[BACK]Return to many.pl CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / tune

Annotation of OpenXM_contrib/gmp/tune/many.pl, Revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>