[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     ! 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>