3
# Copyright 2000, 2001 Free Software Foundation, Inc.
5
# This file is part of the GNU MP Library.
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.
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.
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,
23
# Usage: cd $builddir/tune
24
# perl $srcdir/tune/many.pl [-t] <files/dirs>...
26
# Output: speed-many.c
30
# Make alternate versions of various mpn routines available for measuring
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
38
# perl many.pl [-t] <files/dirs>...
43
# Suppose $HOME/newcode/mul_1_experiment.asm is a new implementation of
47
# perl $srcdir/tune/many.pl $HOME/newcode/mul_1_experiment.asm
49
# will produce rules and renaming so that a speed program incorporating it
52
# make -f Makefile.many speed-many
54
# then for example it can be compared to the standard mul_1,
56
# ./speed-many -s 1-30 mpn_mul_1 mpn_mul_1_experiment
58
# An expanded try program can be used to check correctness,
60
# make -f Makefile.many try-many
64
# ./try-many mpn_mul_1_experiment
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
73
# If a directory is given, then all files in it will be made available.
77
# perl $srcdir/tune/many.pl $HOME/newcode
79
# Each file should have a suffix, like "_experiment" above.
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
90
# perl $srcdir/tune/many.pl `find $srcdir/mpn/x86 -type d`
92
# On a new x86 chip a comparison could then be made to see how existing code
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
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.)
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,
114
# perl $srcdir/tune/many.pl $srcdir/mpn/generic
116
# or if just a few routines are of interest, then for example
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
124
# giving mpn_lshift_generic etc.
127
# TESTS/DEVEL PROGRAMS
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,
134
# make -f Makefile.many tests_mul_1_experimental
135
# ./tests_mul_1_experimental
139
# make -f Makefile.many tests_mul_1_experimental_sp
140
# ./tests_mul_1_experimental_sp
142
# Not all the programs support speed measuring, in which case only the
143
# correctness test will be useful.
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,
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
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
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.
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.
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.
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.
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.
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
194
# perl $srcdir/tune/many.pl -t $HOME/newcode/add_n_weird.asm
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.
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.
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.
218
# The nonsense involving $ENV is some hooks used during development to add
219
# additional functions temporarily.
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.
227
# Warn if a file provides no functions.
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.
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
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.
253
my @DIRECTORIES = @ARGV;
254
if (defined $ENV{directories}) { push @DIRECTORIES, @{$ENV{directories}} }
257
# regexp - matched against the start of the filename. If a grouping "(...)"
258
# is present then only the first such part is used.
260
# mulfunc - filenames to be generated from a multi-function file.
262
# funs - functions provided by the file, defaulting to the filename with mpn
265
# mpX - prefix like "mpz", defaulting to "mpn".
267
# ret - return value type.
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.
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.
277
# speed - SPEED_ROUTINE_ to use, handled like "try".
279
# speed_flags - SPEED_ROUTINE_ to use, handled like "try".
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',
292
'mulfunc'=> ['add_n','sub_n'],
293
'ret' => 'mp_limb_t',
294
'args' => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
295
'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
299
'regexp'=> 'addmul_1|submul_1',
300
'ret' => 'mp_limb_t',
301
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
302
'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
303
'speed_flags'=> 'FLAG_R',
306
'regexp'=> 'aorsmul_1',
307
'mulfunc'=> ['addmul_1','submul_1'],
308
'ret' => 'mp_limb_t',
309
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
310
'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
311
'speed_flags'=> 'FLAG_R',
315
'regexp'=> 'addsub_n',
316
'ret' => 'mp_limb_t',
317
'args' => 'mp_ptr sum, mp_ptr diff, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
318
'speed_flags'=> 'FLAG_R_OPTIONAL',
322
'regexp'=> 'bdivmod',
323
'ret' => 'mp_limb_t',
324
'args' => 'mp_ptr qp, mp_ptr up, mp_size_t usize, mp_srcptr vp, mp_size_t vsize, unsigned long int d',
331
'regexp'=> 'com_n|copyi|copyd',
333
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
334
'speed' => 'SPEED_ROUTINE_MPN_COPY',
339
'funs' => ['divexact_1'],
341
'args' => 'mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor',
342
'speed_flags'=> 'FLAG_R',
345
'regexp'=> 'diveby3',
346
'funs' => ['divexact_by3c'],
347
'ret' => 'mp_limb_t',
348
'args' => 'mp_ptr dst, mp_srcptr src, mp_size_t size',
350
'speed' => 'SPEED_ROUTINE_MPN_COPY',
354
'regexp'=> 'divrem_1',
355
'ret' => 'mp_limb_t',
356
'args' => 'mp_ptr rp, mp_size_t xsize, mp_srcptr sp, mp_size_t size, mp_limb_t divisor',
357
'speed_flags' => 'FLAG_R',
358
'speed_suffixes' => ['f'],
361
'regexp'=> 'divrem_2',
362
'ret' => 'mp_limb_t',
363
'args' => 'mp_ptr qp, mp_size_t qxn, mp_srcptr np, mp_size_t nsize, mp_srcptr dp',
368
'regexp'=> 'sb_divrem_mn',
369
'ret' => 'mp_limb_t',
370
'args' => 'mp_ptr qp, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
371
'speed' => 'SPEED_ROUTINE_MPN_DC_DIVREM_SB',
375
'regexp'=> 'tdiv_qr',
377
'args' => 'mp_ptr qp, mp_size_t qxn, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize',
382
'regexp'=> 'get_str',
384
'args' => 'unsigned char *str, int base, mp_ptr mptr, mp_size_t msize',
385
'speed_flags' => 'FLAG_R_OPTIONAL',
389
'regexp'=> 'set_str',
390
'ret' => 'mp_size_t',
391
'args' => 'mp_ptr xp, const unsigned char *str, size_t str_len, int base',
392
'speed_flags' => 'FLAG_R_OPTIONAL',
400
'args' => 'mpz_ptr r, unsigned long n',
401
'speed_flags' => 'FLAG_NODATA',
406
'regexp'=> 'fib2_ui',
408
'args' => 'mp_ptr fp, mp_ptr f1p, unsigned long n',
409
'rename'=> ['__gmp_fib_table'],
410
'speed_flags' => 'FLAG_NODATA',
417
'args' => 'mpz_ptr fn, unsigned long n',
418
'speed_flags' => 'FLAG_NODATA',
422
'regexp'=> 'fib2_ui',
425
'args' => 'mpz_ptr fn, mpz_ptr fnsub1, unsigned long n',
426
'speed_flags' => 'FLAG_NODATA',
431
'regexp'=> 'lucnum_ui',
434
'args' => 'mpz_ptr ln, unsigned long n',
435
'speed_flags' => 'FLAG_NODATA',
439
'regexp'=> 'lucnum2_ui',
442
'args' => 'mpz_ptr ln, mpz_ptr lnsub1, unsigned long n',
443
'speed_flags' => 'FLAG_NODATA',
449
'ret' => 'mp_limb_t',
450
'args' => 'mp_ptr xp, mp_size_t xsize, mp_limb_t y',
451
'attrib'=> '__GMP_ATTRIBUTE_PURE',
452
'speed_flags'=> 'FLAG_R_OPTIONAL',
453
'speed_suffixes' => ['N'],
456
'regexp'=> '(gcd)(?!(_1|ext|_finda))',
457
'ret' => 'mp_size_t',
458
'args' => 'mp_ptr gp, mp_ptr up, mp_size_t usize, mp_ptr vp, mp_size_t vsize',
461
'regexp'=> 'gcd_finda',
462
'ret' => 'mp_limb_t',
463
'args' => 'mp_srcptr cp',
464
'attrib'=> '__GMP_ATTRIBUTE_PURE',
470
'funs' => ['jacobi', 'legendre', 'kronecker'],
473
'args' => 'mpz_srcptr a, mpz_srcptr b',
474
'attrib'=> '__GMP_ATTRIBUTE_PURE',
475
'try-legendre' => 'TYPE_MPZ_JACOBI',
478
'regexp'=> 'jacbase',
479
'funs' => ['jacobi_base'],
480
'ret' => 'mp_limb_t',
481
'args' => 'mp_limb_t a, mp_limb_t b, int bit1',
482
'attrib'=> 'ATTRIBUTE_CONST',
483
'speed' => 'SPEED_ROUTINE_MPN_JACBASE',
488
'regexp'=> 'logops_n',
489
'mulfunc'=> ['and_n','andn_n','nand_n','ior_n','iorn_n','nior_n','xor_n','xnor_n'],
491
'args' => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
492
'speed' => 'SPEED_ROUTINE_MPN_BINARY_N',
496
'regexp'=> '[lr]shift',
497
'ret' => 'mp_limb_t',
498
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, unsigned shift',
499
'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
500
'speed_flags'=> 'FLAG_R',
503
# mpn_preinv_mod_1 is an optional extra entrypoint
505
'regexp'=> '(mod_1)(?!_rs)',
506
'funs' => ['mod_1','preinv_mod_1'],
507
'ret' => 'mp_limb_t',
508
'args_mod_1' => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor',
509
'args_preinv_mod_1'=> 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
510
'attrib'=> '__GMP_ATTRIBUTE_PURE',
511
'speed_flags'=> 'FLAG_R',
514
'regexp'=> 'pre_mod_1',
515
'funs' => ['preinv_mod_1'],
516
'ret' => 'mp_limb_t',
517
'args' => 'mp_srcptr xp, mp_size_t size, mp_limb_t divisor, mp_limb_t inverse',
518
'attrib'=> '__GMP_ATTRIBUTE_PURE',
519
'speed_flags'=> 'FLAG_R',
522
'regexp'=> 'mod_34lsub1',
523
'ret' => 'mp_limb_t',
524
'args' => 'mp_srcptr src, mp_size_t len',
525
'attrib'=> '__GMP_ATTRIBUTE_PURE',
528
'regexp'=> 'invert_limb',
529
'ret' => 'mp_limb_t',
530
'args' => 'mp_limb_t divisor',
531
'attrib'=> 'ATTRIBUTE_CONST',
532
'speed_flags'=> 'FLAG_R_OPTIONAL',
538
'funs' => ['modexact_1_odd'],
539
'ret' => 'mp_limb_t',
540
'args' => 'mp_srcptr src, mp_size_t size, mp_limb_t divisor',
541
'attrib'=> '__GMP_ATTRIBUTE_PURE',
542
'speed_flags'=> 'FLAG_R',
545
'regexp'=> 'modlinv',
546
'funs' => ['modlimb_invert'],
547
'ret' => 'mp_limb_t',
548
'args' => 'mp_limb_t v',
549
'attrib'=> 'ATTRIBUTE_CONST',
556
'ret' => 'mp_limb_t',
557
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t mult',
558
'speed' => 'SPEED_ROUTINE_MPN_UNARY_1',
559
'speed_flags'=> 'FLAG_R',
563
'ret' => 'mp_limb_t',
564
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size, mp_limb_t low, mp_limb_t high',
565
'speed' => 'SPEED_ROUTINE_MPN_UNARY_2',
569
'regexp'=> 'mul_basecase',
571
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t xsize, mp_srcptr yp, mp_size_t ysize',
572
'speed_flags' => 'FLAG_R_OPTIONAL | FLAG_RSIZE',
575
'regexp'=> '(mul_n)[_.]',
577
'args' => 'mp_ptr wp, mp_srcptr xp, mp_srcptr yp, mp_size_t size',
578
'rename'=> ['kara_mul_n','kara_sqr_n','toom3_mul_n','toom3_sqr_n'],
581
# not for use with hppa reversed argument versions of mpn_umul_ppmm
583
'funs' => ['umul_ppmm'],
584
'ret' => 'mp_limb_t',
585
'args' => 'mp_limb_t *lowptr, mp_limb_t m1, mp_limb_t m2',
593
'mulfunc'=> ['popcount','hamdist'],
594
'ret' => 'unsigned long',
595
'args_popcount'=> 'mp_srcptr xp, mp_size_t size',
596
'args_hamdist' => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
597
'attrib'=> '__GMP_ATTRIBUTE_PURE',
600
'regexp'=> 'popcount',
601
'ret' => 'unsigned long',
602
'args' => 'mp_srcptr xp, mp_size_t size',
603
'attrib'=> '__GMP_ATTRIBUTE_PURE',
606
'regexp'=> 'hamdist',
607
'ret' => 'unsigned long',
608
'args' => 'mp_srcptr xp, mp_srcptr yp, mp_size_t size',
609
'attrib'=> '__GMP_ATTRIBUTE_PURE',
610
# extra renaming to support sharing a data table with mpn_popcount
611
'rename'=> ['popcount'],
615
'regexp'=> 'sqr_basecase',
617
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
618
'speed' => 'SPEED_ROUTINE_MPN_SQR',
622
'regexp'=> 'sqr_diagonal',
624
'args' => 'mp_ptr wp, mp_srcptr xp, mp_size_t size',
629
'regexp'=> 'sqrtrem',
630
'ret' => 'mp_size_t',
631
'args' => 'mp_ptr root, mp_ptr rem, mp_srcptr src, mp_size_t size',
637
'funs' => ['count_leading_zeros'],
639
'args' => 'mp_limb_t',
640
'attrib'=> 'ATTRIBUTE_CONST',
641
'macro-before' => "#undef COUNT_LEADING_ZEROS_0",
643
'#ifdef COUNT_LEADING_ZEROS_0
644
#define COUNT_LEADING_ZEROS_0_ALLOWED 1
646
#define COUNT_LEADING_ZEROS_0_ALLOWED 0
648
SPEED_ROUTINE_COUNT_LEADING_ZEROS_C ($fun (c, n),
649
COUNT_LEADING_ZEROS_0_ALLOWED)',
650
'speed_flags'=> 'FLAG_R_OPTIONAL',
655
'funs' => ['count_trailing_zeros'],
657
'args' => 'mp_limb_t',
658
'attrib'=> 'ATTRIBUTE_CONST',
659
'macro-speed' => 'SPEED_ROUTINE_COUNT_TRAILING_ZEROS_C ($fun(c,n), 0)',
660
'speed_flags' => 'FLAG_R_OPTIONAL',
667
'args' => 'mp_ptr ptr, mp_size_t size',
671
'regexp'=> '(powm)(?!_ui)',
674
'args' => 'mpz_ptr r, mpz_srcptr b, mpz_srcptr e, mpz_srcptr m',
678
'regexp'=> 'powm_ui',
681
'args' => 'mpz_ptr r, mpz_srcptr b, unsigned long e, mpz_srcptr m',
685
# special for use during development
688
'funs' => ['back_to'],
694
'speed_flags'=> 'FLAG_NODATA',
698
if (defined $ENV{table2}) {
699
my @newtable = @{$ENV{table2}};
700
push @newtable, @table;
709
'asmflags'=> '$(ASMFLAGS_PIC)',
710
'cflags' => '$(CFLAGS_PIC)',
720
my $builddir = $ENV{builddir};
721
$builddir = "." if (! defined $builddir);
723
my $top_builddir = "${builddir}/..";
726
open(MAKEFILE, "<${builddir}/Makefile")
727
or die "Cannot open Makefile: $!\nIs this a tune build directory?";
728
my ($srcdir, $top_srcdir);
730
if (/^srcdir = (.*)/) { $srcdir = $1; }
731
if (/^top_srcdir = (.*)/) { $top_srcdir = $1; }
733
die "Cannot find \$srcdir in Makefile\n" if (! defined $srcdir);
734
die "Cannot find \$top_srcdir in Makefile\n" if (! defined $top_srcdir);
735
print "srcdir $srcdir\n" if $opt{'t'};
736
print "top_srcdir $top_srcdir\n" if $opt{'t'};
740
open(SPEED, ">speed-many.c") or die;
742
"/* speed-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
745
my $SPEED_EXTRA_ROUTINES = "#define SPEED_EXTRA_ROUTINES \\\n";
746
my $SPEED_EXTRA_PROTOS = "#define SPEED_EXTRA_PROTOS \\\n";
749
open(TRY, ">try-many.c") or die;
751
"/* try-many.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */\n" .
753
my $TRY_EXTRA_ROUTINES = "#define EXTRA_ROUTINES \\\n";
754
my $TRY_EXTRA_PROTOS = "#define EXTRA_PROTOS \\\n";
756
open(FD,"<${top_builddir}/libtool") or die "Cannot open \"${top_builddir}/libtool\": $!\n";
759
if (/^pic_flag="?([^"]*)"?$/) {
765
if (! defined $pic_flag) {
766
die "Cannot find pic_flag in ${top_builddir}/libtool";
769
my $CFLAGS_PIC = $pic_flag;
771
my $ASMFLAGS_PIC = "";
772
foreach (split /[ \t]/, $pic_flag) {
774
$ASMFLAGS_PIC .= " " . $_;
778
open(MAKEFILE, ">Makefile.many") or die;
780
"# Makefile.many generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST\n" .
782
"all: speed-many try-many\n" .
784
"#--------- begin included copy of basic Makefile ----------\n" .
786
open(FD,"<${builddir}/Makefile") or die "Cannot open \"${builddir}/Makefile\": $!\n";
791
"#--------- end included copy of basic Makefile ----------\n" .
793
"CFLAGS_PIC = $CFLAGS_PIC\n" .
794
"ASMFLAGS_PIC = $ASMFLAGS_PIC\n" .
802
my ($base,$file,$includes) = @_;
803
if (! defined $file) { $file = "$base.c"; }
804
if (! defined $includes) { $includes = ""; }
806
print MAKEFILE <<EOF;
807
${base}_.c: $file \$(ANSI2KNR)
808
\$(CPP) \$(DEFS) \$(INCLUDES) $includes \$(AM_CPPFLAGS) \$(CPPFLAGS) $file | sed 's/^# \([0-9]\)/#line \\1/' | \$(ANSI2KNR) >${base}_.c
814
# Spawning a glob is a touch slow when there's lots of files.
816
foreach my $dir (@DIRECTORIES) {
817
print "dir $dir\n" if $opt{'t'};
821
if (! opendir DD,$dir) {
822
print "Cannot open $dir: $!\n";
824
push @files, map {$_="$dir/$_"} grep /\.(c|asm|S|h)$/, readdir DD;
829
@files = sort @files;
830
print "@files ",join(" ",@files),"\n" if $opt{'t'};
833
my $count_functions = 0;
837
foreach my $file_full (@files) {
838
if (! -f $file_full) {
839
print "Not a file: $file_full\n";
842
if (defined $seen_file{$file_full}) {
843
print "Skipping duplicate file: $file_full\n";
846
$seen_file{$file_full} = 1;
848
my ($FILE,$path,$lang) = fileparse($file_full,"\.[a-zA-Z]+");
850
print "file $FILE path $path lang $lang\n" if $opt{'t'};
853
if ($lang eq '.asm') { @pic_choices=('no','yes'); }
854
elsif ($lang eq '.c') { @pic_choices=('no'); }
855
elsif ($lang eq '.S') { @pic_choices=('no','yes'); }
856
elsif ($lang eq '.h') { @pic_choices=('no'); }
859
my ($t, $file_match);
860
foreach my $p (@table) {
861
# print " ",$p->{'regexp'},"\n" if $opt{'t'};
862
if ($FILE =~ "^($p->{'regexp'})") {
865
$file_match = $2 if defined $2;
869
next if ! defined $t;
870
print "match $t->{'regexp'} $FILE ($file_full)\n" if $opt{'t'};
872
if (! open FD,"<$file_full") { print "Can't open $file_full: $!\n"; next }
873
my @file_contents = <FD>;
877
if (defined $t->{'mulfunc'}) { $objs = $t->{'mulfunc'}; }
878
else { $objs = [$file_match]; }
879
print "objs @$objs\n" if $opt{'t'};
881
my $ret = $t->{'ret'};
882
if (! defined $ret && $lang eq '.h') { $ret = ''; }
883
if (! defined $ret) { die "$FILE return type not defined\n" };
884
print "ret $ret\n" if $opt{'t'};
886
my $mpX = $t->{'mpX'};
887
if (! defined $mpX) { $mpX = ($lang eq '.h' ? '' : 'mpn'); }
888
$mpX = "${mpX}_" if $mpX ne '';
889
print "mpX $mpX\n" if $opt{'t'};
892
if (defined $t->{'carrys'}) { $carrys = $t->{'carrys'}; }
893
else { $carrys = ['','c']; }
894
print "carrys $carrys @$carrys\n" if $opt{'t'};
896
# some restriction functions are implemented, but they're not very useful
900
if ($FILE =~ ("${file_match}_(.+)")) {
902
} elsif ($path =~ /\/mp[zn]\/(.*)$/) {
903
# derive the suffix from the path
906
# use last directory name, or if there's 3 or more then the last two
907
if ($suffix =~ /([^_]*_)+([^_]+_[^_]+)$/) {
909
} elsif ($suffix =~ /([^_]*_)*([^_]+)$/) {
912
} elsif (defined $t->{'suffix'}) {
913
$suffix = $t->{'suffix'};
915
die "Can't determine suffix for: $file_full (path $path)\n";
917
print "suffix $suffix\n" if $opt{'t'};
921
foreach my $obj (@{$objs}) {
922
print "obj $obj\n" if $opt{'t'};
924
my $obj_with_suffix = "${obj}_$suffix";
925
if (defined $seen_obj{$obj_with_suffix}) {
926
print "Skipping duplicate object: $obj_with_suffix\n";
927
print " first from: $seen_obj{$obj_with_suffix}\n";
928
print " now from: $file_full\n";
931
$seen_obj{$obj_with_suffix} = $file_full;
933
my $funs = $t->{'funs'};
934
$funs = [$obj] if ! defined $funs;
935
print "funs @$funs\n" if $opt{'t'};
937
if (defined $t->{'pic'}) { @pic_choices = ('no'); }
939
foreach my $pic (map {$pictable{$_}} @pic_choices) {
940
print "pic $pic->{'suffix'}\n" if $opt{'t'};
942
my $objbase = "${obj}_$suffix$pic->{'suffix'}";
943
print "objbase $objbase\n" if $opt{'t'};
945
if ($path !~ "." && -f "${objbase}.c") {
946
die "Already have ${objbase}.c";
949
my $tmp_file = "tmp-$objbase.c";
952
foreach my $fun (@{$funs}) {
953
my $fun_carry = $fun;
954
if (! ($fun_carry =~ s/_1/_1c/)) { $fun_carry = "${fun}c"; }
956
"\t\t-D__g$mpX$fun=$mpX${fun}_$suffix$pic->{'suffix'} \\\n" .
957
"\t\t-D__g$mpX$fun_carry=$mpX${fun_carry}_$suffix$pic->{'suffix'} \\\n";
959
foreach my $r (@{$t->{'rename'}}) {
960
if ($r =~ /^__gmp/) {
961
$renaming .= "\\\n" .
962
"\t\t-D$r=${r}_$suffix$pic->{'suffix'}";
964
$renaming .= "\\\n" .
965
"\t\t-D__g$mpX$r=$mpX${r}_$suffix$pic->{'suffix'}";
968
print "renaming $renaming\n" if $opt{'t'};
971
if ($lang eq '.asm') {
973
"$objbase.o: $file_full \$(ASM_HEADERS)\n" .
974
" \$(M4) \$(M4FLAGS) -DOPERATION_$obj $pic->{'asmflags'} \\\n" .
976
" $file_full >tmp-$objbase.s\n" .
977
" \$(CCAS) \$(COMPILE_FLAGS) $pic->{'cflags'} tmp-$objbase.s -o $objbase.o\n" .
978
" \$(RM_TMP) tmp-$objbase.s\n";
979
$MANY_OBJS .= " $objbase.o";
981
} elsif ($lang eq '.c') {
983
"$objbase.o: $file_full\n" .
984
" \$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
986
" -c $file_full -o $objbase.o\n";
987
print_ansi2knr($objbase,
989
" -DOPERATION_$obj\\\n$renaming\t\t");
990
$MANY_OBJS .= " $objbase\$U.o";
992
} elsif ($lang eq '.S') {
994
"$objbase.o: $file_full\n" .
995
" \$(COMPILE) -g $pic->{'asmflags'} \\\n" .
997
" -c $file_full -o $objbase.o\n";
998
$MANY_OBJS .= " $objbase.o";
1000
} elsif ($lang eq '.h') {
1002
"$objbase.o: tmp-$objbase.c $file_full\n" .
1003
" \$(COMPILE) -DOPERATION_$obj $pic->{'cflags'} \\\n" .
1005
" -c tmp-$objbase.c -o $objbase.o\n";
1006
print_ansi2knr($objbase,
1008
" -DOPERATION_$obj\\\n$renaming\t\t");
1009
$MANY_OBJS .= " $objbase\$U.o";
1011
$CLEAN .= " tmp-$objbase.c";
1012
open(TMP_C,">tmp-$objbase.c")
1013
or die "Can't create tmp-$objbase.c: $!\n";
1015
"/* tmp-$objbase.c generated by many.pl - DO NOT EDIT, CHANGES WILL BE LOST */
1018
#include \"gmp-impl.h\"
1019
#include \"longlong.h\"
1020
#include \"speed.h\"
1025
my $tests_program = "$top_srcdir/tests/devel/$obj.c";
1026
if (-f $tests_program) {
1027
$tests_program = "\$(top_srcdir)/tests/devel/$obj.c";
1028
print_ansi2knr("tests_${objbase}",
1030
"\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
1031
print_ansi2knr("tests_${objbase}_sp",
1033
"\\\n$renaming\t\t\$(CFLAGS_TESTS_SP)");
1035
print MAKEFILE <<EOF;
1036
tests_$objbase.o: $tests_program
1037
\$(COMPILE) \$(CFLAGS_TESTS) \\
1038
$renaming -c $tests_program -o tests_$objbase.o
1040
tests_$objbase: $objbase\$U.o tests_$objbase\$U.o ../libgmp.la
1041
\$(LINK) tests_$objbase\$U.o $objbase\$U.o ../libgmp.la -o tests_$objbase
1043
tests_${objbase}_sp.o: $tests_program
1044
\$(COMPILE) \$(CFLAGS_TESTS_SP) \\
1045
$renaming -c $tests_program -o tests_${objbase}_sp.o
1047
tests_${objbase}_sp: $objbase\$U.o tests_${objbase}_sp\$U.o ../libgmp.la
1048
\$(LINK) tests_${objbase}_sp\$U.o $objbase\$U.o ../libgmp.la -o tests_${objbase}_sp
1051
$CLEAN .= " tests_$objbase tests_${objbase}_sp";
1054
foreach my $fun (@{$funs}) {
1055
print "fun $fun\n" if $opt{'t'};
1057
if ($lang eq '.h') {
1058
my $macro_before = $t->{'macro_before'};
1059
$macro_before = "" if ! defined $macro_before;
1063
#include \"$file_full\"
1068
my $args = $t->{"args_$fun"};
1069
if (! defined $args) { $args = $t->{'args'}; }
1070
if (! defined $args) { die "Need args for $fun\n"; }
1071
print "args $args\n" if $opt{'t'};
1073
foreach my $carry (@$carrys) {
1074
print "carry $carry\n" if $opt{'t'};
1076
my $fun_carry = $fun;
1077
if (! ($fun_carry =~ s/_1/_1$carry/)) { $fun_carry = "$fun$carry"; }
1078
print "fun_carry $fun_carry\n" if $opt{'t'};
1080
if ($lang =~ /\.(asm|S)/
1081
&& ! grep(m"PROLOGUE.*$mpX$fun_carry",@file_contents)) {
1082
print "no PROLOGUE $mpX$fun_carry\n" if $opt{'t'};
1086
&& ! grep(m"^(#define FUNCTION\s+)?$mpX$fun_carry\W", @file_contents)) {
1087
print "no mention of $mpX$fun_carry\n" if $opt{'t'};
1091
&& ! grep(m"^#define $fun_carry\W", @file_contents)) {
1092
print "no mention of #define $fun_carry\n" if $opt{'t'};
1099
if (defined $t->{'carryarg'}) { $carryarg = $t->{'carryarg'}; }
1100
if ($carry eq '') { $carryarg = ''; }
1101
else { $carryarg = ', mp_limb_t carry'; }
1102
print "carryarg $carryarg\n" if $opt{'t'};
1104
my $funfull="$mpX${fun_carry}_$suffix$pic->{'suffix'}";
1105
print "funfull $funfull\n" if $opt{'t'};
1107
if ($lang ne '.h') {
1108
my $attrib = $t->{'attrib'};
1109
if (defined $attrib) { $attrib = " $attrib"; }
1110
else { $attrib = ''; }
1112
my $proto = "$t->{'ret'} $funfull _PROTO (($args$carryarg))$attrib; \\\n";
1113
$SPEED_EXTRA_PROTOS .= $proto;
1114
$TRY_EXTRA_PROTOS .= $proto;
1117
my $try_type = $t->{"try-$fun"};
1118
$try_type = $t->{'try'} if ! defined $try_type;
1119
if (! defined $try_type) {
1120
if ($mpX eq 'mpn_') {
1121
$try_type = "TYPE_\U$fun_carry";
1123
$try_type = "TYPE_\U$mpX\U$fun_carry";
1126
print "try_type $try_type\n" if $opt{'t'};
1128
my $try_minsize = $t->{'try-minsize'};
1129
if (defined $try_minsize) {
1130
$try_minsize = ", " . $try_minsize;
1134
print "try_minsize $try_minsize\n" if $opt{'t'};
1136
if ($try_type ne 'none') {
1137
$TRY_EXTRA_ROUTINES .=
1138
" { TRY($mpX${fun_carry}_$suffix$pic->{'suffix'}), $try_type$try_minsize }, \\\n";
1141
my $speed_flags = $t->{'speed_flags'};
1142
$speed_flags = '0' if ! defined $speed_flags;
1143
print "speed_flags $speed_flags\n" if $opt{'t'};
1145
my $speed_routine = $t->{'speed'};
1146
$speed_routine = "SPEED_ROUTINE_\U$mpX\U$fun"
1147
if !defined $speed_routine;
1148
if (! ($speed_routine =~ s/_1/_1\U$carry/)) {
1149
$speed_routine = "$speed_routine\U$carry";
1151
print "speed_routine $speed_routine\n" if $opt{'t'};
1153
my @speed_suffixes = ();
1154
push (@speed_suffixes, '') if $speed_routine ne 'none';
1155
push (@speed_suffixes, @{$t->{'speed_suffixes'}})
1156
if defined $t->{'speed_suffixes'};
1158
my $macro_speed = $t->{'macro-speed'};
1159
$macro_speed = "$speed_routine ($fun_carry)" if ! defined $macro_speed;
1160
$macro_speed =~ s/\$fun/$fun_carry/g;
1162
foreach my $S (@speed_suffixes) {
1163
my $Sfunfull="$mpX${fun_carry}${S}_$suffix$pic->{'suffix'}";
1165
$SPEED_EXTRA_PROTOS .=
1166
"double speed_$Sfunfull _PROTO ((struct speed_params *s)); \\\n";
1167
$SPEED_EXTRA_ROUTINES .=
1168
" { \"$Sfunfull\", speed_$Sfunfull, $speed_flags }, \\\n";
1169
if ($lang eq '.h') {
1172
speed_$Sfunfull (struct speed_params *s)
1181
"speed_$Sfunfull (struct speed_params *s)\n" .
1184
" $speed_routine\U$S\E ($funfull)\n" .
1195
print SPEED $SPEED_EXTRA_PROTOS . "\n";
1196
print SPEED $SPEED_EXTRA_ROUTINES . "\n";
1197
if (defined $ENV{speedinc}) { print SPEED $ENV{speedinc} . "\n"; }
1199
"#include \"speed.c\"\n" .
1201
print SPEED $SPEED_CODE;
1203
print TRY $TRY_EXTRA_ROUTINES . "\n";
1204
print TRY $TRY_EXTRA_PROTOS . "\n";
1206
if (defined $ENV{tryinc}) {
1207
$tryinc = $ENV{tryinc};
1208
print TRY "#include \"$tryinc\"\n";
1210
print "tryinc $tryinc\n" if $opt{'t'};
1212
"#include \"try.c\"\n" .
1215
my $extra_libraries = "";
1216
if (defined $ENV{extra_libraries}) { $extra_libraries = $ENV{extra_libraries};}
1219
if (defined $ENV{trydeps}) { $trydeps = $ENV{trydeps}; }
1220
$trydeps .= " $tryinc";
1221
print "trydeps $trydeps\n" if $opt{'t'};
1223
print MAKEFILE <<EOF;
1225
MANY_OBJS = $MANY_OBJS
1226
MANY_CLEAN = \$(MANY_OBJS) \\
1227
speed-many.c speed-many\$U.o speed-many\$(EXEEXT) \\
1228
try-many.c try-many\$U.o try-many \\
1230
MANY_DISTCLEAN = Makefile.many
1232
speed-many: \$(MANY_OBJS) speed-many\$U.o libspeed.la $extra_libraries
1233
\$(LINK) \$(LDFLAGS) speed-many\$U.o \$(MANY_OBJS) \$(LDADD) \$(LIBS) $extra_libraries
1235
try-many: \$(MANY_OBJS) try-many\$U.o libspeed.la $extra_libraries
1236
\$(LINK) \$(LDFLAGS) try-many\$U.o \$(MANY_OBJS) \$(LDADD) \$(LIBS) $extra_libraries
1238
try-many.o: try-many.c \$(top_srcdir)/tests/devel/try.c $trydeps
1239
\$(COMPILE) -I\$(top_srcdir)/tests/devel -c try-many.c
1243
print_ansi2knr("speed-many");
1244
print_ansi2knr("try-many",
1245
"\$(top_srcdir)/tests/devel/try.c",
1246
"-I\$(top_srcdir)/tests/devel");
1248
print MAKEFILE <<EOF;
1250
CFLAGS_TESTS = -DSIZE=50 -DTIMES=1 -DRANDOM -DCLOCK=333000000
1251
CFLAGS_TESTS_SP = -DSIZE=1024 -DNOCHECK -DOPS=200000000 -DCLOCK=333000000
1255
print "Total $count_files files, $count_functions functions\n";
1260
# perl-indent-level: 2