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