diff options
author | David Shaw <dshaw@jabberwocky.com> | 2002-06-29 16:15:02 +0200 |
---|---|---|
committer | David Shaw <dshaw@jabberwocky.com> | 2002-06-29 16:15:02 +0200 |
commit | 0ed622829316ebad4e8d40642bec699209a7ff2d (patch) | |
tree | 36d5b54103c961d662fd65c5fdeab3354453878f | |
parent | * gpgsm.c: New option --auto-issuer-key-retrieve. (diff) | |
download | gnupg2-0ed622829316ebad4e8d40642bec699209a7ff2d.tar.xz gnupg2-0ed622829316ebad4e8d40642bec699209a7ff2d.zip |
Update head to match stable 1.0
144 files changed, 18924 insertions, 667 deletions
@@ -1,93 +1,99 @@ -Authors of GNU Privacy Guard (GnuPG) -==================================== +Program: GnuPG +Maintainer: Werner Koch <wk@gnupg.org> -GNUPG Werner Koch 1998-02-23 -Assigns GNU Privacy Guard and future changes. -werner.koch@guug.de -Designed and implemented GnuPG. +Authors +======= +Birger Langkjer <birger.langkjer@image.dk> Translations [da] -GNUPG Matthew Skala 1998-08-10 -Disclaims changes. -mskala@ansuz.sooke.bc.ca -Wrote cipher/twofish.c. +Daniel Resare <daniel@resare.com> Translations [sv] -GNUPG Natural Resources Canada 1998-08-11 -Disclaims changes by Matthew Skala. +David Shaw <dshaw@jabberwocky.com> Assignment + (all in keyserver/, + a lot of changes in g10/ see the ChangeLog, + bug fixes here and there) +Dokianakis Theofanis <madf@hellug.gr> Translations [el] -GNUPG Michael Roth Germany 1998-09-17 -Assigns changes. -mroth@nessie.de -Wrote cipher/des.c. -Changes and bug fixes all over the place. +Edmund GRIMLEY EVANS <edmundo@rano.org> Translations [eo] +Gaël Quéri <gael@lautre.net> Translations [fr] + (fixed a lot of typos) -GNUPG Niklas Hernaeus 1998-09-18 -Disclaims changes. -nh@df.lth.se -Weak key patches. +Gregory Steuck <steuck@iname.com> Translations [ru] +Ivo Timmermans <itimmermans@bigfoot.com> Translations [nl] -GNUPG Rémi Guyomarch 1999-05-25 -Assigns past and future changes. (g10/compress.c, g10/encr-data.c, -g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c) -rguyom@mail.dotcom.fr +Jacobo Tarri'o Barreiro <jtarrio@iname.com> Translations [gl] +Janusz Aleksander Urbanowicz <alex@bofh.torun.pl> Translations [po] -TRANSLATIONS Marco d'Itri 1997-02-22 -Disclaimer. [it] -md@linux.it +Magda Procha'zkova' <magda@math.muni.cz> Translations [cs] +Michael Roth <mroth@nessie.de> Assignment + (wrote cipher/des.c., changes and bug fixes all over the place) -TRANSLATIONS Gael Queri 1998-09-08 -Disclaimer. [fr] -gqueri@mail.dotcom.fr -Fixed a lot of typos. +Marco d'Itri <md@linux.it> Translations [it] +Matthew Skala <mskala@ansuz.sooke.bc.ca> Disclaimer + (wrote cipher/twofish.c) -TRANSLATIONS Walter Koch 1998-09-08 -Disclaimer. [de] -koch@hsp.de +Niklas Hernaeus <nh@df.lth.se> Disclaimer + (weak key patches) +Nilgun Belma Buguner <nilgun@technologist.com> Translations [tr] -TRANSLATIONS Gregory Steuck 1998-10-20 -Disclaimer. [ru] -steuck@iname.com +Nils Ellmenreich <nils 'at' infosun.fmi.uni-passau.de> Assignment + (configure.in, cipher/rndlinux.c, FAQ) +Paul Eggert <eggert@twinsun.com> + (configuration macros for LFS) -TRANSLATIONS Urko Lusa -Disclaimer. [es_ES] -ulusa@euskalnet.net +Pedro Morais <morais@poli.org> Translations [pt_PT] +Rémi Guyomarch <rguyom@mail.dotcom.fr> Assignment + (g10/compress.c, g10/encr-data.c, + g10/free-packet.c, g10/mdfilter.c, g10/plaintext.c, util/iobuf.c) -TRANSLATIONS Thiago Jung Bauermann -Disclaimer. [pt_BR] -jungmann@cwb.matrix.com.br +Stefan Bellon <sbellon@sbellon.de> Assignment + (All patches to support RISC OS) +Timo Schulz <twoaday@freakmail.de> Assignment + (util/w32reg.c, g10/passphrase.c, g10/hkp.c) -TRANSLATIONS Pedro Morais -Disclaimer. [pt_PT] -morais@poli.org +Tedi Heriyanto <tedi_h@gmx.net> Translations [id] +Thiago Jung Bauermann <jungmann@cwb.matrix.com.br> Translations [pt_BR] +Rafael Caetano dos Santos <rcaetano@linux.ime.usp.br> Translations [pt_BR] -TRANSLATIONS Janusz Aleksander Urbanowicz 1999-01-09 -Disclaimer. [po] -alex@bofh.torun.pl +Toomas Soome <tsoome@ut.ee> Translations [et] +Urko Lusa <ulusa@euskalnet.net> Translations [es_ES] +Walter Koch <koch@u32.de> Translations [de] + +Werner Koch <wk@gnupg.org> Assignment + (started the whole thing) + +Yosiaki IIDA <iida@ring.gr.jp> Translations [ja] + + + +Other legal information +======================= -More credits -============ This program uses the zlib compression library written by Jean-loup Gailly and Mark Adler. Most of the stuff in mpi has been taken from the GMP library by Torbjorn Granlund <tege@noisy.tmg.se>. -The keybox implementation is based on GDBM 1.7.3 by Philip A. Nelson. +The Rijndael implementation (cipher/rijndael.c) is based on the +public domain reference code provided for the AES selection process. +The Rijndael algorithm is due to Joan Daemen and Vincent Rijmen. -The file cipher/rndunix.c is based on rndunix.c from cryptlib. +The files cipher/rndunix.c and cipher/rndw32.c are based on rndunix.c +and rndwin32.c from cryptlib. Copyright Peter Gutmann, Paul Kendall, and Chris Wedgwood 1996-1999. The files in debian/ are by James Troup who is the Debian maintainer @@ -96,3 +102,13 @@ for GnuPG. The RPM specs file scripts/gnupg.spec has been contributed by several people. + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + @@ -1,63 +1,8 @@ - List of some known bugs - ------------------------- +Please see -This following list contains those bugs which we are aware of. Please -make sure that bugs you report are not listed here. If you can fix one -of these bugs/limitations we will certainly be glad to receive a patch. -(Please note that we need a disclaimer if a patch is longer than about -10 lines; but it may help anyway to show us where we have to fix it. Do -an "info standards" to find out why a disclaimer is needed for GNU.) + http://www.gnupg.org/buglist.html -Format: severity: [ *] to [***], no, first reported, by, version. -Bugs which are marked with "FIX: yyyy-mm-dd" are fixed in the CVS -and after about half a day in the rsync snapshots. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +for a list of know bugs in GnuPG. We don't distribute this list anymore +with the package because a more current one with notes in which version +the bug is fixed can be found online. -[ *] #3 - --list-packets should continue even w/o a passphrase (or in batch - mode). Maybe we have to move it to a separate program?? - -[ *] #4 1999-01-13 <ralf.stephan@fitug.de> 0.9.1 - v3 key 'expiration date' problem: - 1. generate a key, set expiration date - 2. <do other things, deleting etc.> - 3. edit a v3 secret key, try to set expiration date - - output: "You can't change... - 4. save - 5. key has expiration date from 1. and gpg reports that pubkey - and seckey differ. - The for loop the exp.date is set before v3 detection? - [is this bug still alive? - can someone please check it] - -[ **] #6 1999-02-22 <backes@rhrk.uni-kl.de> 0.9.3 - Bus error on IRIX 6.4: Crash while doing a keygen. I think while creating - the prime. Other bus errors are reported when doing a "gpg README" - on sparc-solaris2.6. - --> Solaris fixed. - --> IRIX bug still there but someone should test this again! - (<mack@sgi.com> reports that it is still alive in 1.0.0) - (seems to be fixed now. wk 2000-01-14) - -[ *] #18 1999-05-27 <Steffen.Zahn@icn.siemens.de> 0.9.7 - rndunix hangs on hp/ux. The problem is related to my_plcose which is - not always called. (I suggest to use EGD instead of rndunix.) - - -[ *] #24 1999-09-05 <marcus@yoyo.cc.monash.edu.au> 0.9.11 - Does not link libc and libz expect when removing all "-lc -lz" except - for the last one. This happens on some systems when not using the - GNU ld. This need to be fixed in libtool. - -[ *] #28 1999-11-29 - --list-key will only emit an error about unknown UIDs when all UIDs - are unknown. - [Postponed for 1.2] - -[ *] #30 1999-12-16 <pfeifer@dbai.tuwien.ac.at> - Using -r with a name does not check for multiple recpients and may - lead to unwanted recipients. - -[ *] #31 199-12-24 Jeff Allen <jra@corp.webtv.net> - VPATH build in a subdirectory of the sources does not work for po files. - -Next #31 @@ -11,7 +11,7 @@ The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This +software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by @@ -19,7 +19,7 @@ the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you +price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it @@ -201,7 +201,7 @@ otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent +may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to @@ -239,7 +239,7 @@ of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. -Each version is given a distinguishing version number. If the Program +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free @@ -249,7 +249,7 @@ Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free +to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and @@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> + Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -313,7 +313,7 @@ Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -1,151 +1,486 @@ -2000-12-19 Werner Koch <wk@gnupg.org> +2002-06-20 David Shaw <dshaw@jabberwocky.com> - Removed the stuff which is now in libgcrypt. These are - mainly the directories mpi/, cipher/ and gcrypt/. + * NEWS: changes since 1.0.7. -2000-11-14 Werner Koch <wk@gnupg.org> + * configure.ac: Set new version number (1.1.90), and fix Solaris + compiler flags for shared objects. - Version 1.1.2 released. +2002-06-11 David Shaw <dshaw@jabberwocky.com> -2000-11-13 Werner Koch <wk@gnupg.org> + * configure.ac: Move -lsocket and -lnsl checks before LDAP link + tests so they work properly on Solaris. Noted by David Champion. + Also, check for the Mozilla LDAP library if the OpenLDAP library + check fails. Put -lsocket and -lnsl in NETLIBS rather than LIBS + so not all programs are forced to link to them. + +2002-06-05 David Shaw <dshaw@jabberwocky.com> - * acinclude.m4 (GNUPG_FIX_HDR_VERSION): VPATH build fix. + * configure.ac: Add a switch for the experimental external HKP + keyserver interface. -2000-10-10 Werner Koch <wk@gnupg.org> +2002-05-22 Werner Koch <wk@gnupg.org> - * Makefile.am (dist-hook): Create the version file. - * configure.in: Set the libtool version here, removed the need - for the version file. + * configure.ac: Check for strcasecmp and strncasecmp. Removed + stricmp and memicmp checks. -Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de> +2002-05-08 David Shaw <dshaw@jabberwocky.com> - * acinclude.m4 (GNUPG_CHECK_MLOCK): Removed that silly mkdir(). + * configure.ac: If LDAP comes up unusable, try #including <lber.h> + before giving up. Old versions of OpenLDAP require that. - * configure.in: Changes to allow for Solaris random device. - By Nils Ellmenreich. - (--with-egd-socket): New. +2002-05-03 David Shaw <dshaw@jabberwocky.com> - * configure.in (GNUPG_HOMEDIR): New. + * configure.ac: In g10defs.h, use \ for the directory separator + when HAVE_DOSISH_SYSTEM is on. - * configure.in: Check for fstat64 and fopen64 + * configure.ac: Add --disable-exec flag to disable all remote + program execution. --disable-exec implies --disable-ldap and + --disable-mailto. Also look in /usr/lib for sendmail. If + sendmail is not found, do not default - just fail. + +2002-04-30 David Shaw <dshaw@jabberwocky.com> + + * configure.ac: Try and link to a sample LDAP program to check if + the LDAP we're about to use is really sane. The most common + problem (using a very old OpenLDAP), could be fixed with an extra + #include, but this would not be very portable to other LDAP + libraries. + +2002-04-29 Werner Koch <wk@gnupg.org> + + Released 1.0.7. + + * README: Fixed some minor things. + +2002-04-25 Werner Koch <wk@gnupg.org> + + * configure.ac: Check for locale.h and setlocale + +2002-04-24 David Shaw <dshaw@jabberwocky.com> + + * Update NEWS with recent changes. + +2002-04-19 Werner Koch <wk@gnupg.org> + + Released 1.0.6e snapshot. + +2002-04-12 Werner Koch <wk@gnupg.org> + + * configure.ac: Add a warning note to the definition of the + EXTSEP macros. + +2002-04-09 Werner Koch <wk@gnupg.org> + + * configure.ac (ALL_LINGUAS): Added Czech, Galician and Greek + translations. s/es_ES/es/. + +2002-03-06 Werner Koch <wk@gnupg.org> + + * configure.ac (ALL_LINGUAS): s/pt_PT/pt/ + +2002-03-04 David Shaw <dshaw@jabberwocky.com> + + * Add a AC_DEFINE(_GNU_SOURCE). Since this is always defined in + config.h, the various autoconf tests should be tested with it + enabled. This also works around a compiler warning caused by a + minor header bug in glibc 2.1 that causes fseeko to be defined + when building gpg, but not when tested for in configure. + +2002-03-03 Werner Koch <wk@gnupg.org> + + Release 1.0.6d snapshot. + +2002-01-04 David Shaw <dshaw@jabberwocky.com> + + * NEWS: about symmetric messages and fixed file sizes. + +2001-12-22 Werner Koch <wk@gnupg.org> + + Released 1.0.6c snapshot. + + * configure.ac (AH_BOTTOM): Moved EXEC_TEMPFILE_ONLY to here. + + * acconfig.h: Removed, it should no longer be used. + +2001-12-21 David Shaw <dshaw@jabberwocky.com> + + * Add an acconfig.h to define EXEC_TEMPFILE_ONLY on platforms that + can't do fork/exec. + +2001-12-21 Werner Koch <wk@gnupg.org> + + * Makefile.am (dist-hook): We should also look in include for + distfiles. + (EXTRA_DIST): Remove VERSION because it is generated by dist-hook. + +2001-12-20 David Shaw <dshaw@jabberwocky.com> + + * configure.ac: replacement function for mkdtemp() + +2001-12-19 David Shaw <dshaw@jabberwocky.com> + + * configure.ac: Check for stat() + +2001-12-19 Werner Koch <wk@gnupg.org> + + * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Support Cygwin target + * configure.ac [CYGWIN32]: Don't build tiger. By Disastry. + +2001-12-18 Werner Koch <wk@gnupg.org> + + * Makefile.am (SUBDIRS): Add keyserver. + (dist-hook): Only look in mpi and scripts for distfiles; this way + we don't include those of a stale "make dist" directory. + +2001-10-23 Werner Koch <wk@gnupg.org> + + Released 1.0.6b snapshot. + +2001-10-22 Werner Koch <wk@gnupg.org> + + * configure.ac: Fixed for automake 1.5 + +2001-10-17 Werner Koch <wk@gnupg.org> + + * README: Removed note on local_ID. + +2001-09-28 Werner Koch <wk@gnupg.org> + + * configure.ac: From now on add a string "-cvs" to the version to + indicate that this is a pre-release of the given version number. + +2001-09-26 Werner Koch <wk@gnupg.org> + + * configure.ac [MINGW32]: Switched from wsock.dll to ws2_32.dll. + +2001-09-09 Werner Koch <wk@gnupg.org> + + * configure.ac: autoconf changed the name of the maintainer mode + flag, so that not all warnings where enabled. Fixed that. + Reported by Dirk Meyer. + +2001-09-07 Werner Koch <wk@gnupg.org> + + * configure.ac: Test for strsep(). + +2001-09-03 Werner Koch <wk@gnupg.org> + + * configure.ac: Removed GDBM tests. + +2001-08-23 Werner Koch <wk@gnupg.org> + + * configure.in (AC_FUNC_FSEEKO): Add. + (AC_CHECK_FUNCS): Remove fseeko. By Paul Eggert <eggert@twinsun.com>. + +2001-08-22 Werner Koch <wk@gnupg.org> + + * configure.ac (gethrtime): Enhanced the test by running a test + program. + * INSTALL: Removed the note about Solaris problems because the + above test should catch this. + +2001-08-20 Werner Koch <wk@gnupg.org> + + * acinclude.m4: Add check for plock if mlock is broken. + * configure.ac: Use regular tests for -lsocket and -lnsl, + more thorough test for gethrtime, allow specifying the path to + the zlib library if it is not in the default compiler/linker + search path, use ${datadir}. All these test enhancements are by + Albert Chin. + + * configure.ac: Set some compiler flags for dec-osf and hpux. By + Tim Mooney. + + * configure.ac: Create g10defs.h with EXTSEP_S et al. + +2001-08-03 Werner Koch <wk@gnupg.org> + + * configure.ac (VERSION,PACKAGE): Fixed quoting. + +2001-07-26 Werner Koch <wk@gnupg.org> + + * configure.ac: Finally got it running with the new autoconf. Had + to define PACKAGE and VERSION and to add -I.. to each Makefile.am. + +2001-07-09 Werner Koch <wk@gnupg.org> + + Migrated to autoconf 2.50. + * acinclude.m4: Removed the temporary LFS macros and GNUPG_LINK_FILES. + * acconfig.h: Removed + * configure.in: Replaced by... + * configure.ac: and modified for use with autoconf 2.50, use a + literal string for the version number. Replaced GNUPG_LINK_FILES + with AC_CONFIG_LINKS and moved some informational messages to the end. + * VERSION: Removed. + * Makefile.am (DISTCLEANFILES): gettext is better now; no more + need to remove the libintl.h symlink. + (dist-hook): Create VERSION file. + +2001-06-08 Werner Koch <wk@gnupg.org> + + * configure.in (DYNLINK_MOD_CFLAGS): Use -shared with dec-osf. + Reported by Chris Adams. Merged some cases. + +2001-05-29 Werner Koch <wk@gnupg.org> + + Released version 1.0.6. + +2001-05-28 Werner Koch <wk@gnupg.org> + + * configure.in (BUILD_INCLUDED_LIBINTL): Set to no for W32. + +2001-04-29 Werner Koch <wk@gnupg.org> + + Released version 1.0.5. + +2001-04-28 Werner Koch <wk@gnupg.org> + + Updated all copyright notices. + +2001-04-27 Werner Koch <wk@gnupg.org> + + * README: Removed a few outdated paragraphs. + +2001-04-17 Werner Koch <wk@gnupg.org> + + * acinclude.m4 (GNUPG_CHECK_DOCBOOK_TO_TEXI): New. + (GNUPG_CHECK_TYPEDEF): Define _GNU_SOURCE because we will use it + anyway. + + * configure.in: Use it here. + + * configure.in (ALL_LINGUAS): Add Estonian translation by Toomas Soome. + (use_m_debug): Removed --enable-m-debug because it does not work + anymore. + +2001-04-06 Werner Koch <wk@gnupg.org> + + * configure.in (ALL_LINGUAS): Add Turkish translation. Thanks + to Nilgun Belma Buguner. + +2001-03-18 Werner Koch <wk@gnupg.org> + + * configure.in: Hardwire the use of -lsocket for some + systems. Thanks to Reinhard Wobst. + +2001-03-13 Werner Koch <wk@gnupg.org> + + * configure.in: Add copyright notice and -lwsock32. + +2001-03-12 Werner Koch <wk@gnupg.org> + + * INSTALL: Add a note to VPATH builds. + +2001-03-08 Werner Koch <wk@gnupg.org> + + * debian/: Applied update from James. + + Added copyright and license notices to some more files. + +2001-01-18 Werner Koch <wk@gnupg.org> + + * configure.in: Removed tool definitions for MingW32 + +2000-11-17 Werner Koch <wk@gnupg.org> + + * acinclude.m4 (GNUPG_CHECK_FAQPROG): Do not prinnt the warning. + +2000-11-11 Paul Eggert <eggert@twinsun.com> + + Actually Paul's patches are dated 2000-20-17; I applied them today + and merged some ChangeLog entries (wk@gnupg.org). + + * configure.in (AC_SYS_LARGEFILE): Add. + (try_large_file): Remove. All uses removed. + (AC_CHECK_FUNCS): Remove fopen64 and fstat64. + + * acinclude.m4 (AC_SYS_LARGEFILE_TEST_INCLUDES, + AC_SYS_LARGEFILE_MACRO_VALUE, AC_SYS_LARGEFILE): New macros, + taken from GNU tar. + + * configure.in (AC_CHECK_FUNCS): Add fseeko. + +2000-10-17 Werner Koch <wk@gnupg.org> + + * configure.in: Disabled fopen64 checks for Solaris and HPUX. + +2000-10-13 Werner Koch <wk@gnupg.org> + + * configure.in: Append mpi/mpi-asm-defs.h to g10defs.h + +2000-10-09 Werner Koch <wk@gnupg.org> + + * acinclude.m4: Changed wording of the faqprog.pl warning. + +Wed Oct 4 15:50:18 CEST 2000 Werner Koch <wk@openit.de> + + * configure.in: Set DYNLINK_MOD_CFLAGS for Irix. It seems that Irix + needs the -shared flag. In 1.1 we are going to use libtool, so this + module stuff will get redesigned anyway. Suggested by Jeff Long. + +Thu Sep 14 14:20:38 CEST 2000 Werner Koch <wk@openit.de> * acinclude.m4 (GNUPG_CHECK_FAQPROG): New. * configure.in: Test for this. * configure.in (DYNLINK_MOD_CFLAGS): Fix by David Champion. -Tue Aug 22 14:31:15 CEST 2000 Werner Koch <wk@openit.de> +Wed Sep 6 17:55:47 CEST 2000 Werner Koch <wk@openit.de> - Version 1.1.1 + * configure.in: Check for fstat64 and fopen64 -Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de> +Wed Sep 6 14:59:09 CEST 2000 Werner Koch <wk@openit.de> - * agent/: New. - * Makefile.am, configure.in: Support for the new directory. + * configure.in (GNUPG_HOMEDIR): New. -Mon Jul 17 16:35:47 CEST 2000 Werner Koch <wk@> +Fri Aug 25 16:05:38 CEST 2000 Werner Koch <wk@openit.de> - * configure.in (mingw32): Changes to allow for mingw32msvc + * configure.in: Changes to allow for Solaris random device. + By Nils Ellmenreich. + (--with-egd-socket): New. + +Wed Aug 23 19:52:51 CEST 2000 Werner Koch <wk@openit.de> + + * acinclude.m4 (GNUPG_CHECK_MLOCK): Removed that silly mkdir(). -Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@> +Wed Jul 19 11:26:43 CEST 2000 Werner Koch <wk@openit.de> - The big merge between this one and the stable branch 1.0. Still need - to merge TNANKS, AUTHORS and such. It probaly does not compile yet. + * configure.in (mingw32): Changes to allow for mingw32msvc + +Fri Jul 14 10:17:30 CEST 2000 Werner Koch <wk@openit.de> * acinclude.m4 (GNUPG_CHECK_MLOCK): Fixed syntax error in C code. +Wed Jul 12 13:32:06 CEST 2000 Werner Koch <wk@openit.de> + + Version 1.0.2 + +Fri Jun 9 10:09:52 CEST 2000 Werner Koch <wk@openit.de> + * configure.in: Add check for termio.h, wait unctiosn and sigaction. - * acinclude.m4, configure.in (GNUPG_CHECK_GNUMAKE): New. +Wed Jun 7 19:19:09 CEST 2000 Werner Koch <wk@openit.de> * acinclude.m4 (MKDIR_TAKES_ONE_ARG): Check some headers. By Gaël Quéri. - * configure.in (AM_INIT_AUTOMAKE): Use this now. By Gaël. - * acinclude.m4 (GNUPG_CHECK_EXPORTDYNAMIC): Replacement for +Mon Jun 5 12:37:43 CEST 2000 Werner Koch <wk@openit.de> + + * acnclude.m4 (GNUPG_CHECK_EXPORTDYNAMIC): Replacement for GNUPG_CHECK_RDYNAMIC which should handle gcc with non GNU ld nicer. Contributed by Dave Dykstra. * configure.in (GNYPG_CHECK_RDYNAMIC): Replaced by the new check. - * configure.in: Add a test for unisgned long long. + * configure.in (AC_CHECK_AWK): Moved before the first use of AWK. Suggested + by Dave Dykstra. + +Tue May 30 16:37:55 CEST 2000 Werner Koch <wk@openit.de> + + Version 1.0.1-ePit-1 + +Sun May 28 13:55:17 CEST 2000 Werner Koch <wk@openit.de> - * configure.in (DYNLINK_MOD_CFLAGS): Set different for NetBSD. + * acinclude.m4 (GNUPG_SYS_NM_PARSE): Added BSDI support. + (GNUPG_CHECK_RDYNAMIC): Ditto. - * configure.in: Add check for clock_gettime +Wed Apr 19 10:57:26 CEST 2000 Werner Koch <wk@openit.de> - * configure.in (ALL_LINGUAS): Add nl. - * configure.in (ALL_LINGUAS): Add Esperanto. - * configure.in (ALL_LINGUAS): Add sv and ja. + * acconfig.h (HAVE_MLOCK): Added - * configure.in: Use /usr/local for CFLAGS and LDFLAGS when - target is freebsd. By Rémi. +Wed Mar 22 13:50:24 CET 2000 Werner Koch <wk@openit.de> - * configure.in: Do not set development version when the version has - a dash in it. Suggested by Dave Dykstra. + * acinclude.m4 (GNUPG_CHECK_MLOCK): Changed the way to test for + librt. Test suggested by Jeff Long. - * configure.in: Removed substitution for doc/gph/Makefile. - Do all the gcc warning only in maintainer mode. +Fri Mar 17 17:50:25 CET 2000 Werner Koch <wk@openit.de> - * configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc. - Suggested by Alexandre Oliva. - (-Wall): Moved the settting of gcc warning options near to the end - so that tests don't get confused. Suggested by Paul D. Smith. + * acinclude.m4 (GNUPG_CHECK_MLOCK): Do librt check only when + we can't link a test program. This way GNU systems don't need + to link against linrt. + (GNUPG_CHECK_IPC): Fixed use of TRY_COMPILE macro. From Tim Mooney. - * acinclude.m4 (GNUPG_SYS_NM_PARSE): Added BSDI support. - (GNUPG_CHECK_RDYNAMIC): Ditto. +2000-03-14 12:07:54 Werner Koch (wk@habibti.openit.de) - * acinclude.m4 (GNUPG_CHECK_MLOCK): Changed the way to test for - librt. Test suggested by Jeff Long. + * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add support for + DJGPP. + (GNUPG_CHECK_MLOCK): Check whether mlock sits in librt. + * configure.in: Add a test for unisgned long long. - * acinclude.m4 (GNUPG_CHECK_MLOCK): Do librt check only when - we can't link a test program. This way GNU systems don't need - to link against linrt. - (GNUPG_CHECK_IPC): Fixed use of TRY_COMPILE macro. From Tim Mooney. +Tue Mar 7 18:45:31 CET 2000 Werner Koch <wk@gnupg.de> - * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Add support for - DJGPP. - (GNUPG_CHECK_MLOCK): Check whether mlock sits in librt. + * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Add NetBSD. By Thomas Klausner. + * configure.in (DYNLINK_MOD_CFLAGS): Set different for NetBSD. - * acinclude.m4 (GNUPG_CHECK_RDYNAMIC): Add NetBSD. By Thomas Klausner. +Thu Mar 2 15:37:46 CET 2000 Werner Koch <wk@gnupg.de> - * acconfig.h (HAVE_MLOCK): Added + * configure.in: Add check for clock_gettime -Mon Mar 13 19:22:46 CET 2000 Werner Koch <wk@openit.de> +Wed Feb 23 10:07:57 CET 2000 Werner Koch <wk@gnupg.de> - * configure.in: Now uses the Docbook M4s from GPH. + * configure.in (ALL_LINGUAS): Add nl. -Mon Jan 31 17:46:35 CET 2000 Werner Koch <wk@> +Wed Feb 16 16:25:09 CET 2000 Werner Koch <wk@gnupg.de> - * Makefile.am: Re-added tools. By Rémi. + * configure.in (ALL_LINGUAS): Add Esperanto. -Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de> +Wed Feb 16 14:09:00 CET 2000 Werner Koch <wk@gnupg.de> - * configure.in: Create a symlink for types.h in gcrypt/. + * configure.in (ALL_LINGUAS): Add sv and ja. -Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de> + * AUTHORS: Converted to a more compact format. - * configure.in (g10defs.h): Replaced by gnupg-defs.h + * INSTALL: Wrote a note about a Solaris problem. -Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de> +Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de> - * jnlib/ : New. + * configure.in: Use /usr/local for CFLAGS and LDFLAGS when + target is freebsd. By Rémi. - * configure.in: Do set development version when the version has +Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de> + + * configure.in: Do not set development version when the version has a dash in it. Suggested by Dave Dykstra. -Thu Dec 9 17:22:27 CET 1999 Werner Koch <wk@gnupg.de> +Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de> + + * VERSION: Set to 1.0.1. + + * configure.in: Removed substitution for doc/gph/Makefile. + Do all the gcc warning only in maintainer mode. + +Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de> + + * INSTALL: Add a hint for AIX. By Jos Backus. - * acinclude.m4 (GNUPG_FIX_HDR_VERSION): New. - * configure.in: Check and fix the version number of gcrypt/gcrypt.h - so that it is always the save as VERSION. +Sat Dec 4 12:30:28 CET 1999 Werner Koch <wk@gnupg.de> -Thu Oct 28 16:17:46 CEST 1999 Werner Koch <wk@gnupg.de> + * configure.in (dlopen): Use CHECK_FUNC for a test of dlopen in libc. + Suggested by Alexandre Oliva. + (-Wall): Moved the settting of gcc warning options near to the end + so that tests don't get confused. Suggested by Paul D. Smith. - * Started with development series 1.1 on 1999-10-26 +Mon Nov 22 11:14:53 CET 1999 Werner Koch <wk@gnupg.de> -Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> + * BUGS: Replaced content with a link to the online list. - * README-alpha: New +Fri Nov 12 20:33:19 CET 1999 Werner Koch <wk@gnupg.de> + + * README: Fixed a type and add a note about the gnupg-i18n ML. + +Thu Oct 28 16:08:20 CEST 1999 Werner Koch <wk@gnupg.de> + + * acinclude.m4, configure.in (GNUPG_CHECK_GNUMAKE): New. + +Sat Oct 9 20:34:41 CEST 1999 Werner Koch <wk@gnupg.de> + + * configure.in: Tweaked handling of random modules and removed + dummy support for libgcrypt. + * Makefile.am: Removed libgcrypt support. + * cgrypt/ : Removed. + + * Makefile.am: Removed libtool. + +Fri Oct 8 20:32:01 CEST 1999 Werner Koch <wk@gnupg.de> * configure.in: Fixed quoting in test for development version. @@ -153,17 +488,18 @@ Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de> very nice Howto documents - I apoligize for forgetting to mention them earlier. -Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> +Tue Sep 28 20:54:37 CEST 1999 Werner Koch <wk@gnupg.de> + * textfilter.c (copy_clearsig_text) [__MINGW32__): Use CR,LF. + +Fri Sep 17 12:56:42 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> * configure.in: Add "-lcap" when capabilities are requested. Add the conditional CROSS_COMPILING. * Makefile.am: Don't use checks when CROSS_COMPILING. - Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - * configure.in (ALL_LINGUAS): Add pt_PT. * configure.in: Some tweaks for cross compiling under MingW32 @@ -171,12 +507,10 @@ Wed Sep 15 16:22:17 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> Tue Sep 7 17:08:10 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - * VERSION: Set to 1.0.0. Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - * configure.in: Create makefile in doc/gph * acinclude.m4 (GNUPG_FUNC_MKDIR_TAKES_ONE_ARG): New @@ -184,7 +518,6 @@ Mon Sep 6 19:59:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> Thu Sep 2 16:40:55 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> - * VERSION: Set to 0.9.11. Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> @@ -529,3 +862,15 @@ Fri Feb 13 19:43:41 1998 Werner Koch (wk@isil.d.shuttle.de) * configure.in : Fixed zlib stuff * Makefile.am: Likewise + + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + @@ -1,3 +1,14 @@ +Installation instructions for GnuPG +==================================== + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Please read the Basic Installation section somewhere below. @@ -18,6 +29,15 @@ Configure options for GNUPG none - Do not linkl any module in but rely on a dynmically loaded modules. +--with-egd-socket=<name> This is only used when EGD is used as random + gatherer. GnuPG uses by default "~/.gnupg/entropy" + as the socket to connect EGD. Using this option the + socket name can be changed. You may use any filename + here with 2 exceptions: a filename starting with + "~/" uses the socket in the homedirectory of the user + and one starting with a "=" uses a socket in the + GnuPG homedirectory which is bye default "~/.gnupg". + --with-included-zlib Forces usage of the local zlib sources. Default is to use the (shared) library of the system. @@ -26,7 +46,10 @@ Configure options for GNUPG --disable-nls Disable NLS support (See the file ABOUT-NLS) ---enable-m-guard Enable the integrated malloc checking code. +--enable-m-guard Enable the integrated malloc checking code. Please + note that this feature does not work on all CPUs + (e.g. SunOS 5.7 on UltraSparc-2) and might give + you a Bus error. --disable-dynload If you have problems with dynamic loading, this option disables all dynamic loading stuff. @@ -70,6 +93,28 @@ This doesn't matter and we know about it (actually it is due to the some warning options which we have enabled for gcc) +Specific problems on some machines +================================== + + * IBM RS/6000 running AIX: + + Due to a change in gcc (since version 2.8) the MPI stuff may + not build. In this case try to run configure using: + CFLAGS="-g -O2 -mcpu=powerpc" ./configure + + * Compaq C V6.2 for alpha: + + You may want to use the option "-msg-disable ptrmismatch1" + to get rid of the sign/unsigned char mismatch warnings. + + * SVR4.2 (ESIX V4.2 cc) + + Due to problems with the ESIX as, you probably want to do + CFLAGS="-O -K pentium" ./configure --disable-asm + Reported by Reinhard Wobst. + + + The Random Device ================= Random devices are available in Linux, FreeBSD and OpenBSD. @@ -112,6 +157,10 @@ We will use capabilities in the future. The ~/.gnupg directory will be created if it does not exist. Your first action should be to create a key pair: "gpg --gen-key". +Due to limitations in the automake system, the Info format versions of +the man pages are not installed. You have to convert the Texinfo +files by hand (use makeinfo) and copy them to the appropriate place. + Creating a RPM package @@ -201,13 +250,14 @@ Or, on systems that have the `env' program, you can do it like this: Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the same -time by placing the object files for each architecture in their own -directory. To do this, you must use a version of `make', such as GNU `make', -that supports the `VPATH' variable. `cd' to the directory where you want the -object files and executables to go and run the `configure' script. -`configure' automatically checks for the source code in the directory that -`configure' is in and in `..'. + You can compile the package for more than one kind of computer at +the same time by placing the object files for each architecture in +their own directory. To do this, you must use a version of `make', +such as GNU `make', that supports the `VPATH' variable. `cd' to the +directory where you want the object files and executables to go and +run the `configure' script; please use a relative filename name to +invoke `configure'. `configure' automatically checks for the source +code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time diff --git a/Makefile.am b/Makefile.am index 4ad462f95..427d7b639 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,3 +1,21 @@ +# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + ## Process this file with automake to produce Makefile.in if CROSS_COMPILING @@ -6,27 +24,17 @@ else checks = checks endif -if COMPILE_AGENT -agent = agent -else -agent = -endif - -SUBDIRS = intl zlib jnlib util g10 po tools \ - ${agent} doc ${checks} -EXTRA_DIST = README-alpha PROJECTS BUGS -# gettext never gets it right, so we take here care of deleting the -# symlink. my_clean_gcrypt is just a kludge until we can include -# libgcrypt. -DISTCLEANFILES = gnupg-defs.h intl/libintl.h - +SUBDIRS = intl zlib util mpi cipher tools g10 keyserver po doc ${checks} +EXTRA_DIST = PROJECTS BUGS config.h.in +DISTCLEANFILES = g10defs.h # Add all the files listed in "distfiles" files to the distribution, -# apply version number s to some files and create a VERSION file which +# apply version numbers to some files and create a VERSION file which # we need for the Prereq: patch file trick. dist-hook: @set -e; \ - for file in `cd $(top_srcdir); find . -type f -name distfiles`; do \ + for file in `cd $(top_srcdir); \ + find scripts mpi include -type f -name distfiles`; do \ dir=`dirname $$file` ; $(mkinstalldirs) $(distdir)/$$dir ; \ for i in distfiles `cat $(top_srcdir)/$$file` ; do \ ln $(top_srcdir)/$$dir/$$i $(distdir)/$$dir/$$i 2> /dev/null \ @@ -36,8 +44,11 @@ dist-hook: @set -e; \ sed -e 's/@pkg_version@/$(VERSION)/g' \ $(top_srcdir)/scripts/gnupg.spec.in \ - > $(distdir)/scripts/gnupg.spec ; \ + > $(distdir)/scripts/gnupg.spec echo "$(VERSION)" > $(distdir)/VERSION + + + @@ -1,15 +1,258 @@ +Noteworthy changes in version 1.1.90 +------------------------------------------------ - GnuPG now needs libgcrypt - you will find it at the same place - where you got GnuPG. + * New commands: --personal-cipher-preferences, + --personal-digest-preferences, and + --personal-compress-preferences allow the user to specify which + algorithms are to be preferred. Note that this does not permit + using an algorithm that is not present in the recipient's + preferences (which would violate the OpenPGP standard). This + just allows sorting the preferences differently. -Noteworthy changes in version 1.1.2 ------------------------------------ + * New "group" command to refer to several keys with one name. + + * A warning is issued if the user forces the use of an algorithm + that is not listed in the recipient's preferences. + + * Full revocation key (aka "designated revoker") support. + + * The preferred hash algorithms on a key are consulted when + encrypting a signed message to that key. Note that this is + disabled by default by a SHA1 preference in + --personal-digest-preferences. + + * --cert-digest-algo allows the user to specify the hash algorithm + to use when signing a key rather than the default SHA1 (or MD5 + for PGP2 keys). Do not use this feature unless you fully + understand the implications of this. + + * --pgp7 mode automatically sets all necessary options to ensure + that the resulting message will be usable by a user of PGP 7.x. + + * New --attribute-fd command for frontends and scripts to get the + contents of attribute packets (i.e. photos) + + * In expert mode, the user can now re-sign a v3 key with a v4 + self-signature. This does not change the v3 key into a v4 key, + but it does allow the user to use preferences, primary ID flags, + etc. + + * Significantly improved photo ID support on non-unixlike + platforms. + + * The version number has jumped ahead to 1.1.90 to skip over the + old version 1.1 and to get ready for the upcoming 1.2. + + * ElGamal sign and encrypt is not anymore allowed in the key + generation dialog unless in expert mode. RSA sign and encrypt + has been added with the same restrictions. + + * [W32] Keyserver access does work with Windows NT. + + +Noteworthy changes in version 1.0.7 (2002-04-29) +------------------------------------------------ + + * Secret keys are now stored and exported in a new format which + uses SHA-1 for integrity checks. This format renders the + Rosa/Klima attack useless. Other OpenPGP implementations might + not yet support this, so the option --simple-sk-checksum creates + the old vulnerable format. + + * The default cipher algorithm for encryption is now CAST5, + default hash algorithm is SHA-1. This will give us better + interoperability with other OpenPGP implementations. + + * Symmetric encrypted messages now use a fixed file size if + possible. This is a tradeoff: it breaks PGP 5, but fixes PGP 2, + 6, and 7. Note this was only an issue with RFC-1991 style + symmetric messages. + + * Photographic user ID support. This uses an external program to + view the images. + + * Enhanced keyserver support via keyserver "plugins". GnuPG comes + with plugins for the NAI LDAP keyserver as well as the HKP email + keyserver. It retains internal support for the HKP HTTP + keyserver. + + * Nonrevocable signatures are now supported. If a user signs a + key nonrevocably, this signature cannot be taken back so be + careful! + + * Multiple signature classes are usable when signing a key to + specify how carefully the key information (fingerprint, photo + ID, etc) was checked. + + * --pgp2 mode automatically sets all necessary options to ensure + that the resulting message will be usable by a user of PGP 2.x. + + * --pgp6 mode automatically sets all necessary options to ensure + that the resulting message will be usable by a user of PGP 6.x. + + * Signatures may now be given an expiration date. When signing a + key with an expiration date, the user is prompted whether they + want their signature to expire at the same time. + + * Revocation keys (designated revokers) are now supported if + present. There is currently no way to designate new keys as + designated revokers. + + * Permissions on the .gnupg directory and its files are checked + for safety. + + * --expert mode enables certain silly things such as signing a + revoked user id, expired key, or revoked key. + + * Some fixes to build cleanly under Cygwin32. + + * New tool gpgsplit to split OpenPGP data formats into packets. + + * New option --preserve-permissions. + + * Subkeys created in the future are not used for encryption or + signing unless the new option --ignore-valid-from is used. + + * Revoked user-IDs are not listed unless signatures are listed too + or we are in verbose mode. + + * There is no default comment string with ascii armors anymore + except for revocation certificates and --enarmor mode. + + * The command "primary" in the edit menu can be used to change the + primary UID, "setpref" and "updpref" can be used to change the + preferences. + + * Fixed the preference handling; since 1.0.5 they were erroneously + matched against against the latest user ID and not the given one. + + * RSA key generation. + + * Merged Stefan's patches for RISC OS in. See comments in + scripts/build-riscos. + + * It is now possible to sign and conventional encrypt a message (-cs). + + * The MDC feature flag is supported and can be set by using + the "updpref" edit command. + + * The status messages GOODSIG and BADSIG are now returning the primary + UID, encoded using %XX escaping (but with spaces left as spaces, + so that it should not break too much) + + * Support for GDBM based keyrings has been removed. + + * The entire keyring management has been revamped. + + * The way signature stati are store has changed so that v3 + signatures can be supported. To increase the speed of many + operations for existing keyrings you can use the new + --rebuild-keydb-caches command. + + * The entire key validation process (trustdb) has been revamped. + See the man page entries for --update-trustdb, --check-trustdb + and --no-auto-check-trustdb. + + * --trusted-keys is again obsolete, --edit can be used to set the + ownertrust of any key to ultimately trusted. - --> THIS IS A DEVELOPMENT VERSION; see README and README-alpha <-- + * A subkey is never used to sign keys. - * Add Rijndael (AES) support. + * Read only keyrings are now handled as expected. - * Removed gdbm support. + +Noteworthy changes in version 1.0.6 (2001-05-29) +------------------------------------------------ + + * Security fix for a format string bug in the tty code. + + * Fixed format string bugs in all PO files. + + * Removed Russian translation due to too many bugs. The FTP + server has an unofficial but better translation in the contrib + directory. + + * Fixed expire time calculation and keyserver access. + + * The usual set of minor bug fixes and enhancements. + + * non-writable keyrings are now correctly handled. + + +Noteworthy changes in version 1.0.5 (2001-04-29) +------------------------------------------------ + + * WARNING: The semantics of --verify have changed to address a + problem with detached signature detection. --verify now ignores + signed material given on stdin unless this is requested by using + a "-" as the name for the file with the signed material. Please + check all your detached signature handling applications and make + sure that they don't pipe the signed material to stdin without + using a filename together with "-" on the the command line. + + * WARNING: Corrected hash calculation for input data larger than + 512M - it was just wrong, so you might notice bad signature in + some very big files. It may be wise to keep an old copy of + GnuPG around. + + * Secret keys are no longer imported unless you use the new option + --allow-secret-key-import. This is a kludge and future versions will + handle it in another way. + + * New command "showpref" in the --edit-key menu to show an easier + to understand preference listing. + + * There is now the notation of a primary user ID. For example, it + is printed with a signature verification as the first user ID; + revoked user IDs are not printed there anymore. In general the + primary user ID is the one with the latest self-signature. + + * New --charset=utf-8 to bypass all internal conversions. + + * Large File Support (LFS) is now working. + + * New options: --ignore-crc-error, --no-sig-create-check, + --no-sig-cache, --fixed_list_mode, --no-expensive-trust-checks, + --enable-special-filenames and --use-agent. See man page. + + * New command --pipemode, which can be used to run gpg as a + co-process. Currently only the verification of detached + signatures are working. See doc/DETAILS. + + * Keyserver support for the W32 version. + + * Rewritten key selection code so that GnuPG can better cope with + multiple subkeys, expire dates and so. The drawback is that it + is slower. + + * A whole lot of bug fixes. + + * The verification status of self-signatures are now cached. To + increase the speed of key list operations for existing keys you + can do the following in your GnuPG homedir (~/.gnupg): + cp pubring.gpg pubring.gpg.save && gpg --export-all >x && \ + rm pubring.gpg && gpg --import x + Only v4 keys (i.e not the old RSA keys) benefit from this caching. + + * New translations: Estonian, Turkish. + + +Noteworthy changes in version 1.0.4 (2000-10-17) +------------------------------------------------ + + * Fixed a serious bug which could lead to false signature verification + results when more than one signature is fed to gpg. This is the + primary reason for releasing this version. + + * New utility gpgv which is a stripped down version of gpg to + be used to verify signatures against a list of trusted keys. + + * Rijndael (AES) is now supported and listed with top preference. + + * --with-colons now works with --print-md[s]. + +Noteworthy changes in version 1.0.3 (2000-09-18) +------------------------------------------------ * Fixed problems with piping to/from other MS-Windows software @@ -17,6 +260,10 @@ Noteworthy changes in version 1.1.2 * Revoked user IDs are now marked in the output of --list-key + * New options --show-session-key and --override-session-key + to help the British folks to somewhat minimize the danger + of this Orwellian RIP bill. + * New options --merge-only and --try-all-secrets. * New configuration option --with-egd-socket. @@ -24,7 +271,7 @@ Noteworthy changes in version 1.1.2 * The --trusted-key option is back after it left us with 0.9.5 * RSA is supported. Key generation does not yet work but will come - soon. + soon. * CAST5 and SHA-1 are now the default algorithms to protect the key and for symmetric-only encryption. This should solve a couple @@ -34,14 +281,10 @@ Noteworthy changes in version 1.1.2 * Twofish and MDC enhanced encryption is now used. PGP 7 supports this. Older versions of GnuPG don't support it, so they should be upgraded to at least 1.0.2 - - -Noteworthy changes in version 1.1.1 ------------------------------------ + - * Add gpg-agent. - - * Removed option --emulate-checksum-bug +Noteworthy changes in version 1.0.2 (2000-07-12) +---------------------------------------------- * Fixed expiration handling of encryption keys. @@ -93,7 +336,12 @@ Noteworthy changes in version 1.1.1 entirely. This option should not yet be used. * New option --no-auto-key-retrieve to disable retrieving of - a missing public key from a keyerver, when a keyerver has been set. + a missing public key from a keyserver, when a keyserver has been set. + + * Danish translation + +Noteworthy changes in version 1.0.1 (1999-12-16) +----------------------------------- * New command --verify-files. New option --fast-list-mode. @@ -102,7 +350,7 @@ Noteworthy changes in version 1.1.1 * Fixed some minor bugs and the problem with conventional encrypted packets which did use the gpg v3 partial length headers. - * Some more translations. + * Add Indonesian and Portugese translations. * Fixed a bug with symmetric-only encryption using the non-default 3DES. The option --emulate-3des-s2k-bug may be used to decrypt documents @@ -120,16 +368,8 @@ Noteworthy changes in version 1.1.1 * New keys are now generated with an additional preference to Blowfish. - * Removed the GNU Privacy Handbook from the distribution because it - is now in the package GPH. - - -Noteworthy changes in version 1.1.0 (1999-10-26) ------------------------------------ - - * Did a couple of changes for this new development series. - This release basically works on my machine but may have - serious problems. + * Removed the GNU Privacy Handbook from the distribution as it will go + into a separate one. Noteworthy changes in version 1.0.0 (1999-09-07) @@ -928,3 +1168,13 @@ Noteworthy changes in version 0.2.3 * The string "(INSECURE!)" is appended to a new user-id if this is generated on a system without a good random number generator. + +Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -1,7 +1,6 @@ +Checking ElGamal signatures is really slow and the reason for the long +running time on parts o my keyring. Because somekeys are also checked at startup, this is even worser. I should invalidate my self signature with algo 16 or 20. -gcry_md_open() may return NULL in case of an unknown algorithm - -Return GCRYERR_NOMEM instead of using m_alloc in most library functions SCO UnixWare/7.1.0 reported by Allan Clark <allanc@sco.com> for 0.9.8 @@ -13,16 +12,35 @@ Some other reported cpu-vendor-os strings: sparc-sun-solaris5.4 sparc-sun-sunos4.1.2 i386-pc-sysv4.2 (USL Unixware v1.1.2) + powerpc-ibm-aix4.3.2.0 John Payne <jcapayne@att.com> + +gpg 1.0.1 okay with MP-RAS 3.02.01 Edition 5 using gcc 2.95.2 and EGD + By <CSpeicher@eisi.com> + +gpg 1.0.1 okay with 4.0.1 BSDI BSD/OS 4.0 i386 + + +rndw32 tested on: + Windows 98 4.10.1998 mit einem AMD-K6-2-450 + Michael Engels <angel@dalrin.de>) + Windows 95 4.00.950a + Windows NT 4.00.1381 -Simos Hadjiyiannis <hadjiyia@cs.colostate.edu> -runs successfully on HP-UX v11.00 as well. (using gcc) -Johan Wevers <johanw@vulcan.xs4all.nl> is working on a NL translation. + +tried to compile GnuPG on AIX 4.3 on a power CPU based machine. It +doesn't work out of the box but i found a way to do so: + PowerPC based machines: + CFLAGS="-g -O2 -mcpu=powerpc" ./configure --disable-asm --disable-dynload ++--enable-static-rnd=egd + Power1 and Power2 machines: + CFLAGS="-g -O2 -mcpu=power" ./configure --disable-asm --disable-dynload ++--enable-static-rnd=egd @@ -100,35 +100,3 @@ Ctrl-D does not work correct for messages entered at the tty. FIX: 1999-06-18 (Better EOF detection on terminals) -[ *] #22 1999-07-22 - Solaris make has problems with the generated POTFILES - seems to be a - gettext bug. Use GNU make as a workaround. - FIX: 1999-12-03 (meanwhile fixed in gettext) - -[ *] #23 1999-09-03 <todd.brooks@yale.edu> 0.9.11 - Only the first signature of a cleartext sig seems to be verified. - Can't fix it in 1.0 because the code is semi-frozen. - HMMM: Can't reprodude the bug here - it just works. - -[ **] #25 1999-10-04 <wk@gnupg.org> 1.0 - Validity check based on user name is only done when listing a key; - the key ID based checking (selecting the user ID with the most - validity) is used in all other cases. The Edit menu does not have - a way to disable user ID based validity. - FIX: 1999-12-03 (1.0.x only) - -[ *] #26 1999-11-11 - gpg still does not take UTF8 strings to select a UID. - FIX: 1999-11-12 - -[ **] #27 1999-11-12 <oren@hishome.net> - Unknown packets (type 17 - photo ID?) mess up the checking - of self-signature because they are simply ignored. - FIX: 1999-11-12 (1.0.x only) - -[ **] #29 1999-12-01 <karney@pppl.gov> - Using a --gen-key on a new user account (w/o ~./gnupg) doesn't pay - attention to the standard options files, which get's installed - afterwards. - FIX: 1999-12-02 - @@ -15,8 +15,9 @@ * add an option to re-create a public key from a secret key; we can do this in trustdb.c:verify_own_keys. (special tool?) - - * rewrite --list-packets or put it into another tool. + Hmmm, we better drop the duplication of the public part and just keep + the secrets in the "secring" - this has the additional that we can + put those secrets on a hardware token. * write a tool to extract selected keys from a file. @@ -28,3 +29,18 @@ We should add an abstraction layer so that adding support for different certificate structures will become easier. + * "Michael T. Babcock" <mbabcock@fibrespeed.net> suggested to write + an event log so that other software can display a key history or + alike with GnuPG results. This should be connected to the keyrings. + + + + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -1,17 +1,497 @@ + GnuPG - The GNU Privacy Guard ------------------------------- - Version 1.1 + Version 1.0 + + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Intro + ----- + + GnuPG is GNU's tool for secure communication and data storage. + It can be used to encrypt data and to create digital signatures. + It includes an advanced key management facility and is compliant + with the proposed OpenPGP Internet standard as described in RFC2440. + + GnuPG works best on GNU/Linux or *BSD systems. Most other Unices + are also supported but are not as well tested as the Free Unices. + See http://www.gnupg.org/gnupg.html#supsys for a list of systems + which are known to work. + + See the file COPYING for copyright and warranty information. + + Because GnuPG does not use use any patented algorithm it cannot be + compatible with PGP2 versions. PGP 2.x uses IDEA (which is patented + worldwide). + + The default algorithms are DSA and ElGamal. ElGamal for signing + is still available, but because of the larger size of such + signatures it is deprecated (Please note that the GnuPG + implementation of ElGamal signatures is *not* insecure). Symmetric + algorithms are: AES, 3DES, Blowfish, CAST5 and Twofish + Digest algorithms available are MD5, RIPEMD160 and SHA1. + + + Installation + ------------ + + Please read the file INSTALL! + + Here is a quick summary: + + 1) Check that you have unmodified sources. The below on how to do this. + Don't skip it - this is an important step! + + 2) Unpack the TAR. With GNU tar you can do it this way: + "tar xzvf gnupg-x.y.z.tar.gz" + + 3) "cd gnupg-x.y.z" + + 4) "./configure" + + 5) "make" + + 6) "make install" + + 7) You end up with a "gpg" binary in /usr/local/bin. + Note: Because some old programs rely on the existence of a + binary named "gpgm" (which was build by some Beta versions + of GnuPG); you may want to install a symbolic link to it: + "cd /usr/local/bin; ln -s gpg gpgm" + + 8) To avoid swapping out of sensitive data, you can install "gpg" as + suid root. If you don't do so, you may want to add the option + "no-secmem-warning" to ~/.gnupg/options + + + How to Verify the Source + ------------------------ + + In order to check that the version of GnuPG which you are going to + install is an original and unmodified one, you can do it in one of + the following ways: + + a) If you already have a trusted Version of GnuPG installed, you + can simply check the supplied signature: + + $ gpg --verify gnupg-x.y.z.tar.gz.asc + + This checks that the detached signature gnupg-x.y.z.tar.gz.asc + is indeed a a signature of gnupg-x.y.z.tar.gz. The key used to + create this signature is: + + "pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) <dd9jn@gnu.org>" + + If you do not have this key, you can get it from the source in + the file doc/samplekeys.asc (use "gpg --import doc/samplekeys.asc" + to add it to the keyring) or from any keyserver. You have to + make sure that this is really the key and not a faked one. You + can do this by comparing the output of: + + $ gpg --fingerprint 0x57548DCD + + with the elsewhere published fingerprint + + Please note, that you have to use an old version of GnuPG to + do all this stuff. *Never* use the version which you are going + to check! + + + b) If you don't have any of the above programs, you have to verify + the MD5 checksum: + + $ md5sum gnupg-x.y.z.tar.gz + + This should yield an output _similar_ to this: + + fd9351b26b3189c1d577f0970f9dcadc gnupg-x.y.z.tar.gz + + Now check that this checksum is _exactly_ the same as the one + published via the announcement list and probably via Usenet. + + + + Documentation + ------------- + + The manual will be distributed separate under the name "gph". + An online version of the latest manual draft is available at the + GnuPG web pages: + + http://www.gnupg.org/gph/ + + A list of frequently asked questions is available in GnuPG's + distibution in the file doc/FAQ and online as: + + http://www.gnupg.org/faq.html + + A couple of HOWTO documents are available online; for a listing see: + + http://www.gnupg.org/docs.html#howtos + + A man page with a description of all commands and options gets installed + along with the program. + + + Introduction + ------------ + + Here is a brief overview on how to use GnuPG - it is strongly suggested + that you read the manual and other information about the use of + cryptography. GnuPG is only a tool, secure usage requires that + YOU KNOW WHAT YOU ARE DOING. + + If you already have a DSA key from PGP 5 (they call them DH/ElGamal) + you can simply copy the pgp keyrings over the GnuPG keyrings after + running gpg once to create the correct directory. + + The normal way to create a key is + + gpg --gen-key + + This asks some questions and then starts key generation. To create + good random numbers for the key parameters, GnuPG needs to gather + enough noise (entropy) from your system. If you see no progress + during key generation you should start some other activities such + as mouse moves or hitting on the CTRL and SHIFT keys. + + Generate a key ONLY on a machine where you have direct physical + access - don't do it over the network or on a machine used also + by others - especially if you have no access to the root account. + + When you are asked for a passphrase use a good one which you can + easy remember. Don't make the passphrase too long because you have + to type it for every decryption or signing; but, - AND THIS IS VERY + IMPORTANT - use a good one that is not easily to guess because the + security of the whole system relies on your secret key and the + passphrase that protects it when someone gains access to your secret + keyring. A good way to select a passphrase is to figure out a short + nonsense sentence which makes some sense for you and modify it by + inserting extra spaces, non-letters and changing the case of some + characters - this is really easy to remember especially if you + associate some pictures with it. + + Next, you should create a revocation certificate in case someone + gets knowledge of your secret key or you forgot your passphrase + + gpg --gen-revoke your_user_id + + Run this command and store the revocation certificate away. The output + is always ASCII armored, so that you can print it and (hopefully + never) re-create it if your electronic media fails. + + Now you can use your key to create digital signatures + + gpg -s file + + This creates a file "file.gpg" which is compressed and has a + signature attached. + + gpg -sa file + + Same as above, but creates a file "file.asc" which is ASCII armored + and and ready for sending by mail. It is better to use your + mailers features to create signatures (The mailer uses GnuPG to do + this) because the mailer has the ability to MIME encode such + signatures - but this is not a security issue. + + gpg -s -o out file + + Creates a signature of "file", but writes the output to the file + "out". + + Everyone who knows your public key (you can and should publish + your key by putting it on a key server, a web page or in your .plan + file) is now able to check whether you really signed this text + + gpg --verify file + + GnuPG now checks whether the signature is valid and prints an + appropriate message. If the signature is good, you know at least + that the person (or machine) has access to the secret key which + corresponds to the published public key. + + If you run gpg without an option it will verify the signature and + create a new file that is identical to the original. gpg can also + run as a filter, so that you can pipe data to verify trough it + + cat signed-file | gpg | wc -l + + which will check the signature of signed-file and then display the + number of lines in the original file. + + To send a message encrypted to someone you can use + + gpg -e -r heine file + + This encrypts "file" with the public key of the user "heine" and + writes it to "file.gpg" + + echo "hello" | gpg -ea -r heine | mail heine + + Ditto, but encrypts "hello\n" and mails it as ASCII armored message + to the user with the mail address heine. + + gpg -se -r heine file + + This encrypts "file" with the public key of "heine" and writes it + to "file.gpg" after signing it with your user id. + + gpg -se -r heine -u Suttner file + + Ditto, but sign the file with your alternative user id "Suttner" + + + GnuPG has some options to help you publish public keys. This is + called "exporting" a key, thus + + gpg --export >all-my-keys + + exports all the keys in the keyring and writes them (in a binary + format) to "all-my-keys". You may then mail "all-my-keys" as an + MIME attachment to someone else or put it on an FTP server. To + export only some user IDs, you give them as arguments on the command + line. + + To mail a public key or put it on a web page you have to create + the key in ASCII armored format + + gpg --export --armor | mail panther@tiger.int + + This will send all your public keys to your friend panther. + + If you have received a key from someone else you can put it + into your public keyring. This is called "importing" + + gpg --import [filenames] + + New keys are appended to your keyring and already existing + keys are updated. Note that GnuPG does not import keys that + are not self-signed. + + Because anyone can claim that a public key belongs to her + we must have some way to check that a public key really belongs + to the owner. This can be achieved by comparing the key during + a phone call. Sure, it is not very easy to compare a binary file + by reading the complete hex dump of the file - GnuPG (and nearly + every other program used for management of cryptographic keys) + provides other solutions. + + gpg --fingerprint <username> + + prints the so called "fingerprint" of the given username which + is a sequence of hex bytes (which you may have noticed in mail + sigs or on business cards) that uniquely identifies the public + key - different keys will always have different fingerprints. + It is easy to compare fingerprints by phone and I suggest + that you print your fingerprint on the back of your business + card. To see the fingerprints of the secondary keys, you can + give the command twice; but this is normally not needed. + + If you don't know the owner of the public key you are in trouble. + Suppose however that friend of yours knows someone who knows someone + who has met the owner of the public key at some computer conference. + Suppose that all the people between you and the public key holder + may now act as introducers to you. Introducers signing keys thereby + certify that they know the owner of the keys they sign. If you then + trust all the introducers to have correctly signed other keys, you + can be be sure that the other key really belongs to the one who + claims to own it.. + + There are 2 steps to validate a key: + 1. First check that there is a complete chain + of signed keys from the public key you want to use + and your key and verify each signature. + 2. Make sure that you have full trust in the certificates + of all the introduces between the public key holder and + you. + Step 2 is the more complicated part because there is no easy way + for a computer to decide who is trustworthy and who is not. GnuPG + leaves this decision to you and will ask you for a trust value + (here also referenced as the owner-trust of a key) for every key + needed to check the chain of certificates. You may choose from: + a) "I don't know" - then it is not possible to use any + of the chains of certificates, in which this key is used + as an introducer, to validate the target key. Use this if + you don't know the introducer. + b) "I do not trust" - Use this if you know that the introducer + does not do a good job in certifying other keys. The effect + is the same as with a) but for a) you may later want to + change the value because you got new information about this + introducer. + c) "I trust marginally" - Use this if you assume that the + introducer knows what he is doing. Together with some + other marginally trusted keys, GnuPG validates the target + key then as good. + d) "I fully trust" - Use this if you really know that this + introducer does a good job when certifying other keys. + If all the introducer are of this trust value, GnuPG + normally needs only one chain of signatures to validate + a target key okay. (But this may be adjusted with the help + of some options). + This information is confidential because it gives your personal + opinion on the trustworthiness of someone else. Therefore this data + is not stored in the keyring but in the "trustdb" + (~/.gnupg/trustdb.gpg). Do not assign a high trust value just + because the introducer is a friend of yours - decide how well she + understands the implications of key signatures and you may want to + tell her more about public key cryptography so you can later change + the trust value you assigned. + + Okay, here is how GnuPG helps you with key management. Most stuff + is done with the --edit-key command + + gpg --edit-key <keyid or username> + + GnuPG displays some information about the key and then prompts + for a command (enter "help" to see a list of commands and see + the man page for a more detailed explanation). To sign a key + you select the user ID you want to sign by entering the number + that is displayed in the leftmost column (or do nothing if the + key has only one user ID) and then enter the command "sign" and + follow all the prompts. When you are ready, give the command + "save" (or use "quit" to cancel your actions). + + If you want to sign the key with another of your user IDs, you + must give an "-u" option on the command line together with the + "--edit-key". + + Normally you want to sign only one user ID because GnuPG + uses only one and this keeps the public key certificate + small. Because such key signatures are very important you + should make sure that the signatories of your key sign a user ID + which is very likely to stay for a long time - choose one with an + email address you have full control of or do not enter an email + address at all. In future GnuPG will have a way to tell which + user ID is the one with an email address you prefer - because + you have no signatures on this email address it is easy to change + this address. Remember, your signatories sign your public key (the + primary one) together with one of your user IDs - so it is not possible + to change the user ID later without voiding all the signatures. + + Tip: If you hear about a key signing party on a computer conference + join it because this is a very convenient way to get your key + certified (But remember that signatures have nothing to to with the + trust you assign to a key). + + + 8 Ways to Specify a User ID + -------------------------- + There are several ways to specify a user ID, here are some examples. + + * Only by the short keyid (prepend a zero if it begins with A..F): + + "234567C4" + "0F34E556E" + "01347A56A" + "0xAB123456 + + * By a complete keyid: + + "234AABBCC34567C4" + "0F323456784E56EAB" + "01AB3FED1347A5612" + "0x234AABBCC34567C4" + + * By a fingerprint: + + "1234343434343434C434343434343434" + "123434343434343C3434343434343734349A3434" + "0E12343434343434343434EAB3484343434343434" + + The first one is MD5 the others are ripemd160 or sha1. + + * By an exact string: + + "=Heinrich Heine <heinrichh@uni-duesseldorf.de>" + + * By an email address: + + "<heinrichh@uni-duesseldorf.de>" + + * By word match + + "+Heinrich Heine duesseldorf" + + All words must match exactly (not case sensitive) and appear in + any order in the user ID. Words are any sequences of letters, + digits, the underscore and characters with bit 7 set. + + * Or by the usual substring: + + "Heine" + "*Heine" + + The '*' indicates substring search explicitly. + + + Batch mode + ---------- + If you use the option "--batch", GnuPG runs in non-interactive mode and + never prompts for input data. This does not even allow entering the + passphrase. Until we have a better solution (something like ssh-agent), + you can use the option "--passphrase-fd n", which works like PGP's + PGPPASSFD. + + Batch mode also causes GnuPG to terminate as soon as a BAD signature is + detected. + + + Exit status + ----------- + GnuPG returns with an exit status of 1 if in batch mode and a bad signature + has been detected or 2 or higher for all other errors. You should parse + stderr or, better, the output of the fd specified with --status-fd to get + detailed information about the errors. + + + How to Get More Information + --------------------------- + + The primary WWW page is "http://www.gnupg.org" + The primary FTP site is "ftp://ftp.gnupg.org/gcrypt/" + + See http://www.gnupg.org/mirrors.html for a list of mirrors + and use them if possible. You may also find GnuPG mirrored on + some of the regular GNU mirrors. + + We have some mailing lists dedicated to GnuPG: + + gnupg-announce@gnupg.org For important announcements like + new versions and such stuff. + This is a moderated list and has + very low traffic. + + gnupg-users@gnupg.org For general user discussion and + help. + + gnupg-devel@gnupg.org GnuPG developers main forum. + + You subscribe to one of the list by sending mail with a subject + of "subscribe" to x-request@gnupg.org, where x is the name of the + mailing list (gnupg-announce, gnupg-users, etc.). An archive of + the mailing lists is available at http://lists.gnupg.org . - WARNING: This is the current development branch - of GnuPG. THIS SHOULD NOT BE USED IN - A PRODUCTION ENVIRONMENT. It will - change quite often and may have serious - problems. Use the GnuPG from the stable - Branch 1.0.x for real work. The next - stable release will be 1.2 + The gnupg.org domain is hosted in Germany to avoid possible legal + problems (technical advices may count as a violation of ITAR). -If you are looking for the CVS from the stable tree, use + Please direct bug reports to <gnupg-bugs@gnu.org> or post + them direct to the mailing list <gnupg-devel@gnupg.org>. -cvs -z3 -d :pserver:anoncvs@cvs.gnupg.org:/cvs/gnupg co -r STABLE-BRANCH-1-0 gnupg + Please direct questions about GnuPG to the users mailing list or + one of the pgp newsgroups; please do not direct questions to one + of the authors directly as we are busy working on improvements + and bug fixes. Both mailing lists are watched by the authors + and we try to answer questions when time allows us to do so. + Commercial grade support for GnuPG is available; please see + the GNU service directory or search other resources. @@ -3,79 +3,154 @@ reporting problems, suggesting various improvements or submitting actual code. Here is a list of those people. Help me keep it complete and free of errors. +Adam Mitchell adam@cafe21.org +Albert Chin china@thewrittenword.com +Alec Habig habig@budoe2.bu.edu Allan Clark allanc@sco.com Anand Kumria wildfire@progsoc.uts.edu.au +Andreas Haumer andreas@xss.co.at +Anthony Mulcahy anthony@kcn.ne.jp Ariel T Glenn ariel@columbia.edu Bodo Moeller Bodo_Moeller@public.uni-hamburg.de +Brendan O'Dea bod@debian.org Brenno de Winter brenno@dewinter.com +Brian M. Carlson karlsson@hal-pc.org Brian Moore bem@cmc.net Brian Warner warner@lothar.com Bryan Fullerton bryanf@samurai.com Caskey L. Dickson caskey@technocage.com Cees van de Griend cees-list@griend.xs4all.nl Charles Levert charles@comm.polymtl.ca +Chip Salzenberg chip@valinux.com +Chris Adams cmadams@hiwaay.net +Christian Kurz shorty@debian.org Christian von Roques roques@pond.sub.org Christopher Oliver oliver@fritz.traverse.net Christian Recktenwald chris@citecs.de +Dan Winship danw@helixcode.com Daniel Eisenbud eisenbud@cs.swarthmore.edu Daniel Koening dan@mail.isis.de +Daniel Resare daniel@resare.com +Dave Dykstra dwd@bell-labs.com +David C Niemi niemi@tuxers.net +David Champion dgc@uchicago.edu David Ellement ellement@sdd.hp.com +David Hallinan hallinan@rtd.com +David Hollenberg dhollen@ISI.EDU +David Mathog MATHOG@seqaxp.bio.caltech.edu +David R. Bergstein dbergstein@home.com +David Shaw dshaw@jabberwocky.com Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de +Dimitri dmitri@advantrix.com Dirk Lattermann dlatt@t-online.de +Dirk Meyer dirk.meyer@dinoex.sub.org +Disastry Disastry@saiknes.lv +Douglas Calvert dfc@anize.org Ed Boraas ecxjo@esperanto.org +Edmund GRIMLEY EVANS edmundo@rano.org +Edwin Woudt edwin@woudt.nl Enzo Michelangeli em@MailAndNews.com Ernst Molitor ernst.molitor@uni-bonn.de -Fabio Coatti cova@felix.unife.it +Fabio Coatti cova@ferrara.linux.it Felix von Leitner leitner@amdiv.de +fish stiqz fish@analog.org +Florian Weimer Florian.Weimer@rus.uni-stuttgart.de +Francesco Potorti pot@gnu.org +Frank Donahoe fdonahoe@wilkes1.wilkes.edu Frank Heckenbach heckenb@mi.uni-erlangen.de Frank Stajano frank.stajano@cl.cam.ac.uk -Gaël Quéri gqueri@mail.dotcom.fr +Frank Tobin ftobin@uiuc.edu +Gabriel Rosenkoetter gr@eclipsed.net +Gaël Quéri gael@lautre.net +Gene Carter gcarter@lanier.com +Georg Schwarz georg.schwarz@iname.com +Giampaolo Tomassoni g.tomassoni@libero.it +Gilbert Fernandes gilbert_fernandes@hotmail.com Greg Louis glouis@dynamicro.on.ca Greg Troxel gdt@ir.bbn.com Gregory Steuck steuck@iname.com Geoff Keating geoffk@ozemail.com.au Harald Denker harry@hal.westfalen.de +Holger Baust Holger.Baust@freenet-ag.de Hendrik Buschkamp buschkamp@rheumanet.org Holger Schurig holger@d.om.org +Holger Smolinski smolinsk@de.ibm.com +Holger Trapp Holger.Trapp@informatik.tu-chemnitz.de Hugh Daniel hugh@toad.com +Huy Le huyle@ugcs.caltech.edu Ian McKellar imckellar@harvestroad.com.au +Ivo Timmermans itimmermans@bigfoot.com +Jan Krueger max@physics.otago.ac.nz +Jan Niehusmann jan@gondor.com Janusz A. Urbanowicz alex@bofh.torun.pl James Troup james@nocrew.org Jean-loup Gailly gzip@prep.ai.mit.edu +Jeff Long long@kestrel.cc.ukans.edu +Jeffery Von Ronne jronne@ics.uci.edu Jens Bachem bachem@rrz.uni-koeln.de +Jeroen C. van Gelderen jeroen@vangelderen.org J Horacio MG homega@ciberia.es +J. Michael Ashley jashley@acm.org +Jim Bauer jfbauer@home.com +Jim Small cavenewt@my-deja.com Joachim Backes backes@rhrk.uni-kl.de +Joe Rhett jrhett@isite.net John A. Martin jam@jamux.com Johnny Teveßen j.tevessen@gmx.de Jörg Schilling schilling@fokus.gmd.de +Jos Backus Jos.Backus@nl.origin-it.com Jun Kuriyama kuriyama@sky.rim.or.jp +Kahil D. Jallad kdj4@cs.columbia.edu Karl Fogel kfogel@guanabana.onshore.com Karsten Thygesen karthy@kom.auc.dk Katsuhiro Kondou kondou@nec.co.jp Kazu Yamamoto kazu@iijlab.net +Keith Clayton keith@claytons.org +Kevin Ryde user42@zip.com.au +Klaus Singvogel ks@caldera.de +Kurt Garloff garloff@suse.de Lars Kellogg-Stedman lars@bu.edu +L. Sassaman rabbi@quickie.net +M Taylor mctaylor@privacy.nb.ca +Marcel Waldvogel mwa@arl.wustl.edu Marco d'Itri md@linux.it +Marcus Brinkmann Marcus.Brinkmann@ruhr-uni-bochum.de Mark Adler madler@alumni.caltech.edu Mark Elbrecht snowball3@bigfoot.com +Mark Pettit pettit@yahoo-inc.com Markus Friedl Markus.Friedl@informatik.uni-erlangen.de Martin Kahlert martin.kahlert@provi.de Martin Hamilton Martin Schulte schulte@thp.uni-koeln.de +Matt Kraai kraai@alumni.carnegiemellon.edu Matthew Skala mskala@ansuz.sooke.bc.ca +Matthew Wilcox matthew@wil.cx +Matthias Urlichs smurf@noris.de Max Valianskiy maxcom@maxcom.ml.org +Michael Engels michael.engels@uni-duesseldorf.de Michael Fischer v. Mollard mfvm@gmx.de Michael Roth mroth@nessie.de Michael Sobolev mss@despair.transas.com +Michael Tokarev mjt@tls.msk.ru Nicolas Graner Nicolas.Graner@cri.u-psud.fr +Mike McEwan mike@lotusland.demon.co.uk +Neal H Walfield neal@cs.uml.edu NIIBE Yutaka gniibe@chroot.org Niklas Hernaeus Nimrod Zimerman zimerman@forfree.at N J Doye nic@niss.ac.uk Oliver Haakert haakert@hsp.de Oskari Jääskeläinen f33003a@cc.hut.fi +Pascal Scheffers Pascal@scheffers.net Paul D. Smith psmith@baynetworks.com +Per Cederqvist ceder@lysator.liu.se +Phil Blundell pb@debian.org Philippe Laliberte arsphl@oeil.qc.ca +Peter Fales psfales@lucent.com Peter Gutmann pgut001@cs.auckland.ac.nz +Peter Marschall Peter.Marschall@gedos.de +Peter Valchev pvalchev@openbsd.org +Piotr Krukowiecki piotr@pingu.ii.uj.edu.pl QingLong qinglong@bolizm.ihep.su Ralph Gillen gillen@theochem.uni-duesseldorf.de Rat ratinox@peorth.gweep.net @@ -83,33 +158,69 @@ Reinhard Wobst R.Wobst@ifw-dresden.de Rémi Guyomarch rguyom@mail.dotcom.fr Reuben Sumner rasumner@wisdom.weizmann.ac.il Richard Outerbridge outer@interlog.com +Robert Joop rj@rainbow.in-berlin.de Roddy Strachan roddy@satlink.com.au +Roger Sondermann r.so@bigfoot.com Roland Rosenfeld roland@spinnaker.rhein.de +Roman Pavlik rp@tns.cz Ross Golder rossigee@bigfoot.com +Sam Roberts sam@cogent.ca +Sami Tolvanen sami@tolvanen.com +Sean MacLennan seanm@netwinder.org +Sebastian Klemke packet@convergence.de Serge Munhoven munhoven@mema.ucl.ac.be SL Baur steve@xemacs.org +Stefan Bellon sbellon@sbellon.de Stefan Karrmann S.Karrmann@gmx.net Stefan Keller dres@cs.tu-berlin.de Steffen Ullrich ccrlphr@xensei.com Steffen Zahn zahn@berlin.snafu.de Steven Bakker steven@icoe.att.com +Steven Murdoch sjmurdoch@bigfoot.com Susanne Schultz schultz@hsp.de +Ted Cabeen secabeen@pobox.com Thiago Jung Bauermann jungmann@cwb.matrix.com.br Thomas Roessler roessler@guug.de +Tim Mooney mooney@dogbert.cc.ndsu.nodak.edu +Timo Schulz towaday@freakmail.de Tom Spindler dogcow@home.merit.edu Tom Zerucha tzeruch@ceddec.com Tomas Fasth tomas.fasth@twinspot.net +Tommi Komulainen Tommi.Komulainen@iki.fi +Thomas Klausner wiz@danbala.ifoer.tuwien.ac.at +Tomasz Kozlowski tomek@rentec.com Thomas Mikkelsen tbm@image.dk Ulf Möller 3umoelle@informatik.uni-hamburg.de Urko Lusa ulusa@euskalnet.net +Vincent P. Broman broman@spawar.navy.mil +W Lewis wiml@hhhh.org +Walter Hofmann Walter.Hofmann@physik.stud.uni-erlangen.de Walter Koch koch@hsp.de -Werner Koch werner.koch@guug.de +Wayne Chapeskie waynec@spinnaker.com +Werner Koch wk@gnupg.org Wim Vandeputte bunbun@reptile.rug.ac.be +Winona Brown win@huh.org +Yosiaki IIDA iida@ring.gr.jp +Yoshihiro Kajiki kajiki@ylug.org + disastry@saiknes.lv nbecker@hns.com -Thanks to the German Unix User Group for providing FTP space, -Martin Hamilton for initially hosting the mailing list, HSP for -hosting gnupg.org and Linux Laptops Ltd. for a nice toy. +Thanks to the German Unix User Group for sponsoring this project, +Martin Hamilton for hosting the first mailing list and OpenIT for +cheap hosting conditions. + +The development of this software has partly been funded by the German +Ministry for Economics and Technology under grant VIB3-68553.168-001/1999. Many thanks to my wife Gerlinde for having so much patience with me while hacking late in the evening. + + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -264,3 +264,12 @@ Suggested things which I will not do: --> Use a script and --status-fd + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -1,83 +1,124 @@ + * Reword the "Not enough entropy" messages. - * Look at FEATURES packet to decide wether to use MDC. We should - rethink the whole preference implementation and drop that ugly hamehash - stuff. Is it possible to that in getkey? We have to see whether we - realy lookit up by user name or whethre there is a double lookup, - first by userid and then later by keyid - which is bad. + * Do we need a configure test for putenv? - * options.skel wird mit umask von root installiert. + * Check for consistent spelling of user ID, key ID etc. + Replace "user id not found" in getkey.c by "no valid user ID found". + + * Add remarks to the man page about OpenPGP OPTIONAL algorithms and + issue warnings when such an algorithm is used (disabled by expert modus?) - * See how we can handle the symlinks in ./gcrypt + * Return status information even when an imported key is already + stored. This is useful for GPGME's detailed info function. - * Add SIGSEGV handler to overcome zlib problems with truncated data. + * Describe some pitfalls when using EGD. Check that ~/.gnupg/entropy + really is the default. What about needed permission? - * Use --output for keylistings too. + * Using an expired key for signing should give an error message + "expired key" and not "unusable key'. Furthermore the error should + also be thrown when the default key has expired. Reported by + Eric.VanBuggenhaut@AdValvas.be. - * Never allocate packet memory with a m-alloc, but use a specific function. + * pause scrolling help in --edit-key and elsewhere. - * Should we change names like mpi_write in g10/ so that we don't - use the prefix mpi here? + * getkey does not return revoked/expired keys - therefore it is not + possible to override it. - * Implement the AXP syscall to enable bus traps for GLIB 2 + * Selection using +wordlist does not work. + What about adding a feature -word to the +wordlist search mode. - * parse a paramter file to do automatic key generation and to set - parameters for the keygen menu. Far easier than to do a dialog for - each required parameter. + * Check the changes to the gpg random gatherer on all W32 platforms. - * With option -i prompt before adding a key to the keyring and show some - info what we are about to add. + * Put a note into readme.w32 that there is a man page and a options + file; write the registry stuff in regedit format. - * Speed up calculation of key validation. + * Show more info does not work from edit->trust - * --disable-asm should still assemble _udiv_qrnnd when needed + * set default charset from nl_langinfo. + + * Check that no secret temporary results are stored in the result parameter + of the mpi functions. We have already done this for mpi-mul.c + + * We need another special packet at the end of a clearsign message to mark + it's end and allow for multiple signature for one message. And + add a real grammar to the code in mainproc.c + + * Option to warn when a non MDC message is decrypted? + + * If there is no secure memory, allocate more memory for the secure + memory block or do it in all cases. - * Skip RO keyrings when importing a key. + * add some minor things vor VMS. - * Use the newest encryption key if only the main key has been given. + * Use DSA keys with the test suite (partly done) - * replace the keyserver stuff either by a call to a specialized - utility and SOCKSify this utility. + * Fix the bug in the mips assembler code - * Check the beginning of file to detect already compressed files (gzip, - bzip2, xdelta and some picture formats) + * Add a way to show the fingerprint of an key signator's keys - * Delay the read of the passphrase-fd afte a NEED_PASSPHRASE. But this - may break some scripts. + * Add an is_valid flag to each user ID. - * as soon as we have moved to KBX, we can check signatures at all places - because there is no perfomance drawback as we can store the result of - a verification in the KBX. This enable us to better print information on - revoked user IDs and signatures. Well, caching of non-self-signatures - will still be complicated. + * Replace the printing of the user name by [self-signature] when + appropriate so that a key listing does not get clobbered. + + * Concatenated encryption messages don't work corectly - only the + first one is processed. + + * Add option to put the list of recipients (from the encryption + layer) into the signatures notation data. + + * With option -i prompt before adding a key to the keyring and show some + info what we are about to add. + + * --disable-asm should still assemble _udiv_qrnnd when needed + * Get new assembler stuff from gmp 3.1 -Nice to have ------------- - * Official test vectors for 3DES-EDE3 + * Use new-format headers for compressed packets. + The advantage is that a garbled zip files can be better detected. + * use DEL and ^H for erasing the previous character (util/ttyio.c). or better readline. - * Print a warning if the directory mode is wrong. - * Do a real fix for bug #7 or document that it is a PGP 5 error. + * preferences of hash algorithms are not yet used. - * Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal. - or use POSIX.4 realtime signals. Overhaul the interface and the - test program. Use it with the test suite? + * add test cases for invalid data (scrambled armor or other random data) - * add checking of armor trailers - * Burn the buffers used by fopen(), or use read(2). Does this - really make sense? And while we are at it: implement a secure deletion - stuff? + + * add checking of armor trailers. Try to detect garbled header lines. + * the pubkey encrypt functions should do some sanity checks. - * dynload: implement the hint stuff. + * "gpg filename.tar.gz.asc" should work like --verify (-sab). + * for messages created with "-t", it might make sense to append the verification status of the message to the output (i.e. write something to - the --output file and not only to stderr. - * configure option where to find zlib - * Display more validity information about the user IDs at certain places. - We need a more general function to extract such kind of info from the - trustdb. - * Evaluate whether it make sense to replace the namehashs either by - using the user ID directly or by using pointers into the trustdb. - * --gen-prime may trigger a log_bug; should be a log_fatal. + the --output file and not only to stderr. However the problem is + that we consider the message transpatrent and don't have any + indication of the used character set. To implement this feature + we need to make sure that all output is plain 7 bit ascii but + given that we need to print a user name, this does not make sense + at all. The only way this can be implemented is by assuming that + the message is encoded in utf8 and hope tht everyone starts to use + utf8 instead of latin-1 or whatever RSN. Hmmm, I myself should + start with this. + + * keyflags don't distinguish between {certify,signature}-only. + + * Instead of issuing a "signature packet without keyid" gpg should + try to get the keyID from a corresponding one-pass signature + packet (See bug report 817). This is not easy to do as we don't + store the one-pass packets. + + * cat foo | gpg --sign | gpg --list-packets + Does not list the signature packet. + + * Replace wording "It is NOT certain that the key belongs to its owner..." + with "It is NOT certain that the key belongs to the person named in the + user ID..." (or similar but clearer message). + + +Things we won't do +------------------ + + * New option --file-remove path-to-wipe-program ? diff --git a/acconfig.h b/acconfig.h deleted file mode 100644 index 3c1d32e25..000000000 --- a/acconfig.h +++ /dev/null @@ -1,116 +0,0 @@ -/* acconfig.h - used by autoheader to make config.h.in - * Copyright (C) 1998 Free Software Foundation, Inc. - * - * This file is part of GNUPG. - * - * GNUPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GNUPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ -#ifndef GNUPG_CONFIG_H -#define GNUPG_CONFIG_H - -/* need this, because some autoconf tests rely on this (e.g. stpcpy) - * and it should be used for new programs - */ -#define _GNU_SOURCE 1 - -@TOP@ - -#undef M_DEBUG -#undef M_GUARD -#undef VERSION -#undef PACKAGE -#undef PRINTABLE_OS_NAME -#undef IS_DEVELOPMENT_VERSION - -/* Define if your locale.h file contains LC_MESSAGES. */ -#undef HAVE_LC_MESSAGES - -/* Define to 1 if NLS is requested. */ -#undef ENABLE_NLS - -/* Define as 1 if you have catgets and don't want to use GNU gettext. */ -#undef HAVE_CATGETS - -/* Define as 1 if you have gettext and don't want to use GNU gettext. */ -#undef HAVE_GETTEXT - -/* libintl.h is available; this is obsolete because if we don't have - * this header we use a symlink to the one in intl/ */ -#undef HAVE_LIBINTL_H - - -#undef HAVE_STPCPY - -#undef HAVE_MLOCK - - -#undef BIG_ENDIAN_HOST -#undef LITTLE_ENDIAN_HOST - -#undef HAVE_BYTE_TYPEDEF -#undef HAVE_USHORT_TYPEDEF -#undef HAVE_ULONG_TYPEDEF -#undef HAVE_U16_TYPEDEF -#undef HAVE_U32_TYPEDEF - -#undef HAVE_BROKEN_MLOCK - -/* defined if we have a /dev/random and /dev/urandom */ -#undef HAVE_DEV_RANDOM -/* and the real names of the random devices */ -#undef NAME_OF_DEV_RANDOM -#undef NAME_OF_DEV_URANDOM -/* Linux has an ioctl */ -#undef HAVE_DEV_RANDOM_IOCTL -/* see cipher/rndegd.c */ -#undef EGD_SOCKET_NAME - - -#undef USE_DYNAMIC_LINKING -#undef HAVE_DL_DLOPEN -#undef HAVE_DL_SHL_LOAD -#undef HAVE_DLD_DLD_LINK - -#undef USE_SHM_COPROCESSING - -#undef IPC_HAVE_SHM_LOCK -#undef IPC_RMID_DEFERRED_RELEASE - -/* set this to limit filenames to the 8.3 format */ -#undef USE_ONLY_8DOT3 -/* defined if we must run on a stupid file system */ -#undef HAVE_DRIVE_LETTERS -/* defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) - * with special properties like no file modes */ -#undef HAVE_DOSISH_SYSTEM -/* because the Unix gettext has to much overhead on MingW32 systems - * and these systems lack Posix functions, we use a simplified version - * of gettext */ -#undef USE_SIMPLE_GETTEXT -/* At some point in the system we need to know that we use the Windows - * random module. */ -#undef USE_STATIC_RNDW32 - -#undef USE_CAPABILITIES - -/* Some systems have mkdir that takes a single argument. */ -#undef MKDIR_TAKES_ONE_ARG - - -@BOTTOM@ - -#include "gnupg-defs.h" - -#endif /*GNUPG_CONFIG_H*/ diff --git a/acinclude.m4 b/acinclude.m4 index 9dce2486b..4a2c91672 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1,5 +1,21 @@ -dnl macros to configure g10 - +dnl macros to configure gnupg +dnl Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +dnl +dnl This file is part of GnuPG. +dnl +dnl GnuPG is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl GnuPG is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA dnl GNUPG_MSG_PRINT(STRING) dnl print a message @@ -15,37 +31,15 @@ dnl AC_DEFUN(GNUPG_CHECK_TYPEDEF, [ AC_MSG_CHECKING(for $1 typedef) AC_CACHE_VAL(gnupg_cv_typedef_$1, - [AC_TRY_COMPILE([#include <stdlib.h> + [AC_TRY_COMPILE([#define _GNU_SOURCE 1 + #include <stdlib.h> #include <sys/types.h>], [ #undef $1 int a = sizeof($1); ], gnupg_cv_typedef_$1=yes, gnupg_cv_typedef_$1=no )]) AC_MSG_RESULT($gnupg_cv_typedef_$1) if test "$gnupg_cv_typedef_$1" = yes; then - AC_DEFINE($2) - fi - ]) - - -dnl GNUPG_FIX_HDR_VERSION(FILE, NAME) -dnl Make the version number in gcrypt/gcrypt.h the same as the one here. -dnl (this is easier than to have a .in file just for one substitution) -dnl -AC_DEFUN(GNUPG_FIX_HDR_VERSION, - [ sed "s/^#define $2 \".*/#define $2 \"$VERSION\"/" $srcdir/$1 > $srcdir/$1.tmp - if cmp -s $srcdir/$1 $srcdir/$1.tmp 2>/dev/null; then - rm -f $srcdir/$1.tmp - else - rm -f $srcdir/$1 - if mv $srcdir/$1.tmp $srcdir/$1 ; then - : - else - AC_MSG_ERROR([[ -*** Failed to fix the version string macro $2 in $1. -*** The old file has been saved as $1.tmp - ]]) - fi - AC_MSG_WARN([fixed the $2 macro in $1]) + AC_DEFINE($2,1,[Defined if a `]$1[' is typedef'd]) fi ]) @@ -53,7 +47,7 @@ AC_DEFUN(GNUPG_FIX_HDR_VERSION, dnl GNUPG_CHECK_GNUMAKE dnl AC_DEFUN(GNUPG_CHECK_GNUMAKE, - [ + [ if ${MAKE-make} --version 2>/dev/null | grep '^GNU ' >/dev/null 2>&1; then : else @@ -67,6 +61,7 @@ AC_DEFUN(GNUPG_CHECK_GNUMAKE, fi ]) + dnl GNUPG_CHECK_FAQPROG dnl AC_DEFUN(GNUPG_CHECK_FAQPROG, @@ -82,39 +77,33 @@ AC_DEFUN(GNUPG_CHECK_FAQPROG, AC_SUBST(FAQPROG) AM_CONDITIONAL(WORKING_FAQPROG, test "$working_faqprog" = "yes" ) - if test $working_faqprog = no; then - AC_MSG_WARN([[ -*** -*** It seems that the faqprog.pl program is not installed. -*** Unless you do not change the source of the FAQs it is not required. -*** The working version of this utility should be available at: -*** ftp://ftp.gnupg.org/pub/gcrypt/contrib/faqprog.pl -***]]) - fi - ]) - - - -dnl GNUPG_LINK_FILES( SRC, DEST ) -dnl same as AC_LINK_FILES, but collect the files to link in -dnl some special variables and do the link -dnl when GNUPG_DO_LINK_FILES is called -dnl This is a workaround for AC_LINK_FILES, because it does not work -dnl correct when using a caching scheme +dnl if test $working_faqprog = no; then +dnl AC_MSG_WARN([[ +dnl *** +dnl *** It seems that the faqprog.pl program is not installed; +dnl *** however it is only needed if you want to change the FAQ. +dnl *** (faqprog.pl should be available at: +dnl *** ftp://ftp.gnupg.org/pub/gcrypt/contrib/faqprog.pl ) +dnl *** No need to worry about this warning. +dnl ***]]) +dnl fi + ]) + +dnl GNUPG_CHECK_DOCBOOK_TO_TEXI dnl -define(GNUPG_LINK_FILES, - [ if test "x$wk_link_files_src" = "x"; then - wk_link_files_src="$1" - wk_link_files_dst="$2" - else - wk_link_files_src="$wk_link_files_src $1" - wk_link_files_dst="$wk_link_files_dst $2" +AC_DEFUN(GNUPG_CHECK_DOCBOOK_TO_TEXI, + [ + AC_CHECK_PROG(DOCBOOK_TO_TEXI, docbook2texi, yes, no) + AC_MSG_CHECKING(for sgml to texi tools) + working_sgmltotexi=no + if test "$ac_cv_prog_DOCBOOK_TO_TEXI" = yes; then + if sgml2xml -v /dev/null 2>&1 | grep 'SP version' >/dev/null 2>&1 ; then + working_sgmltotexi=yes + fi fi - ]) -define(GNUPG_DO_LINK_FILES, - [ AC_LINK_FILES( $wk_link_files_src, $wk_link_files_dst ) - ]) - + AC_MSG_RESULT($working_sgmltotexi) + AM_CONDITIONAL(HAVE_DOCBOOK_TO_TEXI, test "$working_sgmltotexi" = "yes" ) + ]) @@ -158,9 +147,11 @@ define(GNUPG_CHECK_ENDIAN, ]) AC_MSG_RESULT([$gnupg_cv_c_endian]) if test "$gnupg_cv_c_endian" = little; then - AC_DEFINE(LITTLE_ENDIAN_HOST) + AC_DEFINE(LITTLE_ENDIAN_HOST,1, + [Defined if the host has little endian byte ordering]) else - AC_DEFINE(BIG_ENDIAN_HOST) + AC_DEFINE(BIG_ENDIAN_HOST,1, + [Defined if the host has big endian byte ordering]) fi ]) @@ -328,7 +319,8 @@ define(GNUPG_CHECK_IPC, gnupg_cv_ipc_rmid_deferred_release="assume-no") ) if test "$gnupg_cv_ipc_rmid_deferred_release" = "yes"; then - AC_DEFINE(IPC_RMID_DEFERRED_RELEASE) + AC_DEFINE(IPC_RMID_DEFERRED_RELEASE,1, + [Defined if we can do a deferred shm release]) AC_MSG_RESULT(yes) else if test "$gnupg_cv_ipc_rmid_deferred_release" = "no"; then @@ -351,7 +343,8 @@ define(GNUPG_CHECK_IPC, ) ) if test "$gnupg_cv_ipc_have_shm_lock" = "yes"; then - AC_DEFINE(IPC_HAVE_SHM_LOCK) + AC_DEFINE(IPC_HAVE_SHM_LOCK,1, + [Defined if a SysV shared memory supports the LOCK flag]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) @@ -384,7 +377,7 @@ define(GNUPG_CHECK_MLOCK, #endif ], [ int i; - + /* glibc defines this for functions which it implements * to always fail with ENOSYS. Some functions are actually * named something starting with __ and the normal name @@ -399,7 +392,8 @@ define(GNUPG_CHECK_MLOCK, gnupg_cv_mlock_is_in_sys_mman=yes, gnupg_cv_mlock_is_in_sys_mman=no)]) if test "$gnupg_cv_mlock_is_in_sys_mman" = "yes"; then - AC_DEFINE(HAVE_MLOCK) + AC_DEFINE(HAVE_MLOCK,1, + [Defined if the system supports an mlock() call]) fi fi fi @@ -439,8 +433,10 @@ define(GNUPG_CHECK_MLOCK, ) ) if test "$gnupg_cv_have_broken_mlock" = "yes"; then - AC_DEFINE(HAVE_BROKEN_MLOCK) + AC_DEFINE(HAVE_BROKEN_MLOCK,1, + [Defined if the mlock() call does not work]) AC_MSG_RESULT(yes) + AC_CHECK_FUNCS(plock) else if test "$gnupg_cv_have_broken_mlock" = "no"; then AC_MSG_RESULT(no) @@ -452,10 +448,8 @@ define(GNUPG_CHECK_MLOCK, ]) - ################################################################ # GNUPG_PROG_NM - find the path to a BSD-compatible name lister -################################################################ AC_DEFUN(GNUPG_PROG_NM, [AC_MSG_CHECKING([for BSD-compatible nm]) AC_CACHE_VAL(ac_cv_path_NM, @@ -667,7 +661,7 @@ AC_CHECK_TOOL(AS, as, false) AC_DEFUN(GNUPG_SYS_SYMBOL_UNDERSCORE, [tmp_do_check="no" case "${target}" in - i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp) + i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp | *-*-cygwin) ac_cv_sys_symbol_underscore=yes ;; *) @@ -718,7 +712,7 @@ fi AC_MSG_RESULT($ac_cv_sys_symbol_underscore) if test x$ac_cv_sys_symbol_underscore = xyes; then AC_DEFINE(WITH_SYMBOL_UNDERSCORE,1, - [define if compiled symbols have a leading underscore]) + [Defined if compiled symbols have a leading underscore]) fi ]) @@ -741,119 +735,8 @@ AC_CACHE_CHECK([if mkdir takes one argument], gnupg_cv_mkdir_takes_one_arg, #endif], [mkdir ("foo", 0);], gnupg_cv_mkdir_takes_one_arg=no, gnupg_cv_mkdir_takes_one_arg=yes)]) if test $gnupg_cv_mkdir_takes_one_arg = yes ; then - AC_DEFINE(MKDIR_TAKES_ONE_ARG) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,1, + [Defined if mkdir() does not take permission flags]) fi ]) -dnl GPH_PROG_DOCBOOK() -dnl Check whether we have the needed Docbook environment -dnl and issue a warning if this is not the case. -dnl -dnl This test defines these variables for substitution: -dnl DB2HTML - command used to convert Docbook to HTML -dnl DB2TEX - command used to convert Docbook to TeX -dnl DB2MAN - command used to convert Docbook to man pages -dnl JADE - command to invoke jade -dnl JADETEX - command to invoke jadetex -dnl DSL_FOR_HTML - the stylesheet used to for the Docbook->HTML conversion -dnl The following make conditionals are defined -dnl HAVE_DB2MAN - defined when db2man is available -dnl HAVE_DB2TEX - defined when db2tex is available -dnl HAVE_DB2HTML - defined when db2html is available -dnl HAVE_DOCBOOK - defined when the entire Docbook environment is present -dnl HAVE_JADE - defined when jade is installed -dnl HAVE_JADETEX - defined when jadetex is installed -dnl -dnl (wk 2000-02-17) -dnl -AC_DEFUN(GPH_PROG_DOCBOOK, - [ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl - all=yes - AC_PATH_PROG(DB2MAN, docbook-to-man, no) - test "$DB2MAN" = no && all=no - AM_CONDITIONAL(HAVE_DB2MAN, test "$DB2MAN" != no ) - - AC_PATH_PROG(JADE, jade, no) - test "$JADE" = no && all=no - AM_CONDITIONAL(HAVE_JADE, test "$JADE" != no ) - - AC_PATH_PROG(JADETEX, jadetex, no) - test "$JADETEX" = no && all=no - AM_CONDITIONAL(HAVE_JADETEX, test "$JADETEX" != no ) - - stylesheet_dirs=' -/usr/local/lib/dsssl/stylesheets/docbook -/usr/local/share/dsssl/stylesheets/docbook -/usr/local/lib/sgml/stylesheet/dsssl/docbook/nwalsh -/usr/local/share/sgml/stylesheet/dsssl/docbook/nwalsh -/usr/lib/dsssl/stylesheets/docbook -/usr/share/dsssl/stylesheets/docbook -/usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh -/usr/share/sgml/stylesheet/dsssl/docbook/nwalsh -' - - AC_MSG_CHECKING(for TeX stylesheet) - dsl=none - for d in ${stylesheet_dirs}; do - file=${d}/print/docbook.dsl - if test -f $file; then - dsl=$file - break - fi - done - AC_MSG_RESULT([$dsl]) - okay=no - if test $dsl = none ; then - DB2TEX="$missing_dir/missing db2tex" - all=no - else - DB2TEX="$JADE -t tex -i tex -d $dsl" - okay=yes - fi - AC_SUBST(DB2TEX) - AM_CONDITIONAL(HAVE_DB2TEX, test $okay = yes ) - - if ( $ac_aux_dir/db2html.in --version) < /dev/null > /dev/null 2>&1; then - : - else - AC_ERROR([needed $ac_aux_dir/db2html.in not found]) - fi - - AC_MSG_CHECKING(for HTML stylesheet) - DSL_FOR_HTML="none" - for d in ${stylesheet_dirs}; do - file=${d}/html/docbook.dsl - if test -f $file; then - DSL_FOR_HTML=$file - break - fi - done - AC_MSG_RESULT([$DSL_FOR_HTML]) - okay=no - if test $DSL_FOR_HTML = none ; then - DB2HTML="$missing_dir/missing db2html" - all=no - else - DB2HTML="`cd $ac_aux_dir && pwd`/db2html --copyfiles" - okay=yes - fi - AC_SUBST(DB2HTML) - AC_SUBST(DSL_FOR_HTML) - AM_CONDITIONAL(HAVE_DB2HTML, test $okay = yes ) - - AM_CONDITIONAL(HAVE_DOCBOOK, test "$all" != yes ) - if test $all = no ; then - AC_MSG_WARN([[ -*** -*** It seems that the Docbook environment is not installed as required. -*** We will try to build everything, but if you either touch some files -*** or use a bogus make tool, you may run into problems. -*** Docbook is normally only needed to build the documentation. -***]]) - fi - ]) - - - - -dnl *-*wedit:notab*-* Please keep this as the last line. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..41ae4e272 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +autogen_sh="`dirname $0`/scripts/autogen.sh" +exec $autogen_sh $* + diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..e3f2e3304 --- /dev/null +++ b/configure.ac @@ -0,0 +1,994 @@ +dnl Configure.ac script for GnuPG +dnl Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +dnl +dnl This file is part of GnuPG. +dnl +dnl GnuPG is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl GnuPG is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA +dnl +dnl (Process this file with autoconf to produce a configure script.) +dnlAC_REVISION($Revision$)dnl + +AC_PREREQ(2.52) +AC_INIT(gnupg, 1.1.90, bug-gnupg@gnu.org) +ALL_LINGUAS="cs da de eo el es et fr gl id it ja nl pl pt_BR pt sv tr" +static_modules="sha1 md5 rmd160" +static_random_module="" + +PACKAGE=$PACKAGE_NAME +VERSION=$PACKAGE_VERSION + +AC_CONFIG_AUX_DIR(scripts) +AC_CONFIG_SRCDIR(g10/g10.c) +AC_CANONICAL_TARGET() +AM_INIT_AUTOMAKE($PACKAGE, $VERSION) +AM_CONFIG_HEADER(config.h) + +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) +AC_DEFINE(_GNU_SOURCE,1,[Some tests rely on this (stpcpy) and it should be used for new programs anyway]) + +AC_PROG_AWK + +MODULES_IN_CIPHER=`$AWK '/^EXTRA_PROGRAMS/ { for(i=3;i<=NF;i++) print $i}' \ + $srcdir/cipher/Makefile.am` + +dnl +dnl Check for random module options +dnl +dnl Fixme: get the list of available modules from MODULES_IN_CIPHER +dnl and check against this list + +AC_MSG_CHECKING([which static random module to use]) +AC_ARG_ENABLE(static-rnd, + [ --enable-static-rnd=[egd|unix|linux|none] ], +[use_static_rnd=$enableval], [use_static_rnd=default] ) + +if test "$use_static_rnd" = no; then + use_static_rnd=default +fi + +case "$use_static_rnd" in + egd | linux | unix | none | default ) + AC_MSG_RESULT($use_static_rnd) + ;; + * ) + AC_MSG_RESULT(invalid argument) + AC_MSG_ERROR(there is no random module rnd$use_static_rnd) + ;; +esac + +AC_ARG_WITH(egd-socket, + [ --with-egd-socket=NAME Use NAME for the EGD socket)], + egd_socket_name="$withval", egd_socket_name="" ) +AC_DEFINE_UNQUOTED(EGD_SOCKET_NAME, "$egd_socket_name", + [Define if you don't want the default EGD socket name. + For details see cipher/rndegd.c]) + + +dnl +dnl See whether the user wants to disable checking for /dev/random + +AC_MSG_CHECKING([whether use of /dev/random is requested]) +AC_ARG_ENABLE(dev-random, +[ --disable-dev-random disable the use of dev random], + try_dev_random=$enableval, try_dev_random=yes) +AC_MSG_RESULT($try_dev_random) + + +dnl +dnl Check other options +dnl + +AC_MSG_CHECKING([whether use of extensions is requested]) +AC_ARG_ENABLE(dynload, +[ --disable-dynload disable use of extensions], + try_dynload=$enableval, try_dynload=yes) +AC_MSG_RESULT($try_dynload) + +AC_MSG_CHECKING([whether assembler modules are requested]) +AC_ARG_ENABLE(asm, +[ --disable-asm do not use assembler modules], + try_asm_modules=$enableval, try_asm_modules=yes) +AC_MSG_RESULT($try_asm_modules) + +AC_MSG_CHECKING([whether memory guard is requested]) +AC_ARG_ENABLE(m-guard, + [ --enable-m-guard enable memory guard facility], + use_m_guard=$enableval, use_m_guard=no) +AC_MSG_RESULT($use_m_guard) +if test "$use_m_guard" = yes ; then + AC_DEFINE(M_GUARD,1,[Define to use the (obsolete) malloc guarding feature]) +fi + +AC_MSG_CHECKING([whether to enable external program execution]) +AC_ARG_ENABLE(exec, + [ --disable-exec disable external program execution], + use_exec=$enableval, use_exec=yes) +AC_MSG_RESULT($use_exec) +if test "$use_exec" = no ; then + AC_DEFINE(NO_EXEC,1,[Define to disable external program execution]) +fi + +if test "$use_exec" = yes ; then + AC_MSG_CHECKING([whether LDAP keyserver support is requested]) + AC_ARG_ENABLE(ldap, + [ --disable-ldap disable LDAP keyserver interface], + try_ldap=$enableval, try_ldap=yes) + AC_MSG_RESULT($try_ldap) + + AC_MSG_CHECKING([whether experimental external hkp keyserver support is requested]) + AC_ARG_ENABLE(external-hkp, + [ --enable-external-hkp enable experimental external HKP keyserver interface], + try_hkp=$enableval, try_hkp=no) + AC_MSG_RESULT($try_hkp) + + if test "$try_hkp" = yes ; then + GPGKEYS_HKP="gpgkeys_hkp" + AC_DEFINE(USE_EXTERNAL_HKP,1,[define to use the experimental external HKP keyserver interface]) + fi + + AC_MSG_CHECKING([whether email keyserver support is requested]) + AC_ARG_ENABLE(mailto, + [ --disable-mailto disable email keyserver interface], + try_mailto=$enableval, try_mailto=yes) + AC_MSG_RESULT($try_mailto) +fi + +AC_MSG_CHECKING([whether included zlib is requested]) +AC_ARG_WITH(included-zlib, + [ --with-included-zlib use the zlib code included here], +[g10_force_zlib=yes], [g10_force_zlib=no] ) +AC_MSG_RESULT($g10_force_zlib) + + +dnl +dnl Check whether we want to use Linux capabilities +dnl +AC_MSG_CHECKING([whether use of capabilities is requested]) +AC_ARG_WITH(capabilities, + [ --with-capabilities use linux capabilities [default=no]], +[use_capabilities="$withval"],[use_capabilities=no]) +AC_MSG_RESULT($use_capabilities) + + +AH_BOTTOM([ +#if !(defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)) +#define EXEC_TEMPFILE_ONLY +#endif + +#include "g10defs.h" +]) + + +AM_MAINTAINER_MODE + +dnl Checks for programs. + +dnl +dnl Setup some stuff depending on host/target. +dnl +case "${target}" in + *-*-mingw32*) + disallowed_modules="rndunix rndlinux rndegd" + ;; + *-*-cygwin*) + disallowed_modules="rndunix rndlinux rndegd tiger" + ;; + *) + disallowed_modules="rndw32" + ;; +esac + +AC_PROG_MAKE_SET +AM_SANITY_CHECK +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_PROG_CC +AC_PROG_CPP +AC_PATH_PROG(PERL,"perl") +AC_ISC_POSIX +AC_SYS_LARGEFILE +AC_PROG_INSTALL +AC_PROG_AWK +AC_CHECK_PROG(DOCBOOK_TO_MAN, docbook-to-man, yes, no) +AM_CONDITIONAL(HAVE_DOCBOOK_TO_MAN, test "$ac_cv_prog_DOCBOOK_TO_MAN" = yes) +GNUPG_CHECK_FAQPROG +GNUPG_CHECK_DOCBOOK_TO_TEXI + +MPI_OPT_FLAGS="" + + +try_gettext=yes +case "${target}" in + *-*-mingw32*|*-*-cygwin*) + # special stuff for Windoze NT + ac_cv_have_dev_random=no + AC_DEFINE(USE_ONLY_8DOT3,1, + [set this to limit filenames to the 8.3 format]) + AC_DEFINE(HAVE_DRIVE_LETTERS,1, + [defined if we must run on a stupid file system]) + AC_DEFINE(HAVE_DOSISH_SYSTEM,1, + [defined if we run on some of the PCDOS like systems + (DOS, Windoze. OS/2) with special properties like + no file modes]) + AC_DEFINE(USE_SIMPLE_GETTEXT,1, + [because the Unix gettext has too much overhead on + MingW32 systems and these systems lack Posix functions, + we use a simplified version of gettext]) + try_gettext="no" + ;; + i?86-emx-os2 | i?86-*-os2*emx ) + # OS/2 with the EMX environment + ac_cv_have_dev_random=no + AC_DEFINE(HAVE_DRIVE_LETTERS) + AC_DEFINE(HAVE_DOSISH_SYSTEM) + try_gettext="no" + ;; + + i?86-*-msdosdjgpp*) + # DOS with the DJGPP environment + ac_cv_have_dev_random=no + AC_DEFINE(HAVE_DRIVE_LETTERS) + AC_DEFINE(HAVE_DOSISH_SYSTEM) + try_gettext="no" + ;; + + *-*-freebsd*) + # FreeBSD + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + ;; + + *-*-hpux*) + if test -z "$GCC" ; then + CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" + fi + ;; + *-dec-osf4*) + if test -z "$GCC" ; then + # Suppress all warnings + # to get rid of the unsigned/signed char mismatch warnings. + CFLAGS="$CFLAGS -w" + fi + ;; + *-dec-osf5*) + if test -z "$GCC" ; then + # Use the newer compiler `-msg_disable ptrmismatch' to + # get rid of the unsigned/signed char mismatch warnings. + # Using this may hide other pointer mismatch warnings, but + # it at least lets other warning classes through + CFLAGS="$CFLAGS -msg_disable ptrmismatch" + fi + ;; + m68k-atari-mint) + ;; + *) + ;; +esac + +AC_SUBST(MPI_OPT_FLAGS) +GNUPG_SYS_SYMBOL_UNDERSCORE +GNUPG_CHECK_PIC +GNUPG_CHECK_EXPORTDYNAMIC +if test "$NO_PIC" = yes; then + try_dynload=no +fi + +dnl Must check for network library requirements before doing link tests +dnl for ldap, for example. If ldap libs are static (or dynamic and without +dnl ELF runtime link paths), then link will fail and LDAP support won't +dnl be detected. + +AC_CHECK_FUNC(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname, + [NETLIBS="-lnsl $NETLIBS"])) +AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt, + [NETLIBS="-lsocket $NETLIBS"])) + +# Try and link a LDAP test program to weed out unusable LDAP +# libraries. -lldap -llber -lresolv is for OpenLDAP. -lldapssl41 is +# for Mozilla LDAP. + +if test "$try_ldap" = yes ; then + for LDAPLIBS in "-lldap -llber -lresolv" "-lldapssl41"; do + _ldap_save_libs=$LIBS + LIBS="$LDAPLIBS $NETLIBS $LIBS" + + AC_MSG_CHECKING([whether LDAP via \"$LDAPLIBS\" is present and sane]) + AC_TRY_LINK([#include <ldap.h>],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldap_init=yes],[gnupg_cv_func_ldap_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldap_init]) + + if test $gnupg_cv_func_ldap_init = no; then + AC_MSG_CHECKING([whether I can make LDAP be sane with lber.h]) + AC_TRY_LINK([#include <lber.h> +#include <ldap.h>],[ldap_open("foobar",1234);], + [gnupg_cv_func_ldaplber_init=yes],[gnupg_cv_func_ldaplber_init=no]) + AC_MSG_RESULT([$gnupg_cv_func_ldaplber_init]) + fi + + if test "$gnupg_cv_func_ldaplber_init" = yes ; then + AC_DEFINE(NEED_LBER_H,1,[Define if the LDAP library requires including lber.h before ldap.h]) + fi + + if test "$gnupg_cv_func_ldap_init" = yes || \ + test "$gnupg_cv_func_ldaplber_init" = yes ; then + GPGKEYS_LDAP="gpgkeys_ldap" + fi + + LIBS=$_ldap_save_libs + + if test "$GPGKEYS_LDAP" != "" ; then break; fi + done +fi + +AC_SUBST(GPGKEYS_LDAP) +AC_SUBST(LDAPLIBS) + +if test "$try_mailto" = yes ; then + AC_PATH_PROG(SENDMAIL,sendmail,,$PATH:/usr/sbin:/usr/libexec:/usr/lib) + + if test "$ac_cv_path_SENDMAIL" ; then + GPGKEYS_MAILTO="gpgkeys_mailto" + fi + fi +AC_SUBST(GPGKEYS_MAILTO) + +AC_SUBST(GPGKEYS_HKP) + +case "${target}" in + *-*-mingw32*) + PRINTABLE_OS_NAME="MingW32" + ;; + *-*-cygwin*) + PRINTABLE_OS_NAME="Cygwin32" + ;; + i?86-emx-os2 | i?86-*-os2*emx ) + PRINTABLE_OS_NAME="OS/2" + ;; + i?86-*-msdosdjgpp*) + PRINTABLE_OS_NAME="MSDOS/DJGPP" + try_dynload=no + ;; + *-linux*) + PRINTABLE_OS_NAME="GNU/Linux" + ;; +dnl let that after linux to avoid gnu-linux problems + *-gnu*) + PRINTABLE_OS_NAME="GNU/Hurd" + ;; + *) + PRINTABLE_OS_NAME=`uname -s || echo "Unknown"` + ;; +esac +AC_DEFINE_UNQUOTED(PRINTABLE_OS_NAME, "$PRINTABLE_OS_NAME", + [A human readable text with the name of the OS]) + + +# +# 1. Set flags to be used for the extension modules +# 2. Set names of random devices +# +NAME_OF_DEV_RANDOM="/dev/random" +NAME_OF_DEV_URANDOM="/dev/urandom" +case "${target}" in + *-openbsd* | *-netbsd*) + NAME_OF_DEV_RANDOM="/dev/srandom" + NAME_OF_DEV_URANDOM="/dev/urandom" + DYNLINK_MOD_CFLAGS="-shared -rdynamic $CFLAGS_PIC -Wl,-Bshareable -Wl,-x" + ;; + + hpux*) + # if using the vendor (ANSI) compiler, arrange to have `-b' passed + # to the linker. If using gcc, it supports `-shared' to do the same. + if test -n "$GCC" ; then + DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" + else + DYNLINK_MOD_CFLAGS='-Wl,-b' + fi + ;; + + *-irix6.5*) + # Irix 6.5 (and probably a lot earlier, but I only still have + # access to 6.5.x) doesn't require any additional flags, as `-KPIC' + # is the default. Also, `-shared' works with the vendor compiler + DYNLINK_MOD_CFLAGS="-shared" + ;; + + alpha*-dec-osf*) + # osf (i.e. OSF/1, Digital UNIX, or Tru64 UNIX, pick any one...) + # on alpha doesn't require any PIC flags, everything is PIC. + # This may not be the case for osf ports to other machines, so + # hence the more specific match for target. + # + # Also, `-shared' works with the vendor compiler or gcc. + # -expect_unresolved turns off warnings about unresolved symbols. + DYNLINK_MOD_CFLAGS='-shared -Wl,-expect_unresolved,\*' + ;; + + *-solaris*) + # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. + if test -n "$GCC" ; then + DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" + else + DYNLINK_MOD_CFLAGS="-G $CFLAGS_PIC" + fi + ;; + + *-irix* | *-dec-osf* ) + DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" + ;; + + *) + # -shared is a gcc-ism. Find pic flags from GNUPG_CHECK_PIC. + if test -n "$GCC" ; then + DYNLINK_MOD_CFLAGS="-shared $CFLAGS_PIC" + else + DYNLINK_MOD_CFLAGS="$CFLAGS_PIC" + fi + ;; +esac +AC_DEFINE_UNQUOTED(NAME_OF_DEV_RANDOM, "$NAME_OF_DEV_RANDOM", + [defined to the name of the strong random device]) +AC_DEFINE_UNQUOTED(NAME_OF_DEV_URANDOM, "$NAME_OF_DEV_URANDOM", + [defined to the name of the weaker random device]) +AC_SUBST(MPI_OPT_FLAGS) + + +dnl Checks for libraries. + +if test "$try_gettext" = yes; then +AM_GNU_GETTEXT +else +USE_NLS=no +USE_INCLUDED_LIBINTL=no +BUILD_INCLUDED_LIBINTL=no +AC_SUBST(USE_NLS) +AC_SUBST(USE_INCLUDED_LIBINTL) +AC_SUBST(BUILD_INCLUDED_LIBINTL) +fi + + +if test "$try_dynload" = yes ; then + AC_CHECK_LIB(dl,dlopen) + if test "$ac_cv_lib_dl_dlopen" = "yes"; then + AC_DEFINE(USE_DYNAMIC_LINKING,1, + [define to enable the use of extensions]) + AC_DEFINE(HAVE_DL_DLOPEN,1, + [Defined when the dlopen function family is available]) + DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" + use_gnupg_extensions=yes + else + AC_CHECK_FUNCS(dlopen) + if test "$ac_cv_func_dlopen" = "yes"; then + AC_DEFINE(USE_DYNAMIC_LINKING) + AC_DEFINE(HAVE_DL_DLOPEN) + DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" + use_gnupg_extensions=yes + else + AC_CHECK_LIB(dld,shl_load) + if test "$ac_cv_lib_dld_shl_load" = "yes"; then + AC_DEFINE(USE_DYNAMIC_LINKING) + AC_DEFINE(HAVE_DL_SHL_LOAD,1, + [Defined if the shl_load function family is available]) + DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" + use_gnupg_extensions=yes +dnl ----------------- +dnl DLD is not ready for use. So I better disable this test +dnl +dnl AC_CHECK_LIB(dld,dld_link) +dnl if test "$ac_cv_lib_dld_dld_link" = "yes"; then +dnl AC_DEFINE(USE_DYNAMIC_LINKING) +dnl AC_DEFINE(HAVE_DLD_DLD_LINK) +dnl DYNLINK_LDFLAGS="$CFLAGS_EXPORTDYNAMIC" +dnl use_gnupg_extensions=yes +dnl --------------- + fi + fi + fi +else + AC_MSG_CHECKING(for dynamic loading) + DYNLINK_LDFLAGS= + DYNLINK_MOD_CFLAGS= + use_gnupg_extensions=no + AC_MSG_RESULT(has been disabled) +fi + +AM_CONDITIONAL(ENABLE_GNUPG_EXTENSIONS, test "$use_gnupg_extensions" = yes ) +AC_SUBST(DYNLINK_LDFLAGS) +AC_SUBST(DYNLINK_MOD_CFLAGS) + + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(unistd.h langinfo.h termio.h locale.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_TYPE_SIGNAL +AC_DECL_SYS_SIGLIST + +GNUPG_CHECK_ENDIAN + + +GNUPG_CHECK_TYPEDEF(byte, HAVE_BYTE_TYPEDEF) +GNUPG_CHECK_TYPEDEF(ushort, HAVE_USHORT_TYPEDEF) +GNUPG_CHECK_TYPEDEF(ulong, HAVE_ULONG_TYPEDEF) +GNUPG_CHECK_TYPEDEF(u16, HAVE_U16_TYPEDEF) +GNUPG_CHECK_TYPEDEF(u32, HAVE_U32_TYPEDEF) + +AC_CHECK_SIZEOF(unsigned short, 2) +AC_CHECK_SIZEOF(unsigned int, 4) +AC_CHECK_SIZEOF(unsigned long, 4) +AC_CHECK_SIZEOF(unsigned long long, 0) + +if test "$ac_cv_sizeof_unsigned_short" = "0" \ + || test "$ac_cv_sizeof_unsigned_int" = "0" \ + || test "$ac_cv_sizeof_unsigned_long" = "0"; then + AC_MSG_WARN([Hmmm, something is wrong with the sizes - using defaults]); +fi + +dnl Checks for library functions. +AC_FUNC_FSEEKO +AC_FUNC_VPRINTF +AC_FUNC_FORK +AC_CHECK_FUNCS(strerror stpcpy strsep strlwr tcgetattr strtoul mmap) +AC_CHECK_FUNCS(strcasecmp strncasecmp) +AC_CHECK_FUNCS(memmove gettimeofday getrusage setrlimit clock_gettime) +AC_CHECK_FUNCS(atexit raise getpagesize strftime nl_langinfo setlocale) +AC_CHECK_FUNCS(waitpid wait4 sigaction sigprocmask rand pipe stat) +AC_REPLACE_FUNCS(mkdtemp) + +# +# check for gethrtime and run a testprogram to see whether +# it is broken. It has been reported that some Solaris and HP UX systems +# raise an SIGILL +# +AC_CACHE_CHECK([for gethrtime], + [gnupg_cv_func_gethrtime], + [AC_TRY_LINK([#include <sys/times.h>],[ + hrtime_t tv; + tv = gethrtime(); + ], + [gnupg_cv_func_gethrtime=yes], + [gnupg_cv_func_gethrtime=no]) + ]) +if test $gnupg_cv_func_gethrtime = yes; then + AC_DEFINE([HAVE_GETHRTIME], 1, + [Define if you have the `gethrtime(2)' function.]) + AC_CACHE_CHECK([whether gethrtime is broken], + [gnupg_cv_func_broken_gethrtime], + [AC_TRY_RUN([ + #include <sys/times.h> + int main () { + hrtime_t tv; + tv = gethrtime(); + } + ], + [gnupg_cv_func_broken_gethrtime=no], + [gnupg_cv_func_broken_gethrtime=yes], + [gnupg_cv_func_broken_gethrtime=assume-no]) + ]) + if test $gnupg_cv_func_broken_gethrtime = yes; then + AC_DEFINE([HAVE_BROKEN_GETHRTIME], 1, + [Define if `gethrtime(2)' does not work correctly i.e. issues a SIGILL.]) + fi +fi + + +GNUPG_CHECK_MLOCK +GNUPG_FUNC_MKDIR_TAKES_ONE_ARG + +dnl +dnl Check whether we can use Linux capabilities as requested +dnl +if test "$use_capabilities" = "yes" ; then +use_capabilities=no +AC_CHECK_HEADERS(sys/capability.h) +if test "$ac_cv_header_sys_capability_h" = "yes" ; then + AC_CHECK_LIB(cap, cap_init, ac_need_libcap=1) + if test "$ac_cv_lib_cap_cap_init" = "yes"; then + AC_DEFINE(USE_CAPABILITIES,1, + [define if capabilities should be used]) + LIBS="$LIBS -lcap" + use_capabilities=yes + fi +fi +if test "$use_capabilities" = "no" ; then + AC_MSG_WARN([[ +*** +*** The use of capabilities on this system is not possible. +*** You need a recent Linux kernel and some patches: +*** fcaps-2.2.9-990610.patch (kernel patch for 2.2.9) +*** fcap-module-990613.tar.gz (kernel module) +*** libcap-1.92.tar.gz (user mode library and utilities) +*** And you have to configure the kernel with CONFIG_VFS_CAP_PLUGIN +*** set (filesystems menu). Be warned: This code is *really* ALPHA. +***]]) +fi +fi + + +GNUPG_CHECK_IPC +if test "$ac_cv_header_sys_shm_h" = "yes"; then + AC_DEFINE(USE_SHM_COPROCESSING,1, + [define if the shared memory interface should be made available]) +fi + +dnl +dnl check whether we have a random device +dnl +if test "$try_dev_random" = yes ; then + AC_CACHE_CHECK(for random device, ac_cv_have_dev_random, + [if test -r "$NAME_OF_DEV_RANDOM" && test -r "$NAME_OF_DEV_URANDOM" ; then + ac_cv_have_dev_random=yes; else ac_cv_have_dev_random=no; fi]) + if test "$ac_cv_have_dev_random" = yes; then + AC_DEFINE(HAVE_DEV_RANDOM,1, + [defined if the system supports a random device] ) + fi +else + AC_MSG_CHECKING(for random device) + ac_cv_have_dev_random=no + AC_MSG_RESULT(has been disabled) +fi + +dnl +dnl and whether this device supports ioctl +dnl (Note, that we should do a real test here) +dnl +if test "$ac_cv_have_dev_random" = yes ; then + AC_CHECK_HEADERS(linux/random.h) + AC_CACHE_CHECK(for random device ioctl, ac_cv_have_dev_random_ioctl, + [ if test "$ac_cv_header_linux_random_h" = yes ; then + ac_cv_have_dev_random_ioctl=yes; + else + ac_cv_have_dev_random_ioctl=no; + fi + ]) + if test "$ac_cv_have_dev_random_ioctl" = yes; then + AC_DEFINE(HAVE_DEV_RANDOM_IOCTL,1, + [defined if the random device supports some IOCTLs]) + fi +fi + + +dnl +dnl Figure out the default linkage mode for random modules +dnl +print_egd_notice=no +if test "$use_static_rnd" = default; then + if test "$ac_cv_have_dev_random" = yes; then + static_random_module="rndlinux" + else + case "${target}" in + *-*-mingw32*|*-*-cygwin*) + static_random_module="rndw32" + AC_DEFINE(USE_STATIC_RNDW32,1, + [At some point in the code we need to know that + we use the Windows random module.]) + ;; + i?86-emx-os2|i?86-*-os2*emx) + static_random_module="rndos2" + ;; + m68k-atari-mint) + static_random_module="rndatari" + ;; + i?86-*-msdosdjgpp*) + : + ;; + *) + static_random_module="rndunix" + print_egd_notice=yes + ;; + esac + fi +else + if test "$use_static_rnd" = none; then + : + else + static_random_module="rnd$use_static_rnd" + if test "$use_static_rnd" = "unix"; then + print_egd_notice=yes + fi + fi +fi + + +if test "$print_egd_notice" = "yes"; then + AC_MSG_WARN([[ +*** +*** The performance of the UNIX random gatherer module is not very good +*** and it does not keep the entropy pool over multiple invocations of +*** GnuPG. The suggested way to overcome this problem is to use the +*** +*** Entropy Gathering Daemon (EGD) +*** +*** which provides a entropy source for the whole system. It is written +*** in Perl and available at the GnuPG FTP servers. For more information +*** consult the GnuPG webpages: +*** +*** http://www.gnupg.org/download.html#egd +*** +*** You may want to run ./configure with --enable-static-rnd=none to be +*** able to load the EGD client code dynamically; this way you can choose +*** between RNDUNIX and RNDEGD without recompilation. +***]]) +fi + +dnl +dnl Parse the modules list and build the list +dnl of static and dymically linked modules +dnl +dnl (We always need a static rmd160) +static_modules="$static_modules rmd160 $static_random_module" +STATIC_CIPHER_NAMES="" +STATIC_CIPHER_OBJS="" +DYNAMIC_CIPHER_MODS="" +show_dynlink="" +for name in $MODULES_IN_CIPHER; do + x="yes" + for i in $disallowed_modules; do + if test "$name" = "$i" ; then x="no" ; fi + done; + if test $x = yes; then + x="no" + for i in $static_modules; do + if test "$name" = "$i" ; then + x="yes" + fi + done; + if test $x = yes; then + STATIC_CIPHER_NAMES="$STATIC_CIPHER_NAMES $name" + STATIC_CIPHER_OBJS="$STATIC_CIPHER_OBJS $name.o" + else + DYNAMIC_CIPHER_MODS="$DYNAMIC_CIPHER_MODS $name" + show_dynlink="$show_dynlink $name" + fi + fi +done +AC_SUBST(STATIC_CIPHER_OBJS) +AC_SUBST(STATIC_CIPHER_NAMES) +AC_SUBST(DYNAMIC_CIPHER_MODS) + +dnl +dnl And build the constructor file +dnl + +test -d cipher || mkdir cipher +cat <<G10EOF >cipher/construct.c +/* automatically generated by configure - do not edit */ + +G10EOF +show_statlink="" +for name in $STATIC_CIPHER_NAMES; do + echo "void ${name}_constructor(void);" >>cipher/construct.c + show_statlink="$show_statlink $name" +done + +cat <<G10EOF >>cipher/construct.c + +void +cipher_modules_constructor(void) +{ + static int done = 0; + if( done ) + return; + done = 1; + +G10EOF +for name in $STATIC_CIPHER_NAMES; do + echo " ${name}_constructor();" >>cipher/construct.c +done +echo '}' >>cipher/construct.c + + + + +dnl +dnl Figure how to link the cipher modules +dnl +AC_SUBST(STATIC_CIPHER_OBJS) +AC_SUBST(DYNAMIC_CIPHER_MODS) + + +dnl setup assembler stuff +AC_MSG_CHECKING(for mpi assembler functions) +if test -f $srcdir/mpi/config.links ; then + . $srcdir/mpi/config.links + AC_CONFIG_LINKS("$mpi_ln_list") + ac_cv_mpi_extra_asm_modules="$mpi_extra_modules" + ac_cv_mpi_sflags="$mpi_sflags" + ac_cv_mpi_config_done="yes" + AC_MSG_RESULT(done) +else + AC_MSG_RESULT(failed) + AC_MSG_ERROR([mpi/config.links missing!]) +fi +MPI_EXTRA_ASM_OBJS="" +show_extraasm="" +if test "$ac_cv_mpi_extra_asm_modules" != ""; then +for i in $ac_cv_mpi_extra_asm_modules; do + show_extraasm="$show_extraasm $i" + MPI_EXTRA_ASM_OBJS="$MPI_EXTRA_ASM_OBJS $i.o" +done +fi +AC_SUBST(MPI_EXTRA_ASM_OBJS) +MPI_SFLAGS="$ac_cv_mpi_sflags" +AC_SUBST(MPI_SFLAGS) + +dnl Do we have zlib? Must do it here because Solaris failed +dnl when compiling a conftest (due to the "-lz" from LIBS). +use_local_zlib=yes +if test "$g10_force_zlib" = "yes"; then + : +else + _cppflags="${CPPFLAGS}" + _ldflags="${LDFLAGS}" + + AC_ARG_WITH(zlib, + [ --with-zlib=DIR use libz in DIR],[ + if test -d "$withval"; then + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + ]) + + AC_CHECK_HEADER(zlib.h, + AC_CHECK_LIB(z, deflateInit2_, + use_local_zlib=no + LIBS="$LIBS -lz", + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}), + CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}) +fi + +if test "$use_local_zlib" = yes ; then + AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, true) + AC_CONFIG_LINKS(zlib.h:zlib/zlib.h zconf.h:zlib/zconf.h ) + ZLIBS="../zlib/libzlib.a" +else + AM_CONDITIONAL(ENABLE_LOCAL_ZLIB, false) + ZLIBS= +fi +AC_SUBST(ZLIBS) + + +# Allow users to append something to the version string without +# flagging it as development version. The user version parts is +# considered everything after a dash. +changequote(,)dnl +tmp_pat='[a-zA-Z]' +changequote([,])dnl +if echo "$VERSION" | sed 's/-.*//' | grep "$tmp_pat" >/dev/null ; then + AC_DEFINE(IS_DEVELOPMENT_VERSION,1, + [Defined if this is not a regular release]) +fi + +AM_CONDITIONAL(CROSS_COMPILING, test x$cross_compiling = xyes) + +GNUPG_CHECK_GNUMAKE + +# add some extra libs here so that previous tests don't fail for +# mysterious reasons - the final link step shoudl bail out. +case "${target}" in + *-*-mingw32*) + LIBS="$LIBS -lws2_32" + ;; + *) + ;; +esac + + +if test "$GCC" = yes; then + if test "$USE_MAINTAINER_MODE" = "yes"; then + CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes" + else + CFLAGS="$CFLAGS -Wall" + fi +fi + +AC_SUBST(NETLIBS) + +# Note the \\\\ for backslashes. Autoconf eats one layer, leaving \\ + +AC_CONFIG_COMMANDS(g10defs.h,[[ +cat >g10defs.tmp <<G10EOF +/* Generated automatically by configure */ +#ifdef HAVE_DRIVE_LETTERS + #define G10_LOCALEDIR "c:/lib/gnupg/locale" + #define GNUPG_LIBDIR "c:/lib/gnupg" + #define GNUPG_DATADIR "c:/lib/gnupg" + #define GNUPG_HOMEDIR "c:/gnupg" +#else + #define G10_LOCALEDIR "${datadir}/locale" + #define GNUPG_LIBDIR "${libdir}/gnupg" + #define GNUPG_DATADIR "${datadir}/gnupg" + #ifdef __VMS + #define GNUPG_HOMEDIR "/SYS\$LOGIN/gnupg" + #else + #define GNUPG_HOMEDIR "~/.gnupg" + #endif +#endif +/* those are here to be redefined by handcrafted g10defs.h. + Please note that the string version must not contain more + than one character because the using code assumes strlen()==1 */ +#ifdef HAVE_DOSISH_SYSTEM +#define DIRSEP_C '\\\\' +#define EXTSEP_C '.' +#define DIRSEP_S "\\\\" +#define EXTSEP_S "." +#else +#define DIRSEP_C '/' +#define EXTSEP_C '.' +#define DIRSEP_S "/" +#define EXTSEP_S "." +#endif +G10EOF +cat mpi/mpi-asm-defs.h >>g10defs.tmp +if cmp -s g10defs.h g10defs.tmp 2>/dev/null; then + echo "g10defs.h is unchanged" + rm -f g10defs.tmp +else + rm -f g10defs.h + mv g10defs.tmp g10defs.h + echo "g10defs.h created" +fi +]],[[ +prefix=$prefix +exec_prefix=$exec_prefix +libdir=$libdir +datadir=$datadir +DATADIRNAME=$DATADIRNAME +]]) + + +AC_CONFIG_FILES([ +Makefile +intl/Makefile +po/Makefile.in +util/Makefile +mpi/Makefile +cipher/Makefile +g10/Makefile +keyserver/Makefile +keyserver/gpgkeys_mailto +keyserver/gpgkeys_test +doc/Makefile +tools/Makefile +zlib/Makefile +checks/Makefile +]) +AC_OUTPUT + +# Give some feedback +echo +echo " Configured for: $PRINTABLE_OS_NAME ($target)" +if test -n "$show_dynlink"; then + echo " Dynamically linked modules:$show_dynlink" +fi +if test -n "$show_statlink"; then + echo " Statically linked modules:$show_statlink" +fi +if test -n "$show_extraasm"; then + echo " Extra cpu specific functions:$show_extraasm" +fi +echo + diff --git a/gnupg.txt b/gnupg.txt new file mode 100644 index 000000000..4bb5603c1 --- /dev/null +++ b/gnupg.txt @@ -0,0 +1,98 @@ +%%comments: +Copyright (C) 2000, 2001 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the file COPYING. + +%%name: GnuPG + +%%short-description: Complete implementation of the OpenPGP Internet standard. + +%%full-description: A complete and free replacement for PGP. The +program does not use any patented algorithms, and can be used as a +filter program. Can handle all OpenPGP messages and messages generated +by PGP 5.0 and newer unless they use the IDEA algorithm. + +Supports ElGamal (signature and encrytion), DSA, AES, 3DES, Blowfish, +Twofish, CAST5, MD5, SHA-1, RIPE-MD-160 and TIGER, and has language +support for sixteen different languages. + +It is believed to be fully OpenPGP (as defined in RFC2440) conform, +and has integrated support for HKP keyservers. There are a lot of +useful extra features like anonymous message recipients. + +%%category: security, administration, email + +%%license: GPL + +%%maintainer: Werner Koch <wk@gnupg.org> + +%%interface: Command line + +%%updated: 1 Jun 2001 + +%%keywords: PGP, security, decryption, encryption, digital signatures + +%%programs: + +%%GNU: yes + +%%web-page: http://www.gnupg.org/ + +%%support: Paid extension/consulting from http://www.g10code.com + +%%doc: English user manual available from: +http://www.gnupg.org/gph/index.html; Spanish user manual available from: +http://www.gnupg.org/gph/index.html; English HOWTO available from +http://www.dewinter.com/gnupg_howto/english/; French HOWTO available +from http://www.gnupg.org/howtos/fr/; German HOWTO available from +http://www.gnupg.org/howtos/de/; Spanish HOWTO available from +http://www.dewinter.com/gnupg_howto/spanish. + +%%developers: Matthew Skala, Michael Roth, Niklas Hernaeus, Remi +Guyomarch, Werner Koch <wk@gnupg.org>. + +%%contributors: J. Michael Ashley + +%%sponsors: German Federal Ministry of Economics and Technology + +%%source: ftp://ftp.gnupg.org/gcrypt/gnupg + +%%debian: http://www.debian.org/Packages/stable/non-us/gnupg.html + +%%redhat: http://www.megaloman.com/~hany/RPM/gnupg.html + +%%repository: See http://www.gnupg.org/cvs-access.html + +%%related: shred + +%%source-language: C + +%%supported-languages: + +%%use-requirements: + +%%build-prerequisites: + +%%weak-prerequisites: + +%%source-prerequisites: + +%%version: 1.0.6 stable released on 29 May 2001 + +%%announce-list: announce@gnupg.org + +%%announce-news: + +%%help-list: gnupg-users@gnupg.org + +%%help-news: + +%%dev-list: gnupg-devel@gnupg.org + +%%dev-news: + +%%bug-list: bug-gnupg@gnupg.org diff --git a/mpi/ChangeLog b/mpi/ChangeLog new file mode 100644 index 000000000..cfe54007c --- /dev/null +++ b/mpi/ChangeLog @@ -0,0 +1,325 @@ +2002-05-10 Stefan Bellon <sbellon@sbellon.de> + + * mpiutil.c (mpi_alloc_like/mpi_debug_alloc_like): Added code + for M_DEBUG. + +2002-04-18 Werner Koch <wk@gnupg.org> + + * i386/syntax.h (ALIGN): Removed parens from definition + * i386/mpih-add1.S, i386/mpih-sub1.S, i386/mpih-rshift.S, + i386/mpih-lshift.S: Minor syntax changes suggested by Mark Pettit + after comparing the files with those for GMP 4. + +2001-11-08 Werner Koch <wk@gnupg.org> + + * config.links (mpi_sflags): Add extra rule for sparc64-sun-solaris2. + +2001-08-20 Werner Koch <wk@gnupg.org> + + * longlong.h [__riscos__]: Need a special pragma here. + +2001-08-09 Werner Koch <wk@gnupg.org> + + * config.links: Added configuraton for powerpc-openbsd. By Peter + Valchev + +2001-07-09 Werner Koch <wk@gnupg.org> + + * config.links: Changed the way the list of files to be + symlinked is returned. + +2001-05-27 Werner Koch <wk@gnupg.org> + + * hppa/, hppa1.1/, pa7100/ : Use .label command instead of labels + because there syntax changed. By Matthew Wilcox. + +2001-05-06 Werner Koch <wk@gnupg.org> + + * longlong.h: Fixes for ARM by Phil Blundell. + +2001-04-17 Werner Koch <wk@gnupg.org> + + Updated copyright notices. + +2001-03-24 Werner Koch <wk@gnupg.org> + + * mpi-mul.c (mpi_mul): Make sure that secret temporary results are + not stored in w. Suggested by Florian Weimer. + +2001-03-18 Werner Koch <wk@gnupg.org> + + * config.links: Use i386 code for i386. According to tests by + Kevin Ryde the i586 code runs slow on i386 CPUs. Ditto for i786. + +2000-10-24 Werner Koch <wk@gnupg.org> + + * mips3/: Changed a few comments to C-style. By Jeff Long. + +2000-10-13 Werner Koch <wk@gnupg.org> + + * mpi.h: Removed the inclusion of mpi-asm-defs.h because this + makes some trouble when doing a VPATH build. configure now + takes care of it. + +2000-10-12 Werner Koch <wk@gnupg.org> + + * generic/mpi-asm-defs.h: New. + * mips3/mpi-asm-defs.h: New. + * config.links: Create a link to one of the above files. + +Wed Jul 19 11:26:43 CEST 2000 Werner Koch <wk@> + + * config.links: Support for powerpc--netbsd by Gabriel Rosenkoetter. + +Wed Mar 22 13:50:24 CET 2000 Werner Koch <wk@openit.de> + + * config.links: Add support for FreeBSD 5 and made the case stmt + looking nicer. From Jun Kuriyama. + +Fri Mar 17 17:50:25 CET 2000 Werner Koch <wk@openit.de> + + * config.links (sparc64-unknown-linux-gnu): use udic module. + From Adam Mitchell. + +2000-03-14 12:03:56 Werner Koch (wk@habibti.openit.de) + + * Makefile.am: Do not use .s and .S files but a temp names, so that + OSes with caseinsensitive filenames do work. From Frank Donahoe. + +Tue Mar 7 18:45:31 CET 2000 Werner Koch <wk@gnupg.de> + + * mpih-mul.c (mpihelp_mul_karatsuba_case): It seems that the + untested part works fine. Removed the debugging message. + + * longlong.h (umul_ppmm): Fixes for ARM-4. By Sean MacLennan. + + * config.links: Add support for NetBSD. + +Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de> + + * mpi-internal.h (karatsuba_ctx): New. + * mpih-mul.c (mpihelp_release_karatsuba_ctx): New. + (mpihelp_mul_karatsuba_case): New. + (mpihelp_mul): Splitted to make use of the new functions. + * mpi-pow.c (mpi_powm): Make use of the new splitted function + to avoid multiple allocation of temporary memory during the + karatsuba operations. + + * mpi_mpow.c: Removed the unused Barrett code. + +Sun Dec 19 15:22:26 CET 1999 Werner Koch <wk@gnupg.de> + + * power/ : Converted more comments to C comments because some AS + complain about ' in comments. + +Thu Dec 16 10:07:58 CET 1999 Werner Koch <wk@gnupg.de> + + * Makefile.am: c/SFLAGS/ASFLAGS/. This has only been used by the + powerpc and actually never passed the -Wa,foo to the cc. + +Thu Dec 9 10:31:05 CET 1999 Werner Koch <wk@gnupg.de> + + * power/: Add all files from GMP for this CPU. + + * config.links: Support for BSDI 4.x. By Wayne Chapeskie. + (sparc8): Made the search path the same as sparc9 + + * mpih-div.c (mpihelp_divrem): The MPN_COPY_DECR copied one + elemnat too many. This is gmp2.0.2p9.txt patch. + +Sat Oct 9 20:34:41 CEST 1999 Werner Koch <wk@gnupg.de> + + * Makefile.am: Removed libtool. + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links: Add case label for DJGPP + +Wed Jul 14 19:42:08 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * Makefile.am: Use .s files as temporaries, disabled other .S rules. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * mpicoder.c (g10_log_mpidump): New. + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + + * mpi-bit.c (mpi_lshift_limbs,mpi_rshift_limbs): New. + * mpi-mpow.c (barrett_mulm): New but diabled. + +Tue Jun 1 16:01:46 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links (i[56]86*-*-freebsdelf*): New. + +Sun May 23 14:20:22 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links (sysdep.h): Not any more conditionally created. + +Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpiutil.c (mpi_alloc_like): New. + +Mon Apr 26 17:48:15 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpih-add.c, mpih-sub.c: Removed + * mpi-inline.c: New. + * mpi-inline.h: Make it usable by mpi-inline.c. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpih-mul.c (mpihelp_mul_n): Fixed use of memory region. + (mpihelp_mul): Ditto. + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Explicit rules to invoke cpp on *.S + +Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * config.links: Take advantage of the with_symbol_underscore macro. + Add support for freebsd 4. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mips3/mpih-sub1.S: Removed left over junk in last line. (Should I + blame me or my editor?). + +Sat Feb 13 12:04:43 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * Makefile.am: Removed the +=. Add MPI_OPT_FLAGS. + +Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpi-cmp.c (mpi_cmp_ui): Normalized the arg. + +Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de> + + * mpi-bit.c (mpi_normalize): New. + (mpi_get_nbits): Normalize the MPI. + * mpi-bit.c (mpi_cmp): Normalize the MPI before the compare. + + +Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de> + + * config.links: Moved the case for powerpc*linux + * powerpcp32/*.S: Removed some underscores. + +Thu Nov 26 07:27:52 1998 Werner Koch <werner.koch@guug.de> + + * config.links: Support for ppc with ELF + * powerpc32/syntax.h: New. + * powerpc32/*.S: Applied ELF patches (glibc patches) + +Tue Nov 10 19:31:37 1998 Werner Koch (wk@isil.d.shuttle.de) + + * power*/ : Started with stuff for PPC + * config.links: Some stuff for PPC. + * generic/udiv-w-sdiv.c: New but disabled. + +Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): Fixes for FreeBSD 3.0 + +Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (freebsd): ELF patches from Jun Kuriyama. + +Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free). + +Thu Sep 17 18:08:50 1998 Werner Koch (wk@(none)) + + * hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20 + +Thu Aug 6 16:39:28 1998 Werner Koch,mobil,,, (wk@tobold) + + * mpi-bit.c (mpi_set_bytes): Removed. + +Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none)) + + * mpicoder.c (mpi_read_from_buffer): New. + + * mpiutil.c (mpi_set_opaque): New. + (mpi_get_opaque): New. + (mpi_copy): Changed to support opauqe flag + (mpi_free): Ditto. + +Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_clear): Reset flags. + (mpi_set): Ditto. + (mpi_alloc_secure): Set flag to 1 and not ored the 1 in, tsss.. + +Fri Jun 26 11:19:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpiutil.c (mpi_alloc): set nbits to 0. + (mpi_alloc_secure): Ditto. + (mpi_clear): Ditto. + +Thu Jun 25 11:50:01 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mips3/*.S: New + +Mon May 18 13:47:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: split mpih-shift into mpih-[lr]shift and + changed all implementations. + * mpi/alpha: add some new assembler stuff. + +Wed May 13 11:04:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Add support for MIPS + +Thu Apr 9 11:31:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_secure_buffer): New. + +Wed Apr 8 09:44:33 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links: Applied small fix from Ulf Möller. + +Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpicoder.c (mpi_get_buffer): Removed returned leading zeroes + and changed all callers. + +Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi-bit.c (mpi_clear_highbit): New. + +Mon Mar 2 19:29:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am (DISTCLEANFILES): New + +Thu Feb 26 06:48:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links (X86_BROKEN_ALIGN): Added for some systems. + +Mon Feb 23 12:21:40 1998 Werner Koch (wk@isil.d.shuttle.de) + + * mpi/m68k/mpih-shift.S (Lspecial): Changed duplicate symbol. + +Mon Feb 16 13:00:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * config.links : Add detection of m68k cpus + + + + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + diff --git a/mpi/Makefile.am b/mpi/Makefile.am new file mode 100644 index 000000000..56cf47a52 --- /dev/null +++ b/mpi/Makefile.am @@ -0,0 +1,79 @@ +# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +## Process this file with automake to produce Makefile.in + + +INCLUDES = -I.. -I$(top_srcdir)/include +CFLAGS = @CFLAGS@ @MPI_OPT_FLAGS@ +ASFLAGS = @MPI_SFLAGS@ + +EXTRA_DIST = config.links +DISTCLEANFILES = mpi-asm-defs.h \ + mpih-add1.S mpih-mul1.S mpih-mul2.S mpih-mul3.S \ + mpih-lshift.S mpih-rshift.S mpih-sub1.S asm-syntax.h sysdep.h +# Note: we only use .S files so we should delete all left over .s +CLEANFILES = _*.s + +noinst_LIBRARIES = libmpi.a + +# libmpi_a_LDFLAGS = +libmpi_a_SOURCES = longlong.h \ + mpi-add.c \ + mpi-bit.c \ + mpi-cmp.c \ + mpi-div.c \ + mpi-gcd.c \ + mpi-internal.h \ + mpi-inline.h \ + mpi-inline.c \ + mpi-inv.c \ + mpi-mul.c \ + mpi-pow.c \ + mpi-mpow.c \ + mpi-scan.c \ + mpicoder.c \ + mpih-cmp.c \ + mpih-div.c \ + mpih-mul.c \ + mpiutil.c \ + g10m.c + +# Note this objects are actually links, the sourcefiles are +# distributed by special code in dist-hook +common_asm_objects = mpih-mul1.o \ + mpih-mul2.o \ + mpih-mul3.o \ + mpih-add1.o \ + mpih-sub1.o \ + mpih-lshift.o \ + mpih-rshift.o + +libmpi_a_DEPENDENCIES = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ +libmpi_a_LIBADD = $(common_asm_objects) @MPI_EXTRA_ASM_OBJS@ + +# cancel the default rules used by libtool which do not really +# work and add one to cpp .S files +.S.o: + $(CPP) $(INCLUDES) $(DEFS) $< | grep -v '^#' > _$*.s + $(COMPILE) -c _$*.s + mv -f _$*.o $*.o + +.S.lo: + + diff --git a/mpi/alpha/README b/mpi/alpha/README new file mode 100644 index 000000000..55c0a2917 --- /dev/null +++ b/mpi/alpha/README @@ -0,0 +1,53 @@ +This directory contains mpn functions optimized for DEC Alpha processors. + +RELEVANT OPTIMIZATION ISSUES + +EV4 + +1. This chip has very limited store bandwidth. The on-chip L1 cache is +write-through, and a cache line is transfered from the store buffer to the +off-chip L2 in as much 15 cycles on most systems. This delay hurts +mpn_add_n, mpn_sub_n, mpn_lshift, and mpn_rshift. + +2. Pairing is possible between memory instructions and integer arithmetic +instructions. + +3. mulq and umulh is documented to have a latency of 23 cycles, but 2 of +these cycles are pipelined. Thus, multiply instructions can be issued at a +rate of one each 21nd cycle. + +EV5 + +1. The memory bandwidth of this chip seems excellent, both for loads and +stores. Even when the working set is larger than the on-chip L1 and L2 +caches, the perfromance remain almost unaffected. + +2. mulq has a measured latency of 13 cycles and an issue rate of 1 each 8th +cycle. umulh has a measured latency of 15 cycles and an issue rate of 1 +each 10th cycle. But the exact timing is somewhat confusing. + +3. mpn_add_n. With 4-fold unrolling, we need 37 instructions, whereof 12 + are memory operations. This will take at least + ceil(37/2) [dual issue] + 1 [taken branch] = 20 cycles + We have 12 memory cycles, plus 4 after-store conflict cycles, or 16 data + cache cycles, which should be completely hidden in the 20 issue cycles. + The computation is inherently serial, with these dependencies: + addq + / \ + addq cmpult + | | + cmpult | + \ / + or + I.e., there is a 4 cycle path for each limb, making 16 cycles the absolute + minimum. We could replace the `or' with a cmoveq/cmovne, which would save + a cycle on EV5, but that might waste a cycle on EV4. Also, cmov takes 2 + cycles. + addq + / \ + addq cmpult + | \ + cmpult -> cmovne + +STATUS + diff --git a/mpi/alpha/distfiles b/mpi/alpha/distfiles new file mode 100644 index 000000000..f2ab9fc3c --- /dev/null +++ b/mpi/alpha/distfiles @@ -0,0 +1,11 @@ +README +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S + +udiv-qrnnd.S + diff --git a/mpi/alpha/mpih-add1.S b/mpi/alpha/mpih-add1.S new file mode 100644 index 000000000..a2ee8eb17 --- /dev/null +++ b/mpi/alpha/mpih-add1.S @@ -0,0 +1,124 @@ +/* alpha add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * Copyright (C) 1995, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, ($16) + * mpi_ptr_t s1_ptr, ($17) + * mpi_ptr_t s2_ptr, ($18) + * mpi_size_t size) ($19) + */ + + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_add_n + .ent mpihelp_add_n +mpihelp_add_n: + .frame $30,0,$26,0 + + ldq $3,0($17) + ldq $4,0($18) + + subq $19,1,$19 + and $19,4-1,$2 # number of limbs in first loop + bis $31,$31,$0 + beq $2,.L0 # if multiple of 4 limbs, skip first loop + + subq $19,$2,$19 + +.Loop0: subq $2,1,$2 + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + + addq $17,8,$17 + addq $18,8,$18 + bis $5,$5,$3 + bis $6,$6,$4 + addq $16,8,$16 + bne $2,.Loop0 + +.L0: beq $19,.Lend + + .align 3 +.Loop: subq $19,4,$19 + + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + + ldq $3,16($17) + addq $6,$0,$6 + ldq $4,16($18) + cmpult $6,$0,$1 + addq $5,$6,$6 + cmpult $6,$5,$0 + stq $6,8($16) + or $0,$1,$0 + + ldq $5,24($17) + addq $4,$0,$4 + ldq $6,24($18) + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,16($16) + or $0,$1,$0 + + ldq $3,32($17) + addq $6,$0,$6 + ldq $4,32($18) + cmpult $6,$0,$1 + addq $5,$6,$6 + cmpult $6,$5,$0 + stq $6,24($16) + or $0,$1,$0 + + addq $17,32,$17 + addq $18,32,$18 + addq $16,32,$16 + bne $19,.Loop + +.Lend: addq $4,$0,$4 + cmpult $4,$0,$1 + addq $3,$4,$4 + cmpult $4,$3,$0 + stq $4,0($16) + or $0,$1,$0 + ret $31,($26),1 + + .end mpihelp_add_n + diff --git a/mpi/alpha/mpih-lshift.S b/mpi/alpha/mpih-lshift.S new file mode 100644 index 000000000..4ce4879af --- /dev/null +++ b/mpi/alpha/mpih-lshift.S @@ -0,0 +1,123 @@ +/* alpha - left shift + * + * Copyright (C) 1994, 1995, 1998, 2001 Free Software Foundation, Inc. + * + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (r16) + * mpi_ptr_t up, (r17) + * mpi_size_t usize, (r18) + * unsigned cnt) (r19) + * + * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, + * it would take 4 cycles/limb. It should be possible to get down to 3 + * cycles/limb since both ldq and stq can be paired with the other used + * instructions. But there are many restrictions in the 21064 pipeline that + * makes it hard, if not impossible, to get down to 3 cycles/limb: + * + * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. + * 2. Only aligned instruction pairs can be paired. + * 3. The store buffer or silo might not be able to deal with the bandwidth. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_lshift + .ent mpihelp_lshift +mpihelp_lshift: + .frame $30,0,$26,0 + + s8addq $18,$17,$17 # make r17 point at end of s1 + ldq $4,-8($17) # load first limb + subq $17,8,$17 + subq $31,$19,$7 + s8addq $18,$16,$16 # make r16 point at end of RES + subq $18,1,$18 + and $18,4-1,$20 # number of limbs in first loop + srl $4,$7,$0 # compute function result + + beq $20,.L0 + subq $18,$20,$18 + + .align 3 +.Loop0: + ldq $3,-8($17) + subq $16,8,$16 + subq $17,8,$17 + subq $20,1,$20 + sll $4,$19,$5 + srl $3,$7,$6 + bis $3,$3,$4 + bis $5,$6,$8 + stq $8,0($16) + bne $20,.Loop0 + +.L0: beq $18,.Lend + + .align 3 +.Loop: ldq $3,-8($17) + subq $16,32,$16 + subq $18,4,$18 + sll $4,$19,$5 + srl $3,$7,$6 + + ldq $4,-16($17) + sll $3,$19,$1 + bis $5,$6,$8 + stq $8,24($16) + srl $4,$7,$2 + + ldq $3,-24($17) + sll $4,$19,$5 + bis $1,$2,$8 + stq $8,16($16) + srl $3,$7,$6 + + ldq $4,-32($17) + sll $3,$19,$1 + bis $5,$6,$8 + stq $8,8($16) + srl $4,$7,$2 + + subq $17,32,$17 + bis $1,$2,$8 + stq $8,0($16) + + bgt $18,.Loop + +.Lend: sll $4,$19,$8 + stq $8,-8($16) + ret $31,($26),1 + .end mpihelp_lshift + + diff --git a/mpi/alpha/mpih-mul1.S b/mpi/alpha/mpih-mul1.S new file mode 100644 index 000000000..e62ccbdb7 --- /dev/null +++ b/mpi/alpha/mpih-mul1.S @@ -0,0 +1,90 @@ +/* Alpha 21064 mpih-mul1.S -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_size_t s1_size, (r18) + * mpi_limb_t s2_limb) (r19) + * + * This code runs at 42 cycles/limb on the EV4 and 18 cycles/limb on the EV5. + * + * To improve performance for long multiplications, we would use + * 'fetch' for S1 and 'fetch_m' for RES. It's not obvious how to use + * these instructions without slowing down the general code: 1. We can + * only have two prefetches in operation at any time in the Alpha + * architecture. 2. There will seldom be any special alignment + * between RES_PTR and S1_PTR. Maybe we can simply divide the current + * loop into an inner and outer loop, having the inner loop handle + * exactly one prefetch block? + */ + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_mul_1 + .ent mpihelp_mul_1 2 +mpihelp_mul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + bic $31,$31,$4 # clear cy_limb + umulh $2,$19,$0 # $0 = prod_high + beq $18,Lend1 # jump if size was == 1 + ldq $2,8($17) # $2 = s1_limb + subq $18,1,$18 # size-- + stq $3,0($16) + beq $18,Lend2 # jump if size was == 2 + + .align 3 +Loop: mulq $2,$19,$3 # $3 = prod_low + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,16($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + stq $3,8($16) + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $16,8,$16 # res_ptr++ + bne $18,Loop + +Lend2: mulq $2,$19,$3 # $3 = prod_low + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + stq $3,8($16) + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +Lend1: stq $3,0($16) + ret $31,($26),1 + + .end mpihelp_mul_1 + + diff --git a/mpi/alpha/mpih-mul2.S b/mpi/alpha/mpih-mul2.S new file mode 100644 index 000000000..595af99d3 --- /dev/null +++ b/mpi/alpha/mpih-mul2.S @@ -0,0 +1,97 @@ +/* Alpha 21064 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_size_t s1_size, (r18) + * mpi_limb_t s2_limb) (r19) + * + * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. + */ + + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_addmul_1 + .ent mpihelp_addmul_1 2 +mpihelp_addmul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + umulh $2,$19,$0 # $0 = prod_high + beq $18,.Lend1 # jump if size was == 1 + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + addq $5,$3,$3 + cmpult $3,$5,$4 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + beq $18,.Lend2 # jump if size was == 2 + + .align 3 +.Loop: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + addq $5,$0,$0 # combine carries + bne $18,.Loop + +.Lend2: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $5,$0,$0 # combine carries + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +.Lend1: addq $5,$3,$3 + cmpult $3,$5,$5 + stq $3,0($16) + addq $0,$5,$0 + ret $31,($26),1 + + .end mpihelp_addmul_1 + diff --git a/mpi/alpha/mpih-mul3.S b/mpi/alpha/mpih-mul3.S new file mode 100644 index 000000000..fa3df92a5 --- /dev/null +++ b/mpi/alpha/mpih-mul3.S @@ -0,0 +1,95 @@ +/* Alpha 21064 submul_1 -- Multiply a limb vector with a limb and + * subtract the result from a second limb vector. + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (r16 ) + * mpi_ptr_t s1_ptr, (r17 ) + * mpi_size_t s1_size, (r18 ) + * mpi_limb_t s2_limb) (r19 ) + * + * This code runs at 42 cycles/limb on EV4 and 18 cycles/limb on EV5. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_submul_1 + .ent mpihelp_submul_1 2 +mpihelp_submul_1: + .frame $30,0,$26 + + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + umulh $2,$19,$0 # $0 = prod_high + beq $18,.Lend1 # jump if size was == 1 + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + subq $18,1,$18 # size-- + subq $5,$3,$3 + cmpult $5,$3,$4 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + beq $18,.Lend2 # jump if size was == 2 + + .align 3 +.Loop: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + subq $18,1,$18 # size-- + umulh $2,$19,$4 # $4 = cy_limb + ldq $2,0($17) # $2 = s1_limb + addq $17,8,$17 # s1_ptr++ + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $16,8,$16 # res_ptr++ + addq $5,$0,$0 # combine carries + bne $18,.Loop + +.Lend2: mulq $2,$19,$3 # $3 = prod_low + ldq $5,0($16) # $5 = *res_ptr + addq $4,$0,$0 # cy_limb = cy_limb + 'cy' + umulh $2,$19,$4 # $4 = cy_limb + addq $3,$0,$3 # $3 = cy_limb + prod_low + cmpult $3,$0,$0 # $0 = carry from (cy_limb + prod_low) + subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $5,$0,$0 # combine carries + addq $4,$0,$0 # cy_limb = prod_high + cy + ret $31,($26),1 +.Lend1: subq $5,$3,$3 + cmpult $5,$3,$5 + stq $3,0($16) + addq $0,$5,$0 + ret $31,($26),1 + + .end mpihelp_submul_1 + diff --git a/mpi/alpha/mpih-rshift.S b/mpi/alpha/mpih-rshift.S new file mode 100644 index 000000000..e15542de5 --- /dev/null +++ b/mpi/alpha/mpih-rshift.S @@ -0,0 +1,120 @@ +/* alpha rshift + * Copyright (C) 1994, 1995, 1998, 1999, + * 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GNUPG. + * + * GNUPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (r16) + * mpi_ptr_t up, (r17) + * mpi_size_t usize, (r18) + * unsigned cnt) (r19) + * + * This code runs at 4.8 cycles/limb on the 21064. With infinite unrolling, + * it would take 4 cycles/limb. It should be possible to get down to 3 + * cycles/limb since both ldq and stq can be paired with the other used + * instructions. But there are many restrictions in the 21064 pipeline that + * makes it hard, if not impossible, to get down to 3 cycles/limb: + * + * 1. ldq has a 3 cycle delay, srl and sll have a 2 cycle delay. + * 2. Only aligned instruction pairs can be paired. + * 3. The store buffer or silo might not be able to deal with the bandwidth. + */ + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_rshift + .ent mpihelp_rshift +mpihelp_rshift: + .frame $30,0,$26,0 + + ldq $4,0($17) # load first limb + addq $17,8,$17 + subq $31,$19,$7 + subq $18,1,$18 + and $18,4-1,$20 # number of limbs in first loop + sll $4,$7,$0 # compute function result + + beq $20,.R0 + subq $18,$20,$18 + + .align 3 +.Roop0: + ldq $3,0($17) + addq $16,8,$16 + addq $17,8,$17 + subq $20,1,$20 + srl $4,$19,$5 + sll $3,$7,$6 + bis $3,$3,$4 + bis $5,$6,$8 + stq $8,-8($16) + bne $20,.Roop0 + +.R0: beq $18,.Rend + + .align 3 +.Roop: ldq $3,0($17) + addq $16,32,$16 + subq $18,4,$18 + srl $4,$19,$5 + sll $3,$7,$6 + + ldq $4,8($17) + srl $3,$19,$1 + bis $5,$6,$8 + stq $8,-32($16) + sll $4,$7,$2 + + ldq $3,16($17) + srl $4,$19,$5 + bis $1,$2,$8 + stq $8,-24($16) + sll $3,$7,$6 + + ldq $4,24($17) + srl $3,$19,$1 + bis $5,$6,$8 + stq $8,-16($16) + sll $4,$7,$2 + + addq $17,32,$17 + bis $1,$2,$8 + stq $8,-8($16) + + bgt $18,.Roop + +.Rend: srl $4,$19,$8 + stq $8,0($16) + ret $31,($26),1 + .end mpihelp_rshift + diff --git a/mpi/alpha/mpih-sub1.S b/mpi/alpha/mpih-sub1.S new file mode 100644 index 000000000..a32b470e2 --- /dev/null +++ b/mpi/alpha/mpih-sub1.S @@ -0,0 +1,124 @@ +/* Alpha sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * Copyright (C) 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (r16) + * mpi_ptr_t s1_ptr, (r17) + * mpi_ptr_t s2_ptr, (r18) + * mpi_size_t size) (r19) + */ + + .set noreorder + .set noat +.text + .align 3 + .globl mpihelp_sub_n + .ent mpihelp_sub_n +mpihelp_sub_n: + .frame $30,0,$26,0 + + ldq $3,0($17) + ldq $4,0($18) + + subq $19,1,$19 + and $19,4-1,$2 # number of limbs in first loop + bis $31,$31,$0 + beq $2,.L0 # if multiple of 4 limbs, skip first loop + + subq $19,$2,$19 + +.Loop0: subq $2,1,$2 + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + + addq $17,8,$17 + addq $18,8,$18 + bis $5,$5,$3 + bis $6,$6,$4 + addq $16,8,$16 + bne $2,.Loop0 + +.L0: beq $19,.Lend + + .align 3 +.Loop: subq $19,4,$19 + + ldq $5,8($17) + addq $4,$0,$4 + ldq $6,8($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + + ldq $3,16($17) + addq $6,$0,$6 + ldq $4,16($18) + cmpult $6,$0,$1 + subq $5,$6,$6 + cmpult $5,$6,$0 + stq $6,8($16) + or $0,$1,$0 + + ldq $5,24($17) + addq $4,$0,$4 + ldq $6,24($18) + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,16($16) + or $0,$1,$0 + + ldq $3,32($17) + addq $6,$0,$6 + ldq $4,32($18) + cmpult $6,$0,$1 + subq $5,$6,$6 + cmpult $5,$6,$0 + stq $6,24($16) + or $0,$1,$0 + + addq $17,32,$17 + addq $18,32,$18 + addq $16,32,$16 + bne $19,.Loop + +.Lend: addq $4,$0,$4 + cmpult $4,$0,$1 + subq $3,$4,$4 + cmpult $3,$4,$0 + stq $4,0($16) + or $0,$1,$0 + ret $31,($26),1 + + .end mpihelp_sub_n + + diff --git a/mpi/alpha/udiv-qrnnd.S b/mpi/alpha/udiv-qrnnd.S new file mode 100644 index 000000000..0079c3cae --- /dev/null +++ b/mpi/alpha/udiv-qrnnd.S @@ -0,0 +1,161 @@ +/* Alpha 21064 __udiv_qrnnd + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + + .set noreorder + .set noat +.text + .align 3 + .globl __udiv_qrnnd + .ent __udiv_qrnnd +__udiv_qrnnd: + .frame $30,0,$26,0 + .prologue 0 +#define cnt $2 +#define tmp $3 +#define rem_ptr $16 +#define n1 $17 +#define n0 $18 +#define d $19 +#define qb $20 + + ldiq cnt,16 + blt d,.Largedivisor + +.Loop1: cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule d,n1,qb + subq n1,d,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + subq cnt,1,cnt + bgt cnt,.Loop1 + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + +.Largedivisor: + and n0,1,$4 + + srl n0,1,n0 + sll n1,63,tmp + or tmp,n0,n0 + srl n1,1,n1 + + and d,1,$6 + srl d,1,$5 + addq $5,$6,$5 + +.Loop2: cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + cmplt n0,0,tmp + addq n1,n1,n1 + bis n1,tmp,n1 + addq n0,n0,n0 + cmpule $5,n1,qb + subq n1,$5,tmp + cmovne qb,tmp,n1 + bis n0,qb,n0 + subq cnt,1,cnt + bgt cnt,.Loop2 + + addq n1,n1,n1 + addq $4,n1,n1 + bne $6,.LOdd + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + +.LOdd: + /* q' in n0. r' in n1 */ + addq n1,n0,n1 + cmpult n1,n0,tmp # tmp := carry from addq + beq tmp,.LLp6 + addq n0,1,n0 + subq n1,d,n1 +.LLp6: cmpult n1,d,tmp + bne tmp,.LLp7 + addq n0,1,n0 + subq n1,d,n1 +.LLp7: + stq n1,0(rem_ptr) + bis $31,n0,$0 + ret $31,($26),1 + + .end __udiv_qrnnd diff --git a/mpi/config.links b/mpi/config.links new file mode 100644 index 000000000..cb89513a5 --- /dev/null +++ b/mpi/config.links @@ -0,0 +1,310 @@ +# config.links - helper for ../configure +# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +# +# This file is part of GnuPG. +# +# GnuPG is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# GnuPG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + +# sourced by ../configure to get the list of files to link +# this should set $mpi_ln_list. +# Note: this is called from the above directory. + + +mpi_extra_modules= +mpi_sflags= + +test -d ./mpi || mkdir ./mpi + +echo '/* created by config.links - do not edit */' >./mpi/asm-syntax.h + +if test "$try_asm_modules" = "yes" ; then +case "${target}" in + i[3467]86*-*-freebsd*-elf | \ + i[3467]86*-*-freebsd[3-9]* | \ + i[3467]86*-*-freebsdelf* | \ + i[3467]86*-*-netbsd* ) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-freebsd*-elf | \ + i586*-*-freebsd[3-9]* | \ + i586*-*-freebsdelf* | \ + i586*-*-netbsd* | \ + pentium-*-netbsd* | \ + pentiumpro-*-netbsd*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[34]86*-*-bsdi4*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i[3467]86*-*-linuxaout* | \ + i[3467]86*-*-linuxoldld* | \ + i[3467]86*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-linuxaout* | \ + i586*-*-linuxoldld* | \ + i586*-*-*bsd*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + echo '#define X86_BROKEN_ALIGN' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-msdosdjgpp*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-msdosdjgpp*) + echo '#define BSD_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + i[3467]86*-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i386" + ;; + i586*-*-* | \ + pentium-*-* | \ + pentiumpro-*-*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/i386/syntax.h >>./mpi/asm-syntax.h + path="i586 i386" + ;; + alpha*-*-*) + echo '/* configured for alpha */' >>./mpi/asm-syntax.h + path="alpha" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa7000*-*-*) + echo '/* configured for HPPA (pa7000) */' >>./mpi/asm-syntax.h + path="hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa1.0*-*-*) + echo '/* configured for HPPA 1.0 */' >>./mpi/asm-syntax.h + path="hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + hppa*-*-*) # assume pa7100 + echo '/* configured for HPPA (pa7100) */' >>./mpi/asm-syntax.h + path="pa7100 hppa1.1 hppa" + mpi_extra_modules="udiv-qrnnd" + ;; + sparc64-*-linux-gnu) + # An extra rule because we have an report for this one only. + # Should be compared against the next GMP version + echo '/* configured for sparc64-*-linux-gnu */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc64-sun-solaris2*) + # Got a report that udiv is missing, so we try this one + echo '/* configured for sparc64-sun-solaris2 */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc9*-*-* | \ + sparc64*-*-* | \ + ultrasparc*-*-* ) + echo '/* configured for sparc9 or higher */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + sparc8*-*-* | \ + microsparc*-*-*) + echo '/* configured for sparc8 */' >>./mpi/asm-syntax.h + path="sparc32v8 sparc32" + ;; + supersparc*-*-*) + echo '/* configured for supersparc */' >>./mpi/asm-syntax.h + path="supersparc sparc32v8 sparc32" + mpi_extra_modules="udiv" + ;; + sparc*-*-*) + echo '/* configured for sparc */' >>./mpi/asm-syntax.h + path="sparc32" + mpi_extra_modules="udiv" + ;; + mips[34]*-*-* | \ + mips*-*-irix6*) + echo '/* configured for MIPS3 */' >>./mpi/asm-syntax.h + path="mips3" + ;; + mips*-*-*) + echo '/* configured for MIPS2 */' >>./mpi/asm-syntax.h + path="mips2" + ;; + + # Motorola 68k configurations. Let m68k mean 68020-68040. + # mc68000 or mc68060 configurations need to be specified explicitly + m680[234]0*-*-linuxaout* | \ + m68k*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68060*-*-linuxaout*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m680[234]0*-*-linux* | \ + m68k*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + ;; + m68060*-*-linux*) + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k" + ;; + m68k-atari-mint) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + m68000*-*-* | \ + m68060*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68000" + ;; + m680[234]0*-*-* | \ + m68k*-*-*) + echo '#define MIT_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/m68k/syntax.h >>./mpi/asm-syntax.h + path="m68k/mc68020 m68k" + ;; + + powerpc*-*-linux*) + echo '/* configured for powerpc/ELF */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + path="powerpc32" + ;; + + powerpc*-*-netbsd* | powerpc*-*-openbsd*) + echo '/* configured {Open,Net}BSD on powerpc */' >>./mpi/asm-syntax.h + echo '#define ELF_SYNTAX' >>./mpi/asm-syntax.h + cat $srcdir/mpi/powerpc32/syntax.h >>./mpi/asm-syntax.h + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + + rs6000-*-aix[456789]* | \ + rs6000-*-aix3.2.[456789]) + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + rs6000-*-* | \ + power-*-* | \ + power2-*-*) + mpi_sflags="-Wa,-mppc" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + powerpc-ibm-aix4.2.* ) + # I am not sure about this one but a machine identified by + # powerpc-ibm-aix4.2.1.0 cannot use the powerpc32 code. + mpi_sflags="-Wa,-mpwr" + path="power" + mpi_extra_modules="udiv-w-sdiv" + ;; + ppc601-*-*) + mpi_sflags="-Wa,-mppc" + path="power powerpc32" + ;; + ppc60[234]*-*-* | \ + powerpc*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc32" + ;; + ppc620-*-* | \ + powerpc64*-*-*) + mpi_sflags="-Wa,-mppc" + path="powerpc64" + ;; + + *) + echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h + path="" + ;; +esac +else + echo '/* Assembler modules disabled on request */' >>./mpi/asm-syntax.h + path="" +fi + + +# Make sysdep.h +echo '/* created by config.links - do not edit */' >./mpi/sysdep.h +if test x$ac_cv_sys_symbol_underscore = xyes; then + cat <<EOF >>./mpi/sysdep.h +#if __STDC__ +#define C_SYMBOL_NAME(name) _##name +#else +#define C_SYMBOL_NAME(name) _/**/name +#endif +EOF +else + cat <<EOF >>./mpi/sysdep.h +#define C_SYMBOL_NAME(name) name +EOF +fi + + +# fixme: grep these modules from Makefile.in +mpi_ln_modules="${mpi_extra_modules} mpih-add1 mpih-mul1 mpih-mul2 mpih-mul3 \ + mpih-lshift mpih-rshift mpih-sub1" + +mpi_ln_objects= +mpi_ln_list= + +# try to get file to link from the assembler subdirectory and +# if this fails get it from the generic subdirectory. +path="$path generic" +for fn in $mpi_ln_modules ; do + mpi_ln_objects="$mpi_ln_objects $fn.o" + for dir in $path ; do + rm -f $srcdir/mpi/$fn.[Sc] + if test -f $srcdir/mpi/$dir/$fn.S ; then + mpi_ln_list="$mpi_ln_list mpi/$fn.S:mpi/$dir/$fn.S" + break; + elif test -f $srcdir/mpi/$dir/$fn.c ; then + mpi_ln_list="$mpi_ln_list mpi/$fn.c:mpi/$dir/$fn.c" + break; + fi + done +done + +# Same thing for the file which defines the limb size +path="$path generic" +for dir in $path ; do + rm -f $srcdir/mpi/mpi-asm-defs.h + if test -f $srcdir/mpi/$dir/mpi-asm-defs.h ; then + mpi_ln_list="$mpi_ln_list mpi/mpi-asm-defs.h:mpi/$dir/mpi-asm-defs.h" + break; + fi +done diff --git a/mpi/g10m.c b/mpi/g10m.c new file mode 100644 index 000000000..ea6696dc7 --- /dev/null +++ b/mpi/g10m.c @@ -0,0 +1,95 @@ +/* g10m.c - Wrapper for MPI + * Copyright (C) 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi.h" +#include "util.h" + +/* FIXME: The modules should use functions from libgcrypt */ + +const char *g10m_revision_string(int dummy) { return "$Revision$"; } + +MPI +g10m_new( unsigned nbits ) +{ + return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI +g10m_new_secure( unsigned nbits ) +{ + return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +void +g10m_release( MPI a ) +{ + mpi_free(a); +} + +void +g10m_resize( MPI a, unsigned nbits ) +{ + mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB ); +} + +MPI g10m_copy( MPI a ) { return mpi_copy( a ); } +void g10m_swap( MPI a, MPI b) { mpi_swap( a, b ); } +void g10m_set( MPI w, MPI u) { mpi_set( w, u ); } +void g10m_set_ui( MPI w, ulong u ) { mpi_set_ui( w, u ); } + +int g10m_cmp( MPI u, MPI v ) { return mpi_cmp( u, v ); } +int g10m_cmp_ui( MPI u, ulong v ) { return mpi_cmp_ui( u, v ); } + +void g10m_add(MPI w, MPI u, MPI v) { mpi_add( w, u, v ); } +void g10m_add_ui(MPI w, MPI u, ulong v ) { mpi_add_ui( w, u, v ); } +void g10m_sub( MPI w, MPI u, MPI v) { mpi_sub( w, u, v ); } +void g10m_sub_ui(MPI w, MPI u, ulong v ) { mpi_sub_ui( w, u, v ); } + +void g10m_mul( MPI w, MPI u, MPI v) { mpi_mul( w, u, v ); } +void g10m_mulm( MPI w, MPI u, MPI v, MPI m) { mpi_mulm( w, u, v, m ); } +void g10m_mul_2exp( MPI w, MPI u, ulong cnt) { mpi_mul_2exp( w, u, cnt ); } +void g10m_mul_ui(MPI w, MPI u, ulong v ) { mpi_mul_ui( w, u, v ); } + +void g10m_fdiv_q( MPI q, MPI d, MPI r ) { mpi_fdiv_q( q, d, r ); } + +void g10m_powm( MPI r, MPI b, MPI e, MPI m) { mpi_powm( r, b, e, m ); } + +int g10m_gcd( MPI g, MPI a, MPI b ) { return mpi_gcd( g, a, b ); } +int g10m_invm( MPI x, MPI u, MPI v ) { mpi_invm( x, u, v ); return 0; } + +unsigned g10m_get_nbits( MPI a ) { return mpi_get_nbits( a ); } + +unsigned +g10m_get_size( MPI a ) +{ + return mpi_get_nlimbs( a ) * BITS_PER_MPI_LIMB; +} + + +void +g10m_set_buffer( MPI a, const char *buffer, unsigned nbytes, int sign ) +{ + mpi_set_buffer( a, buffer, nbytes, sign ); +} + + diff --git a/mpi/generic/distfiles b/mpi/generic/distfiles new file mode 100644 index 000000000..649e829b7 --- /dev/null +++ b/mpi/generic/distfiles @@ -0,0 +1,10 @@ +mpih-add1.c +mpih-mul1.c +mpih-mul2.c +mpih-mul3.c +mpih-lshift.c +mpih-rshift.c +mpih-sub1.c +udiv-w-sdiv.c +mpi-asm-defs.h + diff --git a/mpi/generic/mpi-asm-defs.h b/mpi/generic/mpi-asm-defs.h new file mode 100644 index 000000000..13424e280 --- /dev/null +++ b/mpi/generic/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG) + + + + + + diff --git a/mpi/generic/mpih-add1.c b/mpi/generic/mpih-add1.c new file mode 100644 index 000000000..d9c3cbb66 --- /dev/null +++ b/mpi/generic/mpih-add1.c @@ -0,0 +1,65 @@ +/* mpihelp-add_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, + * 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to one addend */ + cy = y < cy; /* get out carry from that addition */ + y += x; /* add other addend */ + cy += y < x; /* get out carry from that add, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + diff --git a/mpi/generic/mpih-lshift.c b/mpi/generic/mpih-lshift.c new file mode 100644 index 000000000..fba8c052e --- /dev/null +++ b/mpi/generic/mpih-lshift.c @@ -0,0 +1,69 @@ +/* mpihelp-lshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/* Shift U (pointed to by UP and USIZE digits long) CNT bits to the left + * and store the USIZE least significant digits of the result at WP. + * Return the bits shifted out from the most significant digit. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be >= UP. + */ + +mpi_limb_t +mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned int cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp += 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + i = usize - 1; + low_limb = up[i]; + retval = low_limb >> sh_2; + high_limb = low_limb; + while( --i >= 0 ) { + low_limb = up[i]; + wp[i] = (high_limb << sh_1) | (low_limb >> sh_2); + high_limb = low_limb; + } + wp[i] = high_limb << sh_1; + + return retval; +} + + diff --git a/mpi/generic/mpih-mul1.c b/mpi/generic/mpih-mul1.c new file mode 100644 index 000000000..83a81add0 --- /dev/null +++ b/mpi/generic/mpih-mul1.c @@ -0,0 +1,61 @@ +/* mpihelp-mul_1.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + + /* The loop counter and index J goes from -S1_SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + res_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + diff --git a/mpi/generic/mpih-mul2.c b/mpi/generic/mpih-mul2.c new file mode 100644 index 000000000..ff8f998f2 --- /dev/null +++ b/mpi/generic/mpih-mul2.c @@ -0,0 +1,66 @@ +/* mpihelp-mul_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb ); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x + prod_low; + cy_limb += prod_low < x?1:0; + res_ptr[j] = prod_low; + } while ( ++j ); + return cy_limb; +} + + diff --git a/mpi/generic/mpih-mul3.c b/mpi/generic/mpih-mul3.c new file mode 100644 index 000000000..80eedcc4c --- /dev/null +++ b/mpi/generic/mpih-mul3.c @@ -0,0 +1,67 @@ +/* mpihelp-mul_3.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +mpi_limb_t +mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t cy_limb; + mpi_size_t j; + mpi_limb_t prod_high, prod_low; + mpi_limb_t x; + + /* The loop counter and index J goes from -SIZE to -1. This way + * the loop becomes faster. */ + j = -s1_size; + res_ptr -= j; + s1_ptr -= j; + + cy_limb = 0; + do { + umul_ppmm( prod_high, prod_low, s1_ptr[j], s2_limb); + + prod_low += cy_limb; + cy_limb = (prod_low < cy_limb?1:0) + prod_high; + + x = res_ptr[j]; + prod_low = x - prod_low; + cy_limb += prod_low > x?1:0; + res_ptr[j] = prod_low; + } while( ++j ); + + return cy_limb; +} + + diff --git a/mpi/generic/mpih-rshift.c b/mpi/generic/mpih-rshift.c new file mode 100644 index 000000000..be73adfb8 --- /dev/null +++ b/mpi/generic/mpih-rshift.c @@ -0,0 +1,68 @@ +/* mpih-rshift.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GNUPG + * + * GNUPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +/* Shift U (pointed to by UP and USIZE limbs long) CNT bits to the right + * and store the USIZE least significant limbs of the result at WP. + * The bits shifted out to the right are returned. + * + * Argument constraints: + * 1. 0 < CNT < BITS_PER_MP_LIMB + * 2. If the result is to be written over the input, WP must be <= UP. + */ + +mpi_limb_t +mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, unsigned cnt) +{ + mpi_limb_t high_limb, low_limb; + unsigned sh_1, sh_2; + mpi_size_t i; + mpi_limb_t retval; + + sh_1 = cnt; + wp -= 1; + sh_2 = BITS_PER_MPI_LIMB - sh_1; + high_limb = up[0]; + retval = high_limb << sh_2; + low_limb = high_limb; + for( i=1; i < usize; i++) { + high_limb = up[i]; + wp[i] = (low_limb >> sh_1) | (high_limb << sh_2); + low_limb = high_limb; + } + wp[i] = low_limb >> sh_1; + + return retval; +} + diff --git a/mpi/generic/mpih-sub1.c b/mpi/generic/mpih-sub1.c new file mode 100644 index 000000000..c618fee49 --- /dev/null +++ b/mpi/generic/mpih-sub1.c @@ -0,0 +1,65 @@ +/* mpihelp-add_2.c - MPI helper functions + * Copyright (C) 1994, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +mpi_limb_t +mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size) +{ + mpi_limb_t x, y, cy; + mpi_size_t j; + + /* The loop counter and index J goes from -SIZE to -1. This way + the loop becomes faster. */ + j = -size; + + /* Offset the base pointers to compensate for the negative indices. */ + s1_ptr -= j; + s2_ptr -= j; + res_ptr -= j; + + cy = 0; + do { + y = s2_ptr[j]; + x = s1_ptr[j]; + y += cy; /* add previous carry to subtrahend */ + cy = y < cy; /* get out carry from that addition */ + y = x - y; /* main subtract */ + cy += y > x; /* get out carry from the subtract, combine */ + res_ptr[j] = y; + } while( ++j ); + + return cy; +} + + diff --git a/mpi/generic/udiv-w-sdiv.c b/mpi/generic/udiv-w-sdiv.c new file mode 100644 index 000000000..dd0285037 --- /dev/null +++ b/mpi/generic/udiv-w-sdiv.c @@ -0,0 +1,133 @@ +/* mpihelp_udiv_w_sdiv -- implement udiv_qrnnd on machines with only signed + * division. + * Copyright (C) 1992, 1994, 1996, 1998 Free Software Foundation, Inc. + * Contributed by Peter L. Montgomery. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#if 0 /* not yet ported to MPI */ + +mpi_limb_t +mpihelp_udiv_w_sdiv( mpi_limp_t *rp, + mpi_limp_t *a1, + mpi_limp_t *a0, + mpi_limp_t *d ) +{ + mp_limb_t q, r; + mp_limb_t c0, c1, b1; + + if ((mpi_limb_signed_t) d >= 0) + { + if (a1 < d - a1 - (a0 >> (BITS_PER_MP_LIMB - 1))) + { + /* dividend, divisor, and quotient are nonnegative */ + sdiv_qrnnd (q, r, a1, a0, d); + } + else + { + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (BITS_PER_MP_LIMB - 1)); + /* Divide (c1*2^32 + c0) by d */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient */ + q += (mp_limb_t) 1 << (BITS_PER_MP_LIMB - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (BITS_PER_MP_LIMB - 1)) + (a0 >> 1); + + if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ + { + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */ + { + c1 = (b1 - 1) - c1; + c0 = ~c0; /* logical NOT */ + + sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ + + q = ~q; /* (A/2)/b1 */ + r = (b1 - 1) - r; + + r = 2*r + (a0 & 1); /* A/(2*b1) */ + + if ((d & 1) != 0) + { + if (r >= q) + r = r - q; + else if (q - r <= d) + { + r = r - q + d; + q--; + } + else + { + r = r - q + 2*d; + q -= 2; + } + } + } + else /* Implies c1 = b1 */ + { /* Hence a1 = d - 1 = 2*b1 - 1 */ + if (a0 >= -d) + { + q = -1; + r = a0 + d; + } + else + { + q = -2; + r = a0 + 2*d; + } + } + } + + *rp = r; + return q; +} + +#endif + diff --git a/mpi/hppa/README b/mpi/hppa/README new file mode 100644 index 000000000..5a2d5fd97 --- /dev/null +++ b/mpi/hppa/README @@ -0,0 +1,84 @@ +This directory contains mpn functions for various HP PA-RISC chips. Code +that runs faster on the PA7100 and later implementations, is in the pa7100 +directory. + +RELEVANT OPTIMIZATION ISSUES + + Load and Store timing + +On the PA7000 no memory instructions can issue the two cycles after a store. +For the PA7100, this is reduced to one cycle. + +The PA7100 has a lookup-free cache, so it helps to schedule loads and the +dependent instruction really far from each other. + +STATUS + +1. mpn_mul_1 could be improved to 6.5 cycles/limb on the PA7100, using the + instructions bwlow (but some sw pipelining is needed to avoid the + xmpyu-fstds delay): + + fldds s1_ptr + + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + + addc + stws res_ptr + addc + stws res_ptr + + addib Loop + +2. mpn_addmul_1 could be improved from the current 10 to 7.5 cycles/limb + (asymptotically) on the PA7100, using the instructions below. With proper + sw pipelining and the unrolling level below, the speed becomes 8 + cycles/limb. + + fldds s1_ptr + fldds s1_ptr + + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + xmpyu + fstds N(%r30) + + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + ldws N(%r30) + addc + addc + addc + addc + addc %r0,%r0,cy-limb + + ldws res_ptr + ldws res_ptr + ldws res_ptr + ldws res_ptr + add + stws res_ptr + addc + stws res_ptr + addc + stws res_ptr + addc + stws res_ptr + + addib diff --git a/mpi/hppa/distfiles b/mpi/hppa/distfiles new file mode 100644 index 000000000..7f24205d3 --- /dev/null +++ b/mpi/hppa/distfiles @@ -0,0 +1,7 @@ +README +udiv-qrnnd.S +mpih-add1.S +mpih-sub1.S +mpih-lshift.S +mpih-rshift.S + diff --git a/mpi/hppa/mpih-add1.S b/mpi/hppa/mpih-add1.S new file mode 100644 index 000000000..7a2a2c2cb --- /dev/null +++ b/mpi/hppa/mpih-add1.S @@ -0,0 +1,72 @@ +/* hppa add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Fee Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (gr26) + * mpi_ptr_t s1_ptr, (gr25) + * mpi_ptr_t s2_ptr, (gr24) + * mpi_size_t size) (gr23) + * + * One might want to unroll this as for other processors, but it turns + * out that the data cache contention after a store makes such + * unrolling useless. We can't come under 5 cycles/limb anyway. + */ + + .code + .export mpihelp_add_n + .label mpihelp_add_n + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + + addib,= -1,%r23,L$end ; check for (SIZE == 1) + add %r20,%r19,%r28 ; add first limbs ignoring cy + + .label L$loop + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + stws,ma %r28,4(0,%r26) + addib,<> -1,%r23,L$loop + addc %r20,%r19,%r28 + + .label L$end + stws %r28,0(0,%r26) + bv 0(%r2) + addc %r0,%r0,%r28 + + .exit + .procend diff --git a/mpi/hppa/mpih-lshift.S b/mpi/hppa/mpih-lshift.S new file mode 100644 index 000000000..6a8b2c4ce --- /dev/null +++ b/mpi/hppa/mpih-lshift.S @@ -0,0 +1,77 @@ +/* hppa lshift + * + * Copyright (C) 1992, 1994, 1998 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export mpihelp_lshift + .label mpihelp_lshift + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(0,%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ; compute carry out limb + ldws,mb -4(0,%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r22,%r29,%r20 + + .label L$loop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + addib,= -1,%r24,L$0003 + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,<> -1,%r24,L$loop + vshd %r22,%r29,%r20 + + .label L$0002 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + .label L$0003 + stws,mb %r20,-4(0,%r26) + .label L$0004 + vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + + .exit + .procend + + + diff --git a/mpi/hppa/mpih-rshift.S b/mpi/hppa/mpih-rshift.S new file mode 100644 index 000000000..b1e6a6795 --- /dev/null +++ b/mpi/hppa/mpih-rshift.S @@ -0,0 +1,73 @@ +/* hppa rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export mpihelp_rshift + .label mpihelp_rshift + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(0,%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$r004 + vshd %r22,%r0,%r28 ; compute carry out limb + ldws,ma 4(0,%r25),%r29 + addib,= -1,%r24,L$r002 + vshd %r29,%r22,%r20 + + .label L$roop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + addib,= -1,%r24,L$r003 + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,<> -1,%r24,L$roop + vshd %r29,%r22,%r20 + + .label L$r002 + stws,ma %r20,4(0,%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + .label L$r003 + stws,ma %r20,4(0,%r26) + .label L$r004 + vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + + .exit + .procend + diff --git a/mpi/hppa/mpih-sub1.S b/mpi/hppa/mpih-sub1.S new file mode 100644 index 000000000..870009e95 --- /dev/null +++ b/mpi/hppa/mpih-sub1.S @@ -0,0 +1,80 @@ +/* hppa sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (gr26) + * mpi_ptr_t s1_ptr, (gr25) + * mpi_ptr_t s2_ptr, (gr24) + * mpi_size_t size) (gr23) + * + * One might want to unroll this as for other processors, but it turns + * out that the data cache contention after a store makes such + * unrolling useless. We can't come under 5 cycles/limb anyway. + */ + + + .code + .export mpihelp_sub_n + .label mpihelp_sub_n + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + + addib,= -1,%r23,L$end ; check for (SIZE == 1) + sub %r20,%r19,%r28 ; subtract first limbs ignoring cy + + .label L$loop + ldws,ma 4(0,%r25),%r20 + ldws,ma 4(0,%r24),%r19 + stws,ma %r28,4(0,%r26) + addib,<> -1,%r23,L$loop + subb %r20,%r19,%r28 + + .label L$end + stws %r28,0(0,%r26) + addc %r0,%r0,%r28 + bv 0(%r2) + subi 1,%r28,%r28 + + .exit + .procend + + + diff --git a/mpi/hppa/udiv-qrnnd.S b/mpi/hppa/udiv-qrnnd.S new file mode 100644 index 000000000..c8a52412b --- /dev/null +++ b/mpi/hppa/udiv-qrnnd.S @@ -0,0 +1,298 @@ +/* HP-PA __udiv_qrnnd division support, used from longlong.h. + * This version runs fast on pre-PA7000 CPUs. + * + * Copyright (C) 1993, 1994, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +/* INPUT PARAMETERS + * rem_ptr gr26 + * n1 gr25 + * n0 gr24 + * d gr23 + * + * The code size is a bit excessive. We could merge the last two ds;addc + * sequences by simply moving the "bb,< Odd" instruction down. The only + * trouble is the FFFFFFFF code that would need some hacking. + */ + + .code + .export __udiv_qrnnd + .label __udiv_qrnnd + .proc + .callinfo frame=0,no_calls + .entry + + comb,< %r23,0,L$largedivisor + sub %r0,%r23,%r1 ; clear cy as side-effect + ds %r0,%r1,%r0 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r28 + ds %r25,%r23,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r23,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r28,%r28,%r28 + + .label L$largedivisor + extru %r24,31,1,%r19 ; r19 = n0 & 1 + bb,< %r23,31,L$odd + extru %r23,30,31,%r22 ; r22 = d >> 1 + shd %r25,%r24,1,%r24 ; r24 = new n0 + extru %r25,30,31,%r25 ; r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r19,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r24,%r24,%r28 + + .label L$odd + addib,sv,n 1,%r22,L$FF.. ; r22 = (d / 2 + 1) + shd %r25,%r24,1,%r24 ; r24 = new n0 + extru %r25,30,31,%r25 ; r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r28 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r19,%r25 +; We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25 + add,nuv %r28,%r25,%r25 + addl %r25,%r1,%r25 + addc %r0,%r28,%r28 + sub,<< %r25,%r23,%r0 + addl %r25,%r1,%r25 + stws %r25,0(0,%r26) + bv 0(%r2) + addc %r0,%r28,%r28 + +; This is just a special case of the code above. +; We come here when d == 0xFFFFFFFF + .label L$FF.. + add,uv %r25,%r24,%r24 + sub,<< %r24,%r23,%r0 + ldo 1(%r24),%r24 + stws %r24,0(0,%r26) + bv 0(%r2) + addc %r0,%r25,%r28 + + .exit + .procend diff --git a/mpi/hppa1.1/distfiles b/mpi/hppa1.1/distfiles new file mode 100644 index 000000000..d68227ac7 --- /dev/null +++ b/mpi/hppa1.1/distfiles @@ -0,0 +1,5 @@ +udiv-qrnnd.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S + diff --git a/mpi/hppa1.1/mpih-mul1.S b/mpi/hppa1.1/mpih-mul1.S new file mode 100644 index 000000000..ac9baced4 --- /dev/null +++ b/mpi/hppa1.1/mpih-mul1.S @@ -0,0 +1,115 @@ +/* hppa1.1 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (r26) + * mpi_ptr_t s1_ptr, (r25) + * mpi_size_t s1_size, (r24) + * mpi_limb_t s2_limb) (r23) + * + * + * + * This runs at 9 cycles/limb on a PA7000. With the used instructions, it can + * not become faster due to data cache contention after a store. On the + * PA7100 it runs at 7 cycles/limb, and that can not be improved either, since + * only the xmpyu does not need the integer pipeline, so the only dual-issue + * we will get are addc+xmpyu. Unrolling would not help either CPU. + * + * We could use fldds to read two limbs at a time from the S1 array, and that + * could bring down the times to 8.5 and 6.5 cycles/limb for the PA7000 and + * PA7100, respectively. We don't do that since it does not seem worth the + * (alignment) troubles... + * + * At least the PA7100 is rumored to be able to deal with cache-misses + * without stalling instruction issue. If this is true, and the cache is + * actually also lockup-free, we should use a deeper software pipeline, and + * load from S1 very early! (The loads and stores to -12(sp) will surely be + * in the cache.) + */ + + .code + .export mpihelp_mul_1 + .label mpihelp_mul_1 + .proc + .callinfo frame=64,no_calls + .entry + + ldo 64(%r30),%r30 + fldws,ma 4(%r25),%fr5 + stw %r23,-16(%r30) ; move s2_limb ... + addib,= -1,%r24,L$just_one_limb + fldws -16(%r30),%fr4 ; ... into fr4 + add %r0,%r0,%r0 ; clear carry + xmpyu %fr4,%fr5,%fr6 + fldws,ma 4(%r25),%fr7 + fstds %fr6,-16(%r30) + xmpyu %fr4,%fr7,%fr8 + ldw -12(%r30),%r19 ; least significant limb in product + ldw -16(%r30),%r28 + + fstds %fr8,-16(%r30) + addib,= -1,%r24,L$end + ldw -12(%r30),%r1 + +; Main loop + .label L$loop + fldws,ma 4(%r25),%fr5 + stws,ma %r19,4(%r26) + addc %r28,%r1,%r19 + xmpyu %fr4,%fr5,%fr6 + ldw -16(%r30),%r28 + fstds %fr6,-16(%r30) + addib,<> -1,%r24,L$loop + ldw -12(%r30),%r1 + + .label L$end + stws,ma %r19,4(%r26) + addc %r28,%r1,%r19 + ldw -16(%r30),%r28 + stws,ma %r19,4(%r26) + addc %r0,%r28,%r28 + bv 0(%r2) + ldo -64(%r30),%r30 + + .label L$just_one_limb + xmpyu %fr4,%fr5,%fr6 + fstds %fr6,-16(%r30) + ldw -16(%r30),%r28 + ldo -64(%r30),%r30 + bv 0(%r2) + fstws %fr6R,0(%r26) + + .exit + .procend + + diff --git a/mpi/hppa1.1/mpih-mul2.S b/mpi/hppa1.1/mpih-mul2.S new file mode 100644 index 000000000..c73397e3e --- /dev/null +++ b/mpi/hppa1.1/mpih-mul2.S @@ -0,0 +1,117 @@ +/* hppa1.1 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r26) + * mpi_ptr_t s1_ptr, (r25) + * mpi_size_t s1_size, (r24) + * mpi_limb_t s2_limb) (r23) + * + * This runs at 11 cycles/limb on a PA7000. With the used instructions, it + * can not become faster due to data cache contention after a store. On the + * PA7100 it runs at 10 cycles/limb, and that can not be improved either, + * since only the xmpyu does not need the integer pipeline, so the only + * dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb + * on the PA7100. + * + * There are some ideas described in mul1.S that applies to this code too. + */ + + .code + .export mpihelp_addmul_1 + .label mpihelp_addmul_1 + .proc + .callinfo frame=64,no_calls + .entry + + ldo 64(%r30),%r30 + fldws,ma 4(%r25),%fr5 + stw %r23,-16(%r30) ; move s2_limb ... + addib,= -1,%r24,L$just_one_limb + fldws -16(%r30),%fr4 ; ... into fr4 + add %r0,%r0,%r0 ; clear carry + xmpyu %fr4,%fr5,%fr6 + fldws,ma 4(%r25),%fr7 + fstds %fr6,-16(%r30) + xmpyu %fr4,%fr7,%fr8 + ldw -12(%r30),%r19 ; least significant limb in product + ldw -16(%r30),%r28 + + fstds %fr8,-16(%r30) + addib,= -1,%r24,L$end + ldw -12(%r30),%r1 + +; Main loop + .label L$loop + ldws 0(%r26),%r29 + fldws,ma 4(%r25),%fr5 + add %r29,%r19,%r19 + stws,ma %r19,4(%r26) + addc %r28,%r1,%r19 + xmpyu %fr4,%fr5,%fr6 + ldw -16(%r30),%r28 + fstds %fr6,-16(%r30) + addc %r0,%r28,%r28 + addib,<> -1,%r24,L$loop + ldw -12(%r30),%r1 + + .label L$end + ldw 0(%r26),%r29 + add %r29,%r19,%r19 + stws,ma %r19,4(%r26) + addc %r28,%r1,%r19 + ldw -16(%r30),%r28 + ldws 0(%r26),%r29 + addc %r0,%r28,%r28 + add %r29,%r19,%r19 + stws,ma %r19,4(%r26) + addc %r0,%r28,%r28 + bv 0(%r2) + ldo -64(%r30),%r30 + + .label L$just_one_limb + xmpyu %fr4,%fr5,%fr6 + ldw 0(%r26),%r29 + fstds %fr6,-16(%r30) + ldw -12(%r30),%r1 + ldw -16(%r30),%r28 + add %r29,%r1,%r19 + stw %r19,0(%r26) + addc %r0,%r28,%r28 + bv 0(%r2) + ldo -64(%r30),%r30 + + .exit + .procend + + diff --git a/mpi/hppa1.1/mpih-mul3.S b/mpi/hppa1.1/mpih-mul3.S new file mode 100644 index 000000000..f9ccb1b57 --- /dev/null +++ b/mpi/hppa1.1/mpih-mul3.S @@ -0,0 +1,127 @@ +/* hppa1.1 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (r26) + * mpi_ptr_t s1_ptr, (r25) + * mpi_size_t s1_size, (r24) + * mpi_limb_t s2_limb) (r23) + * + * + * This runs at 12 cycles/limb on a PA7000. With the used instructions, it + * can not become faster due to data cache contention after a store. On the + * PA7100 it runs at 11 cycles/limb, and that can not be improved either, + * since only the xmpyu does not need the integer pipeline, so the only + * dual-issue we will get are addc+xmpyu. Unrolling could gain a cycle/limb + * on the PA7100. + * + * There are some ideas described in mul1.S that applies to this code too. + * + * It seems possible to make this run as fast as addmul_1, if we use + * sub,>>= %r29,%r19,%r22 + * addi 1,%r28,%r28 + * but that requires reworking the hairy software pipeline... + */ + + + .code + .export mpihelp_submul_1 + .label mpihelp_submul_1 + .proc + .callinfo frame=64,no_calls + .entry + + ldo 64(%r30),%r30 + fldws,ma 4(%r25),%fr5 + stw %r23,-16(%r30) ; move s2_limb ... + addib,= -1,%r24,L$just_one_limb + fldws -16(%r30),%fr4 ; ... into fr4 + add %r0,%r0,%r0 ; clear carry + xmpyu %fr4,%fr5,%fr6 + fldws,ma 4(%r25),%fr7 + fstds %fr6,-16(%r30) + xmpyu %fr4,%fr7,%fr8 + ldw -12(%r30),%r19 ; least significant limb in product + ldw -16(%r30),%r28 + + fstds %fr8,-16(%r30) + addib,= -1,%r24,L$end + ldw -12(%r30),%r1 + +; Main loop + .label L$loop + ldws 0(%r26),%r29 + fldws,ma 4(%r25),%fr5 + sub %r29,%r19,%r22 + add %r22,%r19,%r0 + stws,ma %r22,4(%r26) + addc %r28,%r1,%r19 + xmpyu %fr4,%fr5,%fr6 + ldw -16(%r30),%r28 + fstds %fr6,-16(%r30) + addc %r0,%r28,%r28 + addib,<> -1,%r24,L$loop + ldw -12(%r30),%r1 + + .label L$end + ldw 0(%r26),%r29 + sub %r29,%r19,%r22 + add %r22,%r19,%r0 + stws,ma %r22,4(%r26) + addc %r28,%r1,%r19 + ldw -16(%r30),%r28 + ldws 0(%r26),%r29 + addc %r0,%r28,%r28 + sub %r29,%r19,%r22 + add %r22,%r19,%r0 + stws,ma %r22,4(%r26) + addc %r0,%r28,%r28 + bv 0(%r2) + ldo -64(%r30),%r30 + + .label L$just_one_limb + xmpyu %fr4,%fr5,%fr6 + ldw 0(%r26),%r29 + fstds %fr6,-16(%r30) + ldw -12(%r30),%r1 + ldw -16(%r30),%r28 + sub %r29,%r1,%r22 + add %r22,%r1,%r0 + stw %r22,0(%r26) + addc %r0,%r28,%r28 + bv 0(%r2) + ldo -64(%r30),%r30 + + .exit + .procend + diff --git a/mpi/hppa1.1/udiv-qrnnd.S b/mpi/hppa1.1/udiv-qrnnd.S new file mode 100644 index 000000000..a1643d707 --- /dev/null +++ b/mpi/hppa1.1/udiv-qrnnd.S @@ -0,0 +1,90 @@ +/* HP-PA __udiv_qrnnd division support, used from longlong.h. + * This version runs fast on PA 7000 and later. + * + * Copyright (C) 1993, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +/* INPUT PARAMETERS + * rem_ptr gr26 + * n1 gr25 + * n0 gr24 + * d gr23 + */ + + .code + .label L$0000 + .word 0x43f00000 + .word 0x0 + .export __udiv_qrnnd + .label __udiv_qrnnd + .proc + .callinfo frame=64,no_calls + .entry + ldo 64(%r30),%r30 + + stws %r25,-16(0,%r30) ; n_hi + stws %r24,-12(0,%r30) ; n_lo + ldil L'L$0000,%r19 ; ' + ldo R'L$0000(%r19),%r19 ; ' + fldds -16(0,%r30),%fr5 + stws %r23,-12(0,%r30) + comib,<= 0,%r25,L$1 + fcnvxf,dbl,dbl %fr5,%fr5 + fldds 0(0,%r19),%fr4 + fadd,dbl %fr4,%fr5,%fr5 + .label L$1 + fcpy,sgl %fr0,%fr6L + fldws -12(0,%r30),%fr6R + fcnvxf,dbl,dbl %fr6,%fr4 + + fdiv,dbl %fr5,%fr4,%fr5 + + fcnvfx,dbl,dbl %fr5,%fr4 + fstws %fr4R,-16(%r30) + xmpyu %fr4R,%fr6R,%fr6 + ldws -16(%r30),%r28 + fstds %fr6,-16(0,%r30) + ldws -12(0,%r30),%r21 + ldws -16(0,%r30),%r20 + sub %r24,%r21,%r22 + subb %r25,%r20,%r19 + comib,= 0,%r19,L$2 + ldo -64(%r30),%r30 + + add %r22,%r23,%r22 + ldo -1(%r28),%r28 + .label L$2 + bv 0(%r2) + stws %r22,0(0,%r26) + + .exit + .procend + + diff --git a/mpi/i386/distfiles b/mpi/i386/distfiles new file mode 100644 index 000000000..88d2a30c7 --- /dev/null +++ b/mpi/i386/distfiles @@ -0,0 +1,9 @@ +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +syntax.h + diff --git a/mpi/i386/mpih-add1.S b/mpi/i386/mpih-add1.S new file mode 100644 index 000000000..da7e7f8b3 --- /dev/null +++ b/mpi/i386/mpih-add1.S @@ -0,0 +1,118 @@ +/* i80386 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal Loop-3(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + adcl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + adcl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + adcl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + adcl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + adcl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + adcl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + adcl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + adcl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret + diff --git a/mpi/i386/mpih-lshift.S b/mpi/i386/mpih-lshift.S new file mode 100644 index 000000000..a7dad2c96 --- /dev/null +++ b/mpi/i386/mpih-lshift.S @@ -0,0 +1,96 @@ +/* i80386 lshift + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_lshift) +C_SYMBOL_NAME(mpihelp_lshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* res_ptr */ + movl 20(%esp),%esi /* s_ptr */ + movl 24(%esp),%edx /* size */ + movl 28(%esp),%ecx /* cnt */ + + subl $4,%esi /* adjust s_ptr */ + + movl (%esi,%edx,4),%ebx /* read most significant limb */ + xorl %eax,%eax + shldl %ebx,%eax /* compute carry limb */ + decl %edx + jz Lend + pushl %eax /* push carry limb onto stack */ + testb $1,%dl + jnz L1 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop: movl (%esi,%edx,4),%ebx /* load next lower limb */ + shldl %ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + decl %edx +L1: movl (%esi,%edx,4),%eax + shldl %eax,%ebx + movl %ebx,(%edi,%edx,4) + decl %edx + jnz Loop + + shll %cl,%eax /* compute least significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend: shll %cl,%ebx /* compute least significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/i386/mpih-mul1.S b/mpi/i386/mpih-mul1.S new file mode 100644 index 000000000..cf87046f5 --- /dev/null +++ b/mpi/i386/mpih-mul1.S @@ -0,0 +1,86 @@ +/* i80386 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i386/mpih-mul2.S b/mpi/i386/mpih-mul2.S new file mode 100644 index 000000000..f134af70e --- /dev/null +++ b/mpi/i386/mpih-mul2.S @@ -0,0 +1,88 @@ +/* i80386 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i386/mpih-mul3.S b/mpi/i386/mpih-mul3.S new file mode 100644 index 000000000..2907ed039 --- /dev/null +++ b/mpi/i386/mpih-mul3.S @@ -0,0 +1,88 @@ +/* i80386 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) +Loop: + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + INSN1(mul,l ,R(s2_limb)) + INSN2(add,l ,R(eax),R(ebx)) + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,MEM_INDEX(res_ptr,size,4),R(eax)) + INSN2(adc,l ,R(edx),$0) + INSN2(mov,l ,R(ebx),R(edx)) + + INSN1(inc,l ,R(size)) + INSN1(jnz, ,Loop) + INSN2(mov,l ,R(eax),R(ebx)) + + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i386/mpih-rshift.S b/mpi/i386/mpih-rshift.S new file mode 100644 index 000000000..4886a98ca --- /dev/null +++ b/mpi/i386/mpih-rshift.S @@ -0,0 +1,99 @@ +/* i80386 rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_rshift) +C_SYMBOL_NAME(mpihelp_rshift:) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp),%edi /* wp */ + movl 20(%esp),%esi /* up */ + movl 24(%esp),%edx /* usize */ + movl 28(%esp),%ecx /* cnt */ + + leal -4(%edi,%edx,4),%edi + leal (%esi,%edx,4),%esi + negl %edx + + movl (%esi,%edx,4),%ebx /* read least significant limb */ + xorl %eax,%eax + shrdl %ebx,%eax /* compute carry limb */ + incl %edx + jz Lend2 + pushl %eax /* push carry limb onto stack */ + testb $1,%dl + jnz L2 /* enter loop in the middle */ + movl %ebx,%eax + + ALIGN (3) +Loop2: movl (%esi,%edx,4),%ebx /* load next higher limb */ + shrdl %ebx,%eax /* compute result limb */ + movl %eax,(%edi,%edx,4) /* store it */ + incl %edx +L2: movl (%esi,%edx,4),%eax + shrdl %eax,%ebx + movl %ebx,(%edi,%edx,4) + incl %edx + jnz Loop2 + + shrl %cl,%eax /* compute most significant limb */ + movl %eax,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebx + popl %esi + popl %edi + ret + +Lend2: shrl %cl,%ebx /* compute most significant limb */ + movl %ebx,(%edi) /* store it */ + + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/i386/mpih-sub1.S b/mpi/i386/mpih-sub1.S new file mode 100644 index 000000000..2339334fe --- /dev/null +++ b/mpi/i386/mpih-sub1.S @@ -0,0 +1,119 @@ +/* i80386 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001, 2002 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_sub_n) +C_SYMBOL_NAME(mpihelp_sub_n:) + pushl %edi + pushl %esi + + movl 12(%esp),%edi /* res_ptr */ + movl 16(%esp),%esi /* s1_ptr */ + movl 20(%esp),%edx /* s2_ptr */ + movl 24(%esp),%ecx /* size */ + + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz Loop /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. Due to limitations in some + assemblers, Loop-L0-3 cannot be put into the leal */ + call L0 +L0: leal (%eax,%eax,8),%eax + addl (%esp),%eax + addl $(Loop-L0-3),%eax + addl $4,%esp +#else +/* Calculate start address in loop for non-PIC. */ + leal Loop-3(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +Loop: movl (%esi),%eax + sbbl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + sbbl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + sbbl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + sbbl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + sbbl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + sbbl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + sbbl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + sbbl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz Loop + + sbbl %eax,%eax + negl %eax + + popl %esi + popl %edi + ret + diff --git a/mpi/i386/syntax.h b/mpi/i386/syntax.h new file mode 100644 index 000000000..035c01960 --- /dev/null +++ b/mpi/i386/syntax.h @@ -0,0 +1,68 @@ +/* syntax.h -- Definitions for x86 syntax variations. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#undef ALIGN + +#if defined (BSD_SYNTAX) || defined (ELF_SYNTAX) +#define R(r) %r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)displacement(R(base)) +#define MEM_INDEX(base,index,size)(R(base),R(index),size) +#ifdef __STDC__ +#define INSN1(mnemonic,size_suffix,dst)mnemonic##size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic##size_suffix src,dst +#else +#define INSN1(mnemonic,size_suffix,dst)mnemonic/**/size_suffix dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic/**/size_suffix src,dst +#endif +#define TEXT .text +#if defined (BSD_SYNTAX) +#define ALIGN(log) .align log +#endif +#if defined (ELF_SYNTAX) +#define ALIGN(log) .align 1<<log +#endif +#define GLOBL .globl +#endif + +#ifdef INTEL_SYNTAX +#define R(r) r +#define MEM(base)[base] +#define MEM_DISP(base,displacement)[base+(displacement)] +#define MEM_INDEX(base,index,size)[base+index*size] +#define INSN1(mnemonic,size_suffix,dst)mnemonic dst +#define INSN2(mnemonic,size_suffix,dst,src)mnemonic dst,src +#define TEXT .text +#define ALIGN(log) .align log +#define GLOBL .globl +#endif + +#ifdef X86_BROKEN_ALIGN +#undef ALIGN +#define ALIGN(log) .align log,0x90 +#endif diff --git a/mpi/i586/README b/mpi/i586/README new file mode 100644 index 000000000..d73b08268 --- /dev/null +++ b/mpi/i586/README @@ -0,0 +1,26 @@ +This directory contains mpn functions optimized for Intel Pentium +processors. + +RELEVANT OPTIMIZATION ISSUES + +1. Pentium doesn't allocate cache lines on writes, unlike most other modern +processors. Since the functions in the mpn class do array writes, we have to +handle allocating the destination cache lines by reading a word from it in the +loops, to achieve the best performance. + +2. Pairing of memory operations requires that the two issued operations refer +to different cache banks. The simplest way to insure this is to read/write +two words from the same object. If we make operations on different objects, +they might or might not be to the same cache bank. + +STATUS + +1. mpn_lshift and mpn_rshift run at about 6 cycles/limb, but the Pentium +documentation indicates that they should take only 43/8 = 5.375 cycles/limb, +or 5 cycles/limb asymptotically. + +2. mpn_add_n and mpn_sub_n run at asymptotically 2 cycles/limb. Due to loop +overhead and other delays (cache refill?), they run at or near 2.5 cycles/limb. + +3. mpn_mul_1, mpn_addmul_1, mpn_submul_1 all run 1 cycle faster than they +should... diff --git a/mpi/i586/distfiles b/mpi/i586/distfiles new file mode 100644 index 000000000..8f821fbfb --- /dev/null +++ b/mpi/i586/distfiles @@ -0,0 +1,9 @@ +mpih-add1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpih-sub1.S +README + diff --git a/mpi/i586/mpih-add1.S b/mpi/i586/mpih-add1.S new file mode 100644 index 000000000..248b0c0b2 --- /dev/null +++ b/mpi/i586/mpih-add1.S @@ -0,0 +1,135 @@ +/* i80586 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + adcl %ebx,%eax + movl 4(%ebp),%ebx + adcl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + adcl %ebx,%eax + movl 12(%ebp),%ebx + adcl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + adcl %ebx,%eax + movl 20(%ebp),%ebx + adcl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %ebx,%eax + movl 28(%ebp),%ebx + adcl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + adcl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + adcl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff --git a/mpi/i586/mpih-lshift.S b/mpi/i586/mpih-lshift.S new file mode 100644 index 000000000..ed040912d --- /dev/null +++ b/mpi/i586/mpih-lshift.S @@ -0,0 +1,231 @@ +/* i80586 lshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_lshift) +C_SYMBOL_NAME(mpihelp_lshift:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Lnormal + leal 4(%esi),%eax + cmpl %edi,%eax + jnc Lspecial /* jump if s_ptr + 1 >= res_ptr */ + leal (%esi,%ebp,4),%eax + cmpl %eax,%edi + jnc Lspecial /* jump if res_ptr >= s_ptr + size */ + +Lnormal: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + xorl %eax,%eax + shldl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Lend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Loop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + shldl %cl,%ebx,%edx + shldl %cl,%eax,%ebx + movl %edx,-8(%edi) + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + shldl %cl,%edx,%eax + shldl %cl,%ebx,%edx + movl %eax,-16(%edi) + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + shldl %cl,%eax,%ebx + shldl %cl,%edx,%eax + movl %ebx,-24(%edi) + movl %eax,-28(%edi) + + subl $32,%esi + subl $32,%edi + decl %ebp + jnz Loop + +Lend: popl %ebp + andl $7,%ebp + jz Lend2 +Loop2: movl (%esi),%eax + shldl %cl,%eax,%edx + movl %edx,(%edi) + movl %eax,%edx + subl $4,%esi + subl $4,%edi + decl %ebp + jnz Loop2 + +Lend2: shll %cl,%edx /* compute least significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Lspecial: + movl (%esi),%edx + addl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + addl %edx,%edx + incl %ebp + decl %ebp + jz LLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +LLoop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + adcl %eax,%eax + movl %ebx,(%edi) + adcl %edx,%edx + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + adcl %ebx,%ebx + movl %edx,8(%edi) + adcl %eax,%eax + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + adcl %edx,%edx + movl %eax,16(%edi) + adcl %ebx,%ebx + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + adcl %eax,%eax + movl %ebx,24(%edi) + adcl %edx,%edx + movl %eax,28(%edi) + + leal 32(%esi),%esi /* use leal not to clobber carry */ + leal 32(%edi),%edi + decl %ebp + jnz LLoop + +LLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz LLend2 + addl %eax,%eax /* restore carry from eax */ +LLoop2: movl %edx,%ebx + movl (%esi),%edx + adcl %edx,%edx + movl %ebx,(%edi) + + leal 4(%esi),%esi /* use leal not to clobber carry */ + leal 4(%edi),%edi + decl %ebp + jnz LLoop2 + + jmp LL1 +LLend2: addl %eax,%eax /* restore carry from eax */ +LL1: movl %edx,(%edi) /* store last limb */ + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + + diff --git a/mpi/i586/mpih-mul1.S b/mpi/i586/mpih-mul1.S new file mode 100644 index 000000000..42bcde6bd --- /dev/null +++ b/mpi/i586/mpih-mul1.S @@ -0,0 +1,91 @@ +/* i80586 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-mul2.S b/mpi/i586/mpih-mul2.S new file mode 100644 index 000000000..54c5df96b --- /dev/null +++ b/mpi/i586/mpih-mul2.S @@ -0,0 +1,95 @@ +/* i80586 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(add,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-mul3.S b/mpi/i586/mpih-mul3.S new file mode 100644 index 000000000..0d61ff267 --- /dev/null +++ b/mpi/i586/mpih-mul3.S @@ -0,0 +1,95 @@ +/* i80586 submul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + +#define res_ptr edi +#define s1_ptr esi +#define size ecx +#define s2_limb ebp + + TEXT + ALIGN (3) + GLOBL C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1:) + + INSN1(push,l ,R(edi)) + INSN1(push,l ,R(esi)) + INSN1(push,l ,R(ebx)) + INSN1(push,l ,R(ebp)) + + INSN2(mov,l ,R(res_ptr),MEM_DISP(esp,20)) + INSN2(mov,l ,R(s1_ptr),MEM_DISP(esp,24)) + INSN2(mov,l ,R(size),MEM_DISP(esp,28)) + INSN2(mov,l ,R(s2_limb),MEM_DISP(esp,32)) + + INSN2(lea,l ,R(res_ptr),MEM_INDEX(res_ptr,size,4)) + INSN2(lea,l ,R(s1_ptr),MEM_INDEX(s1_ptr,size,4)) + INSN1(neg,l ,R(size)) + INSN2(xor,l ,R(ebx),R(ebx)) + ALIGN (3) + +Loop: INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),MEM_INDEX(s1_ptr,size,4)) + + INSN1(mul,l ,R(s2_limb)) + + INSN2(add,l ,R(eax),R(ebx)) + INSN2(mov,l ,R(ebx),MEM_INDEX(res_ptr,size,4)) + + INSN2(adc,l ,R(edx),$0) + INSN2(sub,l ,R(ebx),R(eax)) + + INSN2(mov,l ,MEM_INDEX(res_ptr,size,4),R(ebx)) + INSN1(inc,l ,R(size)) + + INSN2(mov,l ,R(ebx),R(edx)) + INSN1(jnz, ,Loop) + + INSN2(adc,l ,R(ebx),$0) + INSN2(mov,l ,R(eax),R(ebx)) + INSN1(pop,l ,R(ebp)) + INSN1(pop,l ,R(ebx)) + INSN1(pop,l ,R(esi)) + INSN1(pop,l ,R(edi)) + ret + diff --git a/mpi/i586/mpih-rshift.S b/mpi/i586/mpih-rshift.S new file mode 100644 index 000000000..2e3316216 --- /dev/null +++ b/mpi/i586/mpih-rshift.S @@ -0,0 +1,230 @@ +/* i80586 rshift + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_rshift) +C_SYMBOL_NAME(mpihelp_rshift:) + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s_ptr */ + movl 28(%esp),%ebp /* size */ + movl 32(%esp),%ecx /* cnt */ + +/* We can use faster code for shift-by-1 under certain conditions. */ + cmp $1,%ecx + jne Rnormal + leal 4(%edi),%eax + cmpl %esi,%eax + jnc Rspecial /* jump if res_ptr + 1 >= s_ptr */ + leal (%edi,%ebp,4),%eax + cmpl %eax,%esi + jnc Rspecial /* jump if s_ptr >= res_ptr + size */ + +Rnormal: + movl (%esi),%edx + addl $4,%esi + xorl %eax,%eax + shrdl %cl,%edx,%eax /* compute carry limb */ + pushl %eax /* push carry limb onto stack */ + + decl %ebp + pushl %ebp + shrl $3,%ebp + jz Rend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +Roop: movl 28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl 4(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,(%edi) + movl %eax,4(%edi) + + movl 8(%esi),%ebx + movl 12(%esi),%eax + shrdl %cl,%ebx,%edx + shrdl %cl,%eax,%ebx + movl %edx,8(%edi) + movl %ebx,12(%edi) + + movl 16(%esi),%edx + movl 20(%esi),%ebx + shrdl %cl,%edx,%eax + shrdl %cl,%ebx,%edx + movl %eax,16(%edi) + movl %edx,20(%edi) + + movl 24(%esi),%eax + movl 28(%esi),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + movl %ebx,24(%edi) + movl %eax,28(%edi) + + addl $32,%esi + addl $32,%edi + decl %ebp + jnz Roop + +Rend: popl %ebp + andl $7,%ebp + jz Rend2 +Roop2: movl (%esi),%eax + shrdl %cl,%eax,%edx /* compute result limb */ + movl %edx,(%edi) + movl %eax,%edx + addl $4,%esi + addl $4,%edi + decl %ebp + jnz Roop2 + +Rend2: shrl %cl,%edx /* compute most significant limb */ + movl %edx,(%edi) /* store it */ + + popl %eax /* pop carry limb */ + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. +*/ + +Rspecial: + leal -4(%edi,%ebp,4),%edi + leal -4(%esi,%ebp,4),%esi + + movl (%esi),%edx + subl $4,%esi + + decl %ebp + pushl %ebp + shrl $3,%ebp + + shrl $1,%edx + incl %ebp + decl %ebp + jz RLend + + movl (%edi),%eax /* fetch destination cache line */ + + ALIGN (2) +RLoop: movl -28(%edi),%eax /* fetch destination cache line */ + movl %edx,%ebx + + movl (%esi),%eax + movl -4(%esi),%edx + rcrl $1,%eax + movl %ebx,(%edi) + rcrl $1,%edx + movl %eax,-4(%edi) + + movl -8(%esi),%ebx + movl -12(%esi),%eax + rcrl $1,%ebx + movl %edx,-8(%edi) + rcrl $1,%eax + movl %ebx,-12(%edi) + + movl -16(%esi),%edx + movl -20(%esi),%ebx + rcrl $1,%edx + movl %eax,-16(%edi) + rcrl $1,%ebx + movl %edx,-20(%edi) + + movl -24(%esi),%eax + movl -28(%esi),%edx + rcrl $1,%eax + movl %ebx,-24(%edi) + rcrl $1,%edx + movl %eax,-28(%edi) + + leal -32(%esi),%esi /* use leal not to clobber carry */ + leal -32(%edi),%edi + decl %ebp + jnz RLoop + +RLend: popl %ebp + sbbl %eax,%eax /* save carry in %eax */ + andl $7,%ebp + jz RLend2 + addl %eax,%eax /* restore carry from eax */ +RLoop2: movl %edx,%ebx + movl (%esi),%edx + rcrl $1,%edx + movl %ebx,(%edi) + + leal -4(%esi),%esi /* use leal not to clobber carry */ + leal -4(%edi),%edi + decl %ebp + jnz RLoop2 + + jmp RL1 +RLend2: addl %eax,%eax /* restore carry from eax */ +RL1: movl %edx,(%edi) /* store last limb */ + + movl $0,%eax + rcrl $1,%eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/i586/mpih-sub1.S b/mpi/i586/mpih-sub1.S new file mode 100644 index 000000000..a54be0e91 --- /dev/null +++ b/mpi/i586/mpih-sub1.S @@ -0,0 +1,144 @@ +/* i80586 sub_n -- Sub two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 12) + * mpi_size_t size) (sp + 16) + */ + + +.text + ALIGN (3) + .globl C_SYMBOL_NAME(mpihelp_sub_n) +C_SYMBOL_NAME(mpihelp_sub_n:) + + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl 20(%esp),%edi /* res_ptr */ + movl 24(%esp),%esi /* s1_ptr */ + movl 28(%esp),%ebp /* s2_ptr */ + movl 32(%esp),%ecx /* size */ + + movl (%ebp),%ebx + + decl %ecx + movl %ecx,%edx + shrl $3,%ecx + andl $7,%edx + testl %ecx,%ecx /* zero carry flag */ + jz Lend + pushl %edx + + ALIGN (3) +Loop: movl 28(%edi),%eax /* fetch destination cache line */ + leal 32(%edi),%edi + +L1: movl (%esi),%eax + movl 4(%esi),%edx + sbbl %ebx,%eax + movl 4(%ebp),%ebx + sbbl %ebx,%edx + movl 8(%ebp),%ebx + movl %eax,-32(%edi) + movl %edx,-28(%edi) + +L2: movl 8(%esi),%eax + movl 12(%esi),%edx + sbbl %ebx,%eax + movl 12(%ebp),%ebx + sbbl %ebx,%edx + movl 16(%ebp),%ebx + movl %eax,-24(%edi) + movl %edx,-20(%edi) + +L3: movl 16(%esi),%eax + movl 20(%esi),%edx + sbbl %ebx,%eax + movl 20(%ebp),%ebx + sbbl %ebx,%edx + movl 24(%ebp),%ebx + movl %eax,-16(%edi) + movl %edx,-12(%edi) + +L4: movl 24(%esi),%eax + movl 28(%esi),%edx + sbbl %ebx,%eax + movl 28(%ebp),%ebx + sbbl %ebx,%edx + movl 32(%ebp),%ebx + movl %eax,-8(%edi) + movl %edx,-4(%edi) + + leal 32(%esi),%esi + leal 32(%ebp),%ebp + decl %ecx + jnz Loop + + popl %edx +Lend: + decl %edx /* test %edx w/o clobbering carry */ + js Lend2 + incl %edx +Loop2: + leal 4(%edi),%edi + movl (%esi),%eax + sbbl %ebx,%eax + movl 4(%ebp),%ebx + movl %eax,-4(%edi) + leal 4(%esi),%esi + leal 4(%ebp),%ebp + decl %edx + jnz Loop2 +Lend2: + movl (%esi),%eax + sbbl %ebx,%eax + movl %eax,(%edi) + + sbbl %eax,%eax + negl %eax + + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + diff --git a/mpi/longlong.h b/mpi/longlong.h new file mode 100644 index 000000000..6cfb8c8ce --- /dev/null +++ b/mpi/longlong.h @@ -0,0 +1,1499 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Note: I added some stuff for use with gnupg + +Copyright (C) 1991, 1992, 1993, 1994, 1996, 1998, + 2000, 2001 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify +it under the terms of the GNU Library General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public +License for more details. + +You should have received a copy of the GNU Library General Public License +along with this file; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +/* This is used to make sure no undesirable sharing between different libraries + that use this file takes place. */ +#ifndef __MPN +#define __MPN(x) __##x +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first non-zero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! */ + +#ifdef __riscos__ +#pragma continue_after_hash_error +#else /* !__riscos__ */ +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + + +/*************************************** + ************** A29K ***************** + ***************************************/ +#if (defined (__a29k__) || defined (_AM29K)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %1,%4,%5 + addc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %1,%4,%5 + subc %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("multiplu %0,%1,%2" \ + : "=r" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + __asm__ ("multmu %0,%1,%2" \ + : "=r" ((USItype)(xh)) \ + : "r" (__m0), \ + "r" (__m1)); \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("dividu %0,%3,%4" \ + : "=r" ((USItype)(q)), \ + "=q" ((USItype)(r)) \ + : "1" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* __a29k__ */ + + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#endif /* __alpha */ + +/*************************************** + ************** ARM ****************** + ***************************************/ +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5 + adc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5 + sbc %0, %2, %3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "r" ((USItype)(al)), \ + "rI" ((USItype)(bl))) +#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm + mov %|r0, %2, lsr #16 @ AAAA + mov %|r2, %3, lsr #16 @ BBBB + bic %|r1, %2, %|r0, lsl #16 @ aaaa + bic %0, %3, %|r2, lsl #16 @ bbbb + mul %1, %|r1, %|r2 @ aaaa * BBBB + mul %|r2, %|r0, %|r2 @ AAAA * BBBB + mul %|r1, %0, %|r1 @ aaaa * bbbb + mul %0, %|r0, %0 @ AAAA * bbbb + adds %|r0, %1, %0 @ central sum + addcs %|r2, %|r2, #65536 + adds %1, %|r1, %|r0, lsl #16 + adc %0, %|r2, %|r0, lsr #16" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1", "r2") +#else +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("%@ Inlined umul_ppmm + umull %r1, %r0, %r2, %r3" \ + : "=&r" ((USItype)(xh)), \ + "=r" ((USItype)(xl)) \ + : "r" ((USItype)(a)), \ + "r" ((USItype)(b)) \ + : "r0", "r1") +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +/*************************************** + ************** CLIPPER ************** + ***************************************/ +#if defined (__clipper__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define smul_ppmm(w1, w0, u, v) \ + ({union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("mulwx %2,%0" \ + : "=r" (__xx.__ll) \ + : "%0" ((SItype)(u)), \ + "r" ((SItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("mulwux %2,%0" \ + : "=r" (__w) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))); \ + __w; }) +#endif /* __clipper__ */ + + +/*************************************** + ************** GMICRO *************** + ***************************************/ +#if defined (__gmicro__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.w %5,%1 + addx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.w %5,%1 + subx %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + __asm__ ("mulx %3,%0,%1" \ + : "=g" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%0" ((USItype)(m0)), \ + "g" ((USItype)(m1))) +#define udiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("divx %4,%0,%1" \ + : "=g" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "1" ((USItype)(nh)), \ + "0" ((USItype)(nl)), \ + "g" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bsch/1 %1,%0" \ + : "=g" (count) \ + : "g" ((USItype)(x)), \ + "0" ((USItype)0)) +#endif + + +/*************************************** + ************** HPPA ***************** + ***************************************/ +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1 + addc %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "%rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1 + subb %2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rM" ((USItype)(ah)), \ + "rM" ((USItype)(bh)), \ + "rM" ((USItype)(al)), \ + "rM" ((USItype)(bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=*f" (__xx.__ll) \ + : "*f" ((USItype)(u)), \ + "*f" ((USItype)(v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define UMUL_TIME 8 +#define UDIV_TIME 60 +#else +#define UMUL_TIME 40 +#define UDIV_TIME 80 +#endif +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#endif /* LONGLONG_STANDALONE */ +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0 + extru,= %1,15,16,%%r0 ; Bits 31..16 zero? + extru,tr %1,15,16,%1 ; No. Shift down, skip add. + ldo 16(%0),%0 ; Yes. Perform add. + extru,= %1,23,8,%%r0 ; Bits 15..8 zero? + extru,tr %1,23,8,%1 ; No. Shift down, skip add. + ldo 8(%0),%0 ; Yes. Perform add. + extru,= %1,27,4,%%r0 ; Bits 7..4 zero? + extru,tr %1,27,4,%1 ; No. Shift down, skip add. + ldo 4(%0),%0 ; Yes. Perform add. + extru,= %1,29,2,%%r0 ; Bits 3..2 zero? + extru,tr %1,29,2,%1 ; No. Shift down, skip add. + ldo 2(%0),%0 ; Yes. Perform add. + extru %1,30,1,%1 ; Extract bit 1. + sub %0,%1,%0 ; Subtract it. + " : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif /* hppa */ + + +/*************************************** + ************** I370 ***************** + ***************************************/ +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + + +/*************************************** + ************** I386 ***************** + ***************************************/ +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1 + adcl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1 + sbbl %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "rm" ((USItype)(v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divl %4" \ + : "=a" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "rm" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#ifndef UMUL_TIME +#define UMUL_TIME 40 +#endif +#ifndef UDIV_TIME +#define UDIV_TIME 40 +#endif +#endif /* 80x86 */ + + +/*************************************** + ************** I860 ***************** + ***************************************/ +#if defined (__i860__) && W_TYPE_SIZE == 32 +#define rshift_rhlc(r,h,l,c) \ + __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0" \ + "=r" (r) : "r" (h), "r" (l), "rn" (c)) +#endif /* i860 */ + +/*************************************** + ************** I960 ***************** + ***************************************/ +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "%dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "dI" ((USItype)(ah)), \ + "dI" ((USItype)(bh)), \ + "dI" ((USItype)(al)), \ + "dI" ((USItype)(bl))) +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype)(u)), \ + "dI" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (nh); __nn.__i.__l = (nl); \ + __asm__ ("ediv %d,%n,%0" \ + : "=d" (__rq.__ll) \ + : "dI" (__nn.__ll), \ + "dI" ((USItype)(d))); \ + (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ + } while (0) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("scanbit %1,%0" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 (-32) /* sic */ +#if defined (__i960mx) /* what is the proper symbol to test??? */ +#define rshift_rhlc(r,h,l,c) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __nn; \ + __nn.__i.__h = (h); __nn.__i.__l = (l); \ + __asm__ ("shre %2,%1,%0" \ + : "=d" (r) : "dI" (__nn.__ll), "dI" (c)); \ + } +#endif /* i960mx */ +#endif /* i960 */ + + +/*************************************** + ************** 68000 **************** + ***************************************/ +#if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1 + addx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1 + subx%.l %3,%0" \ + : "=d" ((USItype)(sh)), \ + "=&d" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "d" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype)(q)), \ + "=d" ((USItype)(r)) \ + : "0" ((USItype)(n0)), \ + "1" ((USItype)(n1)), \ + "dmi" ((USItype)(d))) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype)(count)) \ + : "od" ((USItype)(x)), "n" (0)) +#define COUNT_LEADING_ZEROS_0 32 +#else /* not mc68020 */ +#define umul_ppmm(xh, xl, a, b) \ + do { USItype __umul_tmp1, __umul_tmp2; \ + __asm__ ("| Inlined umul_ppmm + move%.l %5,%3 + move%.l %2,%0 + move%.w %3,%1 + swap %3 + swap %0 + mulu %2,%1 + mulu %3,%0 + mulu %2,%3 + swap %2 + mulu %5,%2 + add%.l %3,%2 + jcc 1f + add%.l %#0x10000,%0 +1: move%.l %2,%3 + clr%.w %2 + swap %2 + swap %3 + clr%.w %3 + add%.l %3,%1 + addx%.l %2,%0 + | End inlined umul_ppmm" \ + : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)), \ + "=d" (__umul_tmp1), "=&d" (__umul_tmp2) \ + : "%2" ((USItype)(a)), "d" ((USItype)(b))); \ + } while (0) +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mc68020 */ +#endif /* mc68000 */ + + +/*************************************** + ************** 88000 **************** + ***************************************/ +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5 + addu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5 + subu.ci %0,%r2,%r3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rJ" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rJ" ((USItype)(bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype)(x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__m88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("mulu.d %0,%1,%2" : "=r" (__x.__ll) : "r" (u), "r" (v)); \ + (wh) = __x.__i.__h; \ + (wl) = __x.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x, __q; \ + __x.__i.__h = (n1); __x.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q.__ll) : "r" (__x.__ll), "r" (d)); \ + (r) = (n0) - __q.__l * (d); (q) = __q.__l; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __m88110__ */ +#endif /* __m88000__ */ + + +/*************************************** + ************** MIPS ***************** + ***************************************/ +#if defined (__mips__) && W_TYPE_SIZE == 32 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype)(w0)), \ + "=h" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "d" ((USItype)(u)), \ + "d" ((USItype)(v))) +#endif +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +/*************************************** + ************** MIPS/64 ************** + ***************************************/ +#if (defined (__mips) && __mips >= 3) && W_TYPE_SIZE == 64 +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3" \ + : "=l" ((UDItype)(w0)), \ + "=h" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#else +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("dmultu %2,%3 + mflo %0 + mfhi %1" \ + : "=d" ((UDItype)(w0)), \ + "=d" ((UDItype)(w1)) \ + : "d" ((UDItype)(u)), \ + "d" ((UDItype)(v))) +#endif +#define UMUL_TIME 20 +#define UDIV_TIME 140 +#endif /* __mips__ */ + + +/*************************************** + ************** 32000 **************** + ***************************************/ +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype)(u)), \ + "g" ((USItype)(v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype)(d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + + +/*************************************** + ************** PPC ****************** + ***************************************/ +#if (defined (_ARCH_PPC) || defined (_IBMR2)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%r" ((USItype)(al)), \ + "rI" ((USItype)(bl))); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "r" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "rI" ((USItype)(al)), \ + "r" ((USItype)(bl))); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" \ + : "=r" ((USItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" \ + : "=r" ((SItype) ph) \ + : "%r" (__m0), \ + "r" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#else +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((USItype)(xh)), \ + "=q" ((USItype)(xl)) \ + : "r" (__m0), \ + "r" (__m1)); \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" \ + : "=r" ((SItype)(xh)), \ + "=q" ((SItype)(xl)) \ + : "r" (m0), \ + "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" \ + : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \ + : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d))) +#define UDIV_TIME 100 +#endif +#endif /* Power architecture variants. */ + + +/*************************************** + ************** PYR ****************** + ***************************************/ +#if defined (__pyr__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addw %5,%1 + addwc %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subw %5,%1 + subwb %3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */ +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("movw %1,%R0 + uemul %2,%0" \ + : "=&r" (__xx.__ll) \ + : "g" ((USItype) (u)), \ + "g" ((USItype)(v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#endif /* __pyr__ */ + + +/*************************************** + ************** RT/ROMP ************** + ***************************************/ +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5 + ae %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5 + se %0,%3" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "r" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "r" ((USItype)(bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2 + mts r10,%2 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + m r2,%3 + cas %0,r2,r0 + mfs r10,%1" \ + : "=r" ((USItype)(ph)), \ + "=r" ((USItype)(pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype)(count)) \ + : "r" ((USItype)(x))); \ + (count) += 16; \ + } \ + } while (0) +#endif /* RT/ROMP */ + + +/*************************************** + ************** SH2 ****************** + ***************************************/ +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3 + sts macl,%1 + sts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/*************************************** + ************** SPARC **************** + ***************************************/ +#if defined (__sparc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1 + addx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "%rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "%rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1 + subx %r2,%3,%0" \ + : "=r" ((USItype)(sh)), \ + "=&r" ((USItype)(sl)) \ + : "rJ" ((USItype)(ah)), \ + "rI" ((USItype)(bh)), \ + "rJ" ((USItype)(al)), \ + "rI" ((USItype)(bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +/* Don't match immediate range because, 1) it is not often useful, + 2) the 'I' flag thinks of the range as a 13 bit signed interval, + while we want to match a 13 bit interval, sign extended to 32 bits, + but INTERPRETED AS UNSIGNED. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#ifndef SUPERSPARC /* SuperSPARC's udiv only handles 53 bit dividends */ +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + USItype __q; \ + __asm__ ("mov %1,%%y;nop;nop;nop;udiv %2,%3,%0" \ + : "=r" ((USItype)(__q)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "r" ((USItype)(d))); \ + (r) = (n0) - __q * (d); \ + (q) = __q; \ + } while (0) +#define UDIV_TIME 25 +#endif /* SUPERSPARC */ +#else /* ! __sparc_v8__ */ +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v))) +#define UMUL_TIME 5 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd + wr %%g0,%2,%%y ! Not a delayed write for sparclite + tst %%g0 + divscc %3,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%%g1 + divscc %%g1,%4,%0 + rd %%y,%1 + bl,a 1f + add %1,%4,%1 +1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype)(q)), \ + "=r" ((USItype)(r)) \ + : "r" ((USItype)(n1)), \ + "r" ((USItype)(n0)), \ + "rI" ((USItype)(d)) \ + : "%g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + __asm__ ("scan %1,0,%0" \ + : "=r" ((USItype)(x)) \ + : "r" ((USItype)(count))) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +/* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ +#ifndef umul_ppmm +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm + wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr + sra %3,31,%%g2 ! Don't move this insn + and %2,%%g2,%%g2 ! Don't move this insn + andcc %%g0,0,%%g1 ! Don't move this insn + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,%3,%%g1 + mulscc %%g1,0,%%g1 + add %%g1,%%g2,%0 + rd %%y,%1" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "%rI" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "%g1", "%g2" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +#endif +#ifndef udiv_qrnnd +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { USItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern USItype __udiv_qrnnd (); +#define UDIV_TIME 140 +#endif /* LONGLONG_STANDALONE */ +#endif /* udiv_qrnnd */ +#endif /* __sparc__ */ + + +/*************************************** + ************** VAX ****************** + ***************************************/ +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1 + adwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "%0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "%1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1 + sbwc %3,%0" \ + : "=g" ((USItype)(sh)), \ + "=&g" ((USItype)(sl)) \ + : "0" ((USItype)(ah)), \ + "g" ((USItype)(bh)), \ + "1" ((USItype)(al)), \ + "g" ((USItype)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=g" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + + +/*************************************** + ************** Z8000 **************** + ***************************************/ +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ +#endif /* !__riscos__ */ + + +/*************************************** + *********** Generic Versions ******** + ***************************************/ +#if !defined (umul_ppmm) && defined (__umulsidi3) +#define umul_ppmm(ph, pl, m0, m1) \ + { \ + UDWtype __ll = __umulsidi3 (m0, m1); \ + ph = (UWtype) (__ll >> W_TYPE_SIZE); \ + pl = (UWtype) __ll; \ + } +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({UWtype __hi, __lo; \ + umul_ppmm (__hi, __lo, u, v); \ + ((UDWtype) __hi << W_TYPE_SIZE) | __lo; }) +#endif + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + UWtype __u = (u), __v = (v); \ + \ + __ul = __ll_lowpart (__u); \ + __uh = __ll_highpart (__u); \ + __vl = __ll_lowpart (__v); \ + __vh = __ll_highpart (__v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = (__ll_lowpart (__x1) << W_TYPE_SIZE/2) + __ll_lowpart (__x0);\ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define smul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __m0 = (u), __m1 = (v); \ + umul_ppmm (__w1, w0, __m0, __m1); \ + (w1) = __w1 - (-(__m0 >> (W_TYPE_SIZE - 1)) & __m1) \ + - (-(__m1 >> (W_TYPE_SIZE - 1)) & __m0); \ + } while (0) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + UWtype __r; \ + (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern +#ifdef __STDC__ +const +#endif +unsigned char __clz_tab[]; +#define MPI_INTERNAL_NEED_CLZ_TAB 1 +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype) 1 << 2*__BITS4) \ + ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4);\ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +/* This version gives a well-defined value for zero. */ +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/mpi/m68k/distfiles b/mpi/m68k/distfiles new file mode 100644 index 000000000..4c0967b84 --- /dev/null +++ b/mpi/m68k/distfiles @@ -0,0 +1,8 @@ +syntax.h +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +mpih-sub1.S + + + diff --git a/mpi/m68k/mc68020/distfiles b/mpi/m68k/mc68020/distfiles new file mode 100644 index 000000000..fc7df9fa3 --- /dev/null +++ b/mpi/m68k/mc68020/distfiles @@ -0,0 +1,3 @@ +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S diff --git a/mpi/m68k/mc68020/mpih-mul1.S b/mpi/m68k/mc68020/mpih-mul1.S new file mode 100644 index 000000000..4872b9ba7 --- /dev/null +++ b/mpi/m68k/mc68020/mpih-mul1.S @@ -0,0 +1,106 @@ +/* mc68020 __mpn_mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_mul_1) + +C_SYMBOL_NAME(mpihelp_mul_1:) +PROLOG(mpihelp_mul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d4),MEM_PREDEC(sp) +#if 0 + movel R(d2),MEM_PREDEC(sp) + movel R(d3),MEM_PREDEC(sp) + movel R(d4),MEM_PREDEC(sp) +#endif + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,16),R(res_ptr) + movel MEM_DISP(sp,20),R(s1_ptr) + movel MEM_DISP(sp,24),R(s1_size) + movel MEM_DISP(sp,28),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + movel R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + movel R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + clrl R(d3) + addxl R(d3),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d4) +#if 0 + movel MEM_POSTINC(sp),R(d4) + movel MEM_POSTINC(sp),R(d3) + movel MEM_POSTINC(sp),R(d2) +#endif + rts +EPILOG(mpihelp_mul_1) + + diff --git a/mpi/m68k/mc68020/mpih-mul2.S b/mpi/m68k/mc68020/mpih-mul2.S new file mode 100644 index 000000000..7c492ffb2 --- /dev/null +++ b/mpi/m68k/mc68020/mpih-mul2.S @@ -0,0 +1,96 @@ +/* mc68020 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_addmul_1) + +C_SYMBOL_NAME(mpihelp_addmul_1:) +PROLOG(mpihelp_addmul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d5),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,20),R(res_ptr) + movel MEM_DISP(sp,24),R(s1_ptr) + movel MEM_DISP(sp,28),R(s1_size) + movel MEM_DISP(sp,32),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + clrl R(d5) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + addxl R(d5),R(d1) + addl R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + addxl R(d5),R(d0) + addl R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + addxl R(d5),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d5) + + rts +EPILOG(mpihelp_addmul_1) + diff --git a/mpi/m68k/mc68020/mpih-mul3.S b/mpi/m68k/mc68020/mpih-mul3.S new file mode 100644 index 000000000..1e4ac45d6 --- /dev/null +++ b/mpi/m68k/mc68020/mpih-mul3.S @@ -0,0 +1,99 @@ +/* mc68020 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + + +#include "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_size_t s1_size, (sp + 12) + * mpi_limb_t s2_limb) (sp + 16) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_submul_1) + +C_SYMBOL_NAME(mpihelp_submul_1:) +PROLOG(mpihelp_submul_1) + +#define res_ptr a0 +#define s1_ptr a1 +#define s1_size d2 +#define s2_limb d4 + +/* Save used registers on the stack. */ + moveml R(d2)-R(d5),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,20),R(res_ptr) + movel MEM_DISP(sp,24),R(s1_ptr) + movel MEM_DISP(sp,28),R(s1_size) + movel MEM_DISP(sp,32),R(s2_limb) + + eorw #1,R(s1_size) + clrl R(d1) + clrl R(d5) + lsrl #1,R(s1_size) + bcc L(L1) + subql #1,R(s1_size) + subl R(d0),R(d0) /* (d0,cy) <= (0,0) */ + +L(Loop:) + movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d1):R(d3) + addxl R(d0),R(d3) + addxl R(d5),R(d1) + subl R(d3),MEM_POSTINC(res_ptr) +L(L1:) movel MEM_POSTINC(s1_ptr),R(d3) + mulul R(s2_limb),R(d0):R(d3) + addxl R(d1),R(d3) + addxl R(d5),R(d0) + subl R(d3),MEM_POSTINC(res_ptr) + + dbf R(s1_size),L(Loop) + addxl R(d5),R(d0) + subl #0x10000,R(s1_size) + bcc L(Loop) + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d5) + + rts +EPILOG(mpihelp_submul_1) + + diff --git a/mpi/m68k/mpih-add1.S b/mpi/m68k/mpih-add1.S new file mode 100644 index 000000000..1e9cc6406 --- /dev/null +++ b/mpi/m68k/mpih-add1.S @@ -0,0 +1,94 @@ +/* mc68020 __mpn_add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1992, 1994,1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 16) + * mpi_size_t size) (sp + 12) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_add_n) + +C_SYMBOL_NAME(mpihelp_add_n:) +PROLOG(mpihelp_add_n) + /* Save used registers on the stack. */ + movel R(d2),MEM_PREDEC(sp) + movel R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,12),R(a2) + movel MEM_DISP(sp,16),R(a0) + movel MEM_DISP(sp,20),R(a1) + movel MEM_DISP(sp,24),R(d2) + + eorw #1,R(d2) + lsrl #1,R(d2) + bcc L(L1) + subql #1,R(d2) /* clears cy as side effect */ + +L(Loop:) + movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + addxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) +L(L1:) movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + addxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) + + dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ + subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ + subl #0x10000,R(d2) + bcs L(L2) + addl R(d0),R(d0) /* restore cy */ + bra L(Loop) + +L(L2:) + negl R(d0) + + /* Restore used registers from stack frame. */ + movel MEM_POSTINC(sp),R(a2) + movel MEM_POSTINC(sp),R(d2) + + rts +EPILOG(mpihelp_add_n) + + diff --git a/mpi/m68k/mpih-lshift.S b/mpi/m68k/mpih-lshift.S new file mode 100644 index 000000000..cc9dfba69 --- /dev/null +++ b/mpi/m68k/mpih-lshift.S @@ -0,0 +1,166 @@ +/* mc68020 lshift -- Shift left a low-level natural-number integer. + * + * Copyright (C) 1996, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +#define res_ptr a1 +#define s_ptr a0 +#define s_size d6 +#define cnt d4 + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_lshift) + +C_SYMBOL_NAME(mpihelp_lshift:) +PROLOG(mpihelp_lshift) + + /* Save used registers on the stack. */ + moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. */ + movel MEM_DISP(sp,28),R(res_ptr) + movel MEM_DISP(sp,32),R(s_ptr) + movel MEM_DISP(sp,36),R(s_size) + movel MEM_DISP(sp,40),R(cnt) + + moveql #1,R(d5) + cmpl R(d5),R(cnt) + bne L(Lnormal) + cmpl R(s_ptr),R(res_ptr) + bls L(Lspecial) /* jump if s_ptr >= res_ptr */ +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(a2) +#else /* not mc68020 */ + movel R(s_size),R(d0) + asll #2,R(d0) + lea MEM_INDX(s_ptr,d0,l),R(a2) +#endif + cmpl R(res_ptr),R(a2) + bls L(Lspecial) /* jump if res_ptr >= s_ptr + s_size */ + +L(Lnormal:) + moveql #32,R(d5) + subl R(cnt),R(d5) + +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) + lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) +#else /* not mc68000 */ + movel R(s_size),R(d0) + asll #2,R(d0) + addl R(s_size),R(s_ptr) + addl R(s_size),R(res_ptr) +#endif + movel MEM_PREDEC(s_ptr),R(d2) + movel R(d2),R(d0) + lsrl R(d5),R(d0) /* compute carry limb */ + + lsll R(cnt),R(d2) + movel R(d2),R(d1) + subql #1,R(s_size) + beq L(Lend) + lsrl #1,R(s_size) + bcs L(L1) + subql #1,R(s_size) + +L(Loop:) + movel MEM_PREDEC(s_ptr),R(d2) + movel R(d2),R(d3) + lsrl R(d5),R(d3) + orl R(d3),R(d1) + movel R(d1),MEM_PREDEC(res_ptr) + lsll R(cnt),R(d2) +L(L1:) + movel MEM_PREDEC(s_ptr),R(d1) + movel R(d1),R(d3) + lsrl R(d5),R(d3) + orl R(d3),R(d2) + movel R(d2),MEM_PREDEC(res_ptr) + lsll R(cnt),R(d1) + + dbf R(s_size),L(Loop) + subl #0x10000,R(s_size) + bcc L(Loop) + +L(Lend:) + movel R(d1),MEM_PREDEC(res_ptr) /* store least significant limb */ + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts + +/* We loop from least significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. */ + +L(Lspecial:) + clrl R(d0) /* initialize carry */ + eorw #1,R(s_size) + lsrl #1,R(s_size) + bcc L(LL1) + subql #1,R(s_size) + +L(LLoop:) + movel MEM_POSTINC(s_ptr),R(d2) + addxl R(d2),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) +L(LL1:) + movel MEM_POSTINC(s_ptr),R(d2) + addxl R(d2),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) + + dbf R(s_size),L(LLoop) + addxl R(d0),R(d0) /* save cy in lsb */ + subl #0x10000,R(s_size) + bcs L(LLend) + lsrl #1,R(d0) /* restore cy */ + bra L(LLoop) + +L(LLend:) +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts +EPILOG(mpihelp_lshift) + + + + + diff --git a/mpi/m68k/mpih-rshift.S b/mpi/m68k/mpih-rshift.S new file mode 100644 index 000000000..cc86166a7 --- /dev/null +++ b/mpi/m68k/mpih-rshift.S @@ -0,0 +1,164 @@ +/* mc68020 rshift -- Shift right a low-level natural-number integer. + * + * Copyright (C) 1996, 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (sp + 4) + * mpi_ptr_t up, (sp + 8) + * mpi_size_t usize, (sp + 12) + * unsigned cnt) (sp + 16) + */ + +#define res_ptr a1 +#define s_ptr a0 +#define s_size d6 +#define cnt d4 + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_rshift) + +C_SYMBOL_NAME(mpihelp_rshift:) +PROLOG(mpihelp_rshift) + /* Save used registers on the stack. */ + moveml R(d2)-R(d6)/R(a2),MEM_PREDEC(sp) + + /* Copy the arguments to registers. */ + movel MEM_DISP(sp,28),R(res_ptr) + movel MEM_DISP(sp,32),R(s_ptr) + movel MEM_DISP(sp,36),R(s_size) + movel MEM_DISP(sp,40),R(cnt) + + moveql #1,R(d5) + cmpl R(d5),R(cnt) + bne L(Rnormal) + cmpl R(res_ptr),R(s_ptr) + bls L(Rspecial) /* jump if res_ptr >= s_ptr */ +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(res_ptr,s_size,l,4),R(a2) +#else /* not mc68020 */ + movel R(s_size),R(d0) + asll #2,R(d0) + lea MEM_INDX(res_ptr,d0,l),R(a2) +#endif + cmpl R(s_ptr),R(a2) + bls L(Rspecial) /* jump if s_ptr >= res_ptr + s_size */ + +L(Rnormal:) + moveql #32,R(d5) + subl R(cnt),R(d5) + movel MEM_POSTINC(s_ptr),R(d2) + movel R(d2),R(d0) + lsll R(d5),R(d0) /* compute carry limb */ + + lsrl R(cnt),R(d2) + movel R(d2),R(d1) + subql #1,R(s_size) + beq L(Rend) + lsrl #1,R(s_size) + bcs L(R1) + subql #1,R(s_size) + +L(Roop:) + movel MEM_POSTINC(s_ptr),R(d2) + movel R(d2),R(d3) + lsll R(d5),R(d3) + orl R(d3),R(d1) + movel R(d1),MEM_POSTINC(res_ptr) + lsrl R(cnt),R(d2) +L(R1:) + movel MEM_POSTINC(s_ptr),R(d1) + movel R(d1),R(d3) + lsll R(d5),R(d3) + orl R(d3),R(d2) + movel R(d2),MEM_POSTINC(res_ptr) + lsrl R(cnt),R(d1) + + dbf R(s_size),L(Roop) + subl #0x10000,R(s_size) + bcc L(Roop) + +L(Rend:) + movel R(d1),MEM(res_ptr) /* store most significant limb */ + +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts + +/* We loop from most significant end of the arrays, which is only + permissable if the source and destination don't overlap, since the + function is documented to work for overlapping source and destination. */ + +L(Rspecial:) +#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) + lea MEM_INDX1(s_ptr,s_size,l,4),R(s_ptr) + lea MEM_INDX1(res_ptr,s_size,l,4),R(res_ptr) +#else /* not mc68000 */ + movel R(s_size),R(d0) + asll #2,R(d0) + addl R(s_size),R(s_ptr) + addl R(s_size),R(res_ptr) +#endif + + clrl R(d0) /* initialize carry */ + eorw #1,R(s_size) + lsrl #1,R(s_size) + bcc L(LR1) + subql #1,R(s_size) + +L(LRoop:) + movel MEM_PREDEC(s_ptr),R(d2) + roxrl #1,R(d2) + movel R(d2),MEM_PREDEC(res_ptr) +L(LR1:) + movel MEM_PREDEC(s_ptr),R(d2) + roxrl #1,R(d2) + movel R(d2),MEM_PREDEC(res_ptr) + + dbf R(s_size),L(LRoop) + roxrl #1,R(d0) /* save cy in msb */ + subl #0x10000,R(s_size) + bcs L(LRend) + addl R(d0),R(d0) /* restore cy */ + bra L(LRoop) + +L(LRend:) +/* Restore used registers from stack frame. */ + moveml MEM_POSTINC(sp),R(d2)-R(d6)/R(a2) + rts +EPILOG(mpihelp_rshift) + + + + diff --git a/mpi/m68k/mpih-sub1.S b/mpi/m68k/mpih-sub1.S new file mode 100644 index 000000000..1847fbd65 --- /dev/null +++ b/mpi/m68k/mpih-sub1.S @@ -0,0 +1,93 @@ +/* mc68020 __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (sp + 4) + * mpi_ptr_t s1_ptr, (sp + 8) + * mpi_ptr_t s2_ptr, (sp + 16) + * mpi_size_t size) (sp + 12) + */ + + + TEXT + ALIGN + GLOBL C_SYMBOL_NAME(mpihelp_sub_n) + +C_SYMBOL_NAME(mpihelp_sub_n:) +PROLOG(mpihelp_sub_n) +/* Save used registers on the stack. */ + movel R(d2),MEM_PREDEC(sp) + movel R(a2),MEM_PREDEC(sp) + +/* Copy the arguments to registers. Better use movem? */ + movel MEM_DISP(sp,12),R(a2) + movel MEM_DISP(sp,16),R(a0) + movel MEM_DISP(sp,20),R(a1) + movel MEM_DISP(sp,24),R(d2) + + eorw #1,R(d2) + lsrl #1,R(d2) + bcc L(L1) + subql #1,R(d2) /* clears cy as side effect */ + +L(Loop:) + movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + subxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) +L(L1:) movel MEM_POSTINC(a0),R(d0) + movel MEM_POSTINC(a1),R(d1) + subxl R(d1),R(d0) + movel R(d0),MEM_POSTINC(a2) + + dbf R(d2),L(Loop) /* loop until 16 lsb of %4 == -1 */ + subxl R(d0),R(d0) /* d0 <= -cy; save cy as 0 or -1 in d0 */ + subl #0x10000,R(d2) + bcs L(L2) + addl R(d0),R(d0) /* restore cy */ + bra L(Loop) + +L(L2:) + negl R(d0) + +/* Restore used registers from stack frame. */ + movel MEM_POSTINC(sp),R(a2) + movel MEM_POSTINC(sp),R(d2) + + rts +EPILOG(mpihelp_sub_n) + + diff --git a/mpi/m68k/syntax.h b/mpi/m68k/syntax.h new file mode 100644 index 000000000..316518fef --- /dev/null +++ b/mpi/m68k/syntax.h @@ -0,0 +1,187 @@ +/* asm.h -- Definitions for 68k syntax variations. + * + * Copyright (C) 1992, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +#undef ALIGN + +#ifdef MIT_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)base@ +#define MEM_DISP(base,displacement)base@(displacement) +#define MEM_INDX(base,idx,size_suffix)base@(idx:size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)base@(idx:size_suffix:scale) +#define MEM_PREDEC(memory_base)memory_base@- +#define MEM_POSTINC(memory_base)memory_base@+ +#define L(label) label +#define TEXT .text +#define ALIGN .even +#define GLOBL .globl +#define moveql moveq +/* Use variable sized opcodes. */ +#define bcc jcc +#define bcs jcs +#define bls jls +#define beq jeq +#define bne jne +#define bra jra +#endif + +#ifdef SONY_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)(displacement,base) +#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) +#define MEM_PREDEC(memory_base)-(memory_base) +#define MEM_POSTINC(memory_base)(memory_base)+ +#define L(label) label +#define TEXT .text +#define ALIGN .even +#define GLOBL .globl +#endif + +#ifdef MOTOROLA_SYNTAX +#define PROLOG(name) +#define EPILOG(name) +#define R(r)r +#define MEM(base)(base) +#define MEM_DISP(base,displacement)(displacement,base) +#define MEM_INDX(base,idx,size_suffix)(base,idx.size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(base,idx.size_suffix*scale) +#define MEM_PREDEC(memory_base)-(memory_base) +#define MEM_POSTINC(memory_base)(memory_base)+ +#define L(label) label +#define TEXT +#define ALIGN +#define GLOBL XDEF +#define lea LEA +#define movel MOVE.L +#define moveml MOVEM.L +#define moveql MOVEQ.L +#define cmpl CMP.L +#define orl OR.L +#define clrl CLR.L +#define eorw EOR.W +#define lsrl LSR.L +#define lsll LSL.L +#define roxrl ROXR.L +#define roxll ROXL.L +#define addl ADD.L +#define addxl ADDX.L +#define addql ADDQ.L +#define subl SUB.L +#define subxl SUBX.L +#define subql SUBQ.L +#define negl NEG.L +#define mulul MULU.L +#define bcc BCC +#define bcs BCS +#define bls BLS +#define beq BEQ +#define bne BNE +#define bra BRA +#define dbf DBF +#define rts RTS +#define d0 D0 +#define d1 D1 +#define d2 D2 +#define d3 D3 +#define d4 D4 +#define d5 D5 +#define d6 D6 +#define d7 D7 +#define a0 A0 +#define a1 A1 +#define a2 A2 +#define a3 A3 +#define a4 A4 +#define a5 A5 +#define a6 A6 +#define a7 A7 +#define sp SP +#endif + +#ifdef ELF_SYNTAX +#define PROLOG(name) .type name,@function +#define EPILOG(name) .size name,.-name +#define MEM(base)(R(base)) +#define MEM_DISP(base,displacement)(displacement,R(base)) +#define MEM_PREDEC(memory_base)-(R(memory_base)) +#define MEM_POSTINC(memory_base)(R(memory_base))+ +#ifdef __STDC__ +#define R_(r)%##r +#define R(r)R_(r) +#define MEM_INDX_(base,idx,size_suffix)(R(base),R(idx##.##size_suffix)) +#define MEM_INDX(base,idx,size_suffix)MEM_INDX_(base,idx,size_suffix) +#define MEM_INDX1_(base,idx,size_suffix,scale)(R(base),R(idx##.##size_suffix*scale)) +#define MEM_INDX1(base,idx,size_suffix,scale)MEM_INDX1_(base,idx,size_suffix,scale) +#define L(label) .##label +#else +#define R(r)%/**/r +#define MEM_INDX(base,idx,size_suffix)(R(base),R(idx).size_suffix) +#define MEM_INDX1(base,idx,size_suffix,scale)(R(base),R(idx).size_suffix*scale) +#define L(label) ./**/label +#endif +#define TEXT .text +#define ALIGN .align 2 +#define GLOBL .globl +#define bcc jbcc +#define bcs jbcs +#define bls jbls +#define beq jbeq +#define bne jbne +#define bra jbra +#endif + +#if defined (SONY_SYNTAX) || defined (ELF_SYNTAX) +#define movel move.l +#define moveml movem.l +#define moveql moveq.l +#define cmpl cmp.l +#define orl or.l +#define clrl clr.l +#define eorw eor.w +#define lsrl lsr.l +#define lsll lsl.l +#define roxrl roxr.l +#define roxll roxl.l +#define addl add.l +#define addxl addx.l +#define addql addq.l +#define subl sub.l +#define subxl subx.l +#define subql subq.l +#define negl neg.l +#define mulul mulu.l +#endif diff --git a/mpi/mips3/README b/mpi/mips3/README new file mode 100644 index 000000000..e94b2c746 --- /dev/null +++ b/mpi/mips3/README @@ -0,0 +1,23 @@ +This directory contains mpn functions optimized for MIPS3. Example of +processors that implement MIPS3 are R4000, R4400, R4600, R4700, and R8000. + +RELEVANT OPTIMIZATION ISSUES + +1. On the R4000 and R4400, branches, both the plain and the "likely" ones, + take 3 cycles to execute. (The fastest possible loop will take 4 cycles, + because of the delay insn.) + + On the R4600, branches takes a single cycle + + On the R8000, branches often take no noticable cycles, as they are + executed in a separate function unit.. + +2. The R4000 and R4400 have a load latency of 4 cycles. + +3. On the R4000 and R4400, multiplies take a data-dependent number of + cycles, contrary to the SGI documentation. There seem to be 3 or 4 + possible latencies. + +STATUS + +Good... diff --git a/mpi/mips3/distfiles b/mpi/mips3/distfiles new file mode 100644 index 000000000..85260fc8e --- /dev/null +++ b/mpi/mips3/distfiles @@ -0,0 +1,10 @@ +README +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +mpi-asm-defs.h + diff --git a/mpi/mips3/mpi-asm-defs.h b/mpi/mips3/mpi-asm-defs.h new file mode 100644 index 000000000..2d9a9c1f2 --- /dev/null +++ b/mpi/mips3/mpi-asm-defs.h @@ -0,0 +1,10 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB 8 + + + + + + diff --git a/mpi/mips3/mpih-add1.S b/mpi/mips3/mpih-add1.S new file mode 100644 index 000000000..a998420d7 --- /dev/null +++ b/mpi/mips3/mpih-add1.S @@ -0,0 +1,124 @@ +/* mips3 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1995, 1998, 2000 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, ($4) + * mpi_ptr_t s1_ptr, ($5) + * mpi_ptr_t s2_ptr, ($6) + * mpi_size_t size) ($7) + */ + + .text + .align 2 + .globl mpihelp_add_n + .ent mpihelp_add_n +mpihelp_add_n: + .set noreorder + .set nomacro + + ld $10,0($5) + ld $11,0($6) + + daddiu $7,$7,-1 + and $9,$7,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + move $2,$0 + + dsubu $7,$7,$9 + +.Loop0: daddiu $9,$9,-1 + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + or $2,$2,$8 + + daddiu $5,$5,8 + daddiu $6,$6,8 + move $10,$12 + move $11,$13 + bne $9,$0,.Loop0 + daddiu $4,$4,8 + +.L0: beq $7,$0,.Lend + nop + +.Loop: daddiu $7,$7,-4 + + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + or $2,$2,$8 + + ld $10,16($5) + daddu $13,$13,$2 + ld $11,16($6) + sltu $8,$13,$2 + daddu $13,$12,$13 + sltu $2,$13,$12 + sd $13,8($4) + or $2,$2,$8 + + ld $12,24($5) + daddu $11,$11,$2 + ld $13,24($6) + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,16($4) + or $2,$2,$8 + + ld $10,32($5) + daddu $13,$13,$2 + ld $11,32($6) + sltu $8,$13,$2 + daddu $13,$12,$13 + sltu $2,$13,$12 + sd $13,24($4) + or $2,$2,$8 + + daddiu $5,$5,32 + daddiu $6,$6,32 + + bne $7,$0,.Loop + daddiu $4,$4,32 + +.Lend: daddu $11,$11,$2 + sltu $8,$11,$2 + daddu $11,$10,$11 + sltu $2,$11,$10 + sd $11,0($4) + j $31 + or $2,$2,$8 + + .end mpihelp_add_n + diff --git a/mpi/mips3/mpih-lshift.S b/mpi/mips3/mpih-lshift.S new file mode 100644 index 000000000..112383f90 --- /dev/null +++ b/mpi/mips3/mpih-lshift.S @@ -0,0 +1,97 @@ +/* mips3 lshift + * + * Copyright (C) 1995, 1998, 2000, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, ($4) + * mpi_ptr_t up, ($5) + * mpi_size_t usize, ($6) + * unsigned cnt) ($7) + */ + + .text + .align 2 + .globl mpihelp_lshift + .ent mpihelp_lshift +mpihelp_lshift: + .set noreorder + .set nomacro + + dsll $2,$6,3 + daddu $5,$5,$2 # make r5 point at end of src + ld $10,-8($5) # load first limb + dsubu $13,$0,$7 + daddu $4,$4,$2 # make r4 point at end of res + daddiu $6,$6,-1 + and $9,$6,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + dsrl $2,$10,$13 # compute function result + + dsubu $6,$6,$9 + +.Loop0: ld $3,-16($5) + daddiu $4,$4,-8 + daddiu $5,$5,-8 + daddiu $9,$9,-1 + dsll $11,$10,$7 + dsrl $12,$3,$13 + move $10,$3 + or $8,$11,$12 + bne $9,$0,.Loop0 + sd $8,0($4) + +.L0: beq $6,$0,.Lend + nop + +.Loop: ld $3,-16($5) + daddiu $4,$4,-32 + daddiu $6,$6,-4 + dsll $11,$10,$7 + dsrl $12,$3,$13 + + ld $10,-24($5) + dsll $14,$3,$7 + or $8,$11,$12 + sd $8,24($4) + dsrl $9,$10,$13 + + ld $3,-32($5) + dsll $11,$10,$7 + or $8,$14,$9 + sd $8,16($4) + dsrl $12,$3,$13 + + ld $10,-40($5) + dsll $14,$3,$7 + or $8,$11,$12 + sd $8,8($4) + dsrl $9,$10,$13 + + daddiu $5,$5,-32 + or $8,$14,$9 + bgtz $6,.Loop + sd $8,0($4) + +.Lend: dsll $8,$10,$7 + j $31 + sd $8,-8($4) + .end mpihelp_lshift diff --git a/mpi/mips3/mpih-mul1.S b/mpi/mips3/mpih-mul1.S new file mode 100644 index 000000000..70409e8db --- /dev/null +++ b/mpi/mips3/mpih-mul1.S @@ -0,0 +1,89 @@ +/* mips3 mpih-mul1.S -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl mpihelp_mul_1 + .ent mpihelp_mul_1 +mpihelp_mul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: mflo $10 + mfhi $9 + daddiu $5,$5,8 + daddu $10,$10,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$10,$2 # carry from previous addition -> $2 + sd $10,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: mflo $10 + mfhi $9 + daddu $10,$10,$2 + sltu $2,$10,$2 + dmultu $8,$7 + sd $10,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: mflo $10 + mfhi $9 + daddu $10,$10,$2 + sltu $2,$10,$2 + sd $10,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end mpihelp_mul_1 + diff --git a/mpi/mips3/mpih-mul2.S b/mpi/mips3/mpih-mul2.S new file mode 100644 index 000000000..1bddd0530 --- /dev/null +++ b/mpi/mips3/mpih-mul2.S @@ -0,0 +1,101 @@ +/* MIPS3 addmul_1 -- Multiply a limb vector with a single limb and + * add the product to a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl mpihelp_addmul_1 + .ent mpihelp_addmul_1 +mpihelp_addmul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: ld $10,0($4) + mflo $3 + mfhi $9 + daddiu $5,$5,8 + daddu $3,$3,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$3,$2 # carry from previous addition -> $2 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dmultu $8,$7 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + daddu $3,$10,$3 + sltu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end mpihelp_addmul_1 + diff --git a/mpi/mips3/mpih-mul3.S b/mpi/mips3/mpih-mul3.S new file mode 100644 index 000000000..82fe47d53 --- /dev/null +++ b/mpi/mips3/mpih-mul3.S @@ -0,0 +1,101 @@ +/* MIPS3 submul_1 -- Multiply a limb vector with a single limb and + * subtract the product from a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, 2000 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_size_t s1_size, (r6) + * mpi_limb_t s2_limb) (r7) + */ + + .text + .align 4 + .globl mpihelp_submul_1 + .ent mpihelp_submul_1 +mpihelp_submul_1: + .set noreorder + .set nomacro + +/* # warm up phase 0 */ + ld $8,0($5) + +/* # warm up phase 1 */ + daddiu $5,$5,8 + dmultu $8,$7 + + daddiu $6,$6,-1 + beq $6,$0,$LC0 + move $2,$0 # zero cy2 + + daddiu $6,$6,-1 + beq $6,$0,$LC1 + ld $8,0($5) # load new s1 limb as early as possible + +Loop: ld $10,0($4) + mflo $3 + mfhi $9 + daddiu $5,$5,8 + daddu $3,$3,$2 # add old carry limb to low product limb + dmultu $8,$7 + ld $8,0($5) # load new s1 limb as early as possible + daddiu $6,$6,-1 # decrement loop counter + sltu $2,$3,$2 # carry from previous addition -> $2 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + bne $6,$0,Loop + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 1 */ +$LC1: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dmultu $8,$7 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + daddiu $4,$4,8 + daddu $2,$9,$2 # add high product limb and carry from addition + +/* # cool down phase 0 */ +$LC0: ld $10,0($4) + mflo $3 + mfhi $9 + daddu $3,$3,$2 + sltu $2,$3,$2 + dsubu $3,$10,$3 + sgtu $10,$3,$10 + daddu $2,$2,$10 + sd $3,0($4) + j $31 + daddu $2,$9,$2 # add high product limb and carry from addition + + .end mpihelp_submul_1 + diff --git a/mpi/mips3/mpih-rshift.S b/mpi/mips3/mpih-rshift.S new file mode 100644 index 000000000..74a6cc96d --- /dev/null +++ b/mpi/mips3/mpih-rshift.S @@ -0,0 +1,95 @@ +/* mips3 rshift + * + * Copyright (C) 1995, 1998, 2000 + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, ($4) + * mpi_ptr_t up, ($5) + * mpi_size_t usize, ($6) + * unsigned cnt) ($7) + */ + + .text + .align 2 + .globl mpihelp_rshift + .ent mpihelp_rshift +mpihelp_rshift: + .set noreorder + .set nomacro + + ld $10,0($5) # load first limb + dsubu $13,$0,$7 + daddiu $6,$6,-1 + and $9,$6,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + dsll $2,$10,$13 # compute function result + + dsubu $6,$6,$9 + +.Loop0: ld $3,8($5) + daddiu $4,$4,8 + daddiu $5,$5,8 + daddiu $9,$9,-1 + dsrl $11,$10,$7 + dsll $12,$3,$13 + move $10,$3 + or $8,$11,$12 + bne $9,$0,.Loop0 + sd $8,-8($4) + +.L0: beq $6,$0,.Lend + nop + +.Loop: ld $3,8($5) + daddiu $4,$4,32 + daddiu $6,$6,-4 + dsrl $11,$10,$7 + dsll $12,$3,$13 + + ld $10,16($5) + dsrl $14,$3,$7 + or $8,$11,$12 + sd $8,-32($4) + dsll $9,$10,$13 + + ld $3,24($5) + dsrl $11,$10,$7 + or $8,$14,$9 + sd $8,-24($4) + dsll $12,$3,$13 + + ld $10,32($5) + dsrl $14,$3,$7 + or $8,$11,$12 + sd $8,-16($4) + dsll $9,$10,$13 + + daddiu $5,$5,32 + or $8,$14,$9 + bgtz $6,.Loop + sd $8,-8($4) + +.Lend: dsrl $8,$10,$7 + j $31 + sd $8,0($4) + .end mpihelp_rshift + diff --git a/mpi/mips3/mpih-sub1.S b/mpi/mips3/mpih-sub1.S new file mode 100644 index 000000000..72f506ea2 --- /dev/null +++ b/mpi/mips3/mpih-sub1.S @@ -0,0 +1,125 @@ +/* mips3 sub_n -- Subtract two limb vectors of the same length > 0 and + * store difference in a third limb vector. + * + * Copyright (C) 1995, 1998, 1999, 2000, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (r4) + * mpi_ptr_t s1_ptr, (r5) + * mpi_ptr_t s2_ptr, (r6) + * mpi_size_t size) (r7) + */ + + + .text + .align 2 + .globl mpihelp_sub_n + .ent mpihelp_sub_n +mpihelp_sub_n: + .set noreorder + .set nomacro + + ld $10,0($5) + ld $11,0($6) + + daddiu $7,$7,-1 + and $9,$7,4-1 # number of limbs in first loop + beq $9,$0,.L0 # if multiple of 4 limbs, skip first loop + move $2,$0 + + dsubu $7,$7,$9 + +.Loop0: daddiu $9,$9,-1 + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + or $2,$2,$8 + + daddiu $5,$5,8 + daddiu $6,$6,8 + move $10,$12 + move $11,$13 + bne $9,$0,.Loop0 + daddiu $4,$4,8 + +.L0: beq $7,$0,.Lend + nop + +.Loop: daddiu $7,$7,-4 + + ld $12,8($5) + daddu $11,$11,$2 + ld $13,8($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + or $2,$2,$8 + + ld $10,16($5) + daddu $13,$13,$2 + ld $11,16($6) + sltu $8,$13,$2 + dsubu $13,$12,$13 + sltu $2,$12,$13 + sd $13,8($4) + or $2,$2,$8 + + ld $12,24($5) + daddu $11,$11,$2 + ld $13,24($6) + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,16($4) + or $2,$2,$8 + + ld $10,32($5) + daddu $13,$13,$2 + ld $11,32($6) + sltu $8,$13,$2 + dsubu $13,$12,$13 + sltu $2,$12,$13 + sd $13,24($4) + or $2,$2,$8 + + daddiu $5,$5,32 + daddiu $6,$6,32 + + bne $7,$0,.Loop + daddiu $4,$4,32 + +.Lend: daddu $11,$11,$2 + sltu $8,$11,$2 + dsubu $11,$10,$11 + sltu $2,$10,$11 + sd $11,0($4) + j $31 + or $2,$2,$8 + + .end mpihelp_sub_n + diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c new file mode 100644 index 000000000..bbd1ac70e --- /dev/null +++ b/mpi/mpi-add.c @@ -0,0 +1,247 @@ +/* mpi-add.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" + + +/**************** + * Add the unsigned integer V to the mpi-integer U and store the + * result in W. U and V may be the same. + */ +void +mpi_add_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + } + else if( !usign ) { /* mpi is not negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + wsign = 1; + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +void +mpi_add(MPI w, MPI u, MPI v) +{ + mpi_ptr_t wp, up, vp; + mpi_size_t usize, vsize, wsize; + int usign, vsign, wsign; + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + vsize = u->nlimbs; + vsign = u->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = v->d; + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + vsize = v->nlimbs; + vsign = v->sign; + wsize = usize + 1; + RESIZE_IF_NEEDED(w, wsize); + /* These must be after realloc (u or v may be the same as w). */ + up = u->d; + vp = v->d; + } + wp = w->d; + wsign = 0; + + if( !vsize ) { /* simple */ + MPN_COPY(wp, up, usize ); + wsize = usize; + wsign = usign; + } + else if( usign != vsign ) { /* different sign */ + /* This test is right since USIZE >= VSIZE */ + if( usize != vsize ) { + mpihelp_sub(wp, up, usize, vp, vsize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + wsign = usign; + } + else if( mpihelp_cmp(up, vp, usize) < 0 ) { + mpihelp_sub_n(wp, vp, up, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( !usign ) + wsign = 1; + } + else { + mpihelp_sub_n(wp, up, vp, usize); + wsize = usize; + MPN_NORMALIZE(wp, wsize); + if( usign ) + wsign = 1; + } + } + else { /* U and V have same sign. Add them. */ + mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize); + wp[usize] = cy; + wsize = usize + cy; + if( usign ) + wsign = 1; + } + + w->nlimbs = wsize; + w->sign = wsign; +} + + +/**************** + * Subtract the unsigned integer V from the mpi-integer U and store the + * result in W. + */ +void +mpi_sub_ui(MPI w, MPI u, unsigned long v ) +{ + mpi_ptr_t wp, up; + mpi_size_t usize, wsize; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + wsign = 0; + + /* If not space for W (and possible carry), increase space. */ + wsize = usize + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize); + + /* These must be after realloc (U may be the same as W). */ + up = u->d; + wp = w->d; + + if( !usize ) { /* simple */ + wp[0] = v; + wsize = v? 1:0; + wsign = 1; + } + else if( usign ) { /* mpi and v are negative */ + mpi_limb_t cy; + cy = mpihelp_add_1(wp, up, usize, v); + wp[usize] = cy; + wsize = usize + cy; + } + else { /* The signs are different. Need exact comparison to determine + * which operand to subtract from which. */ + if( usize == 1 && up[0] < v ) { + wp[0] = v - up[0]; + wsize = 1; + wsign = 1; + } + else { + mpihelp_sub_1(wp, up, usize, v); + /* Size can decrease with at most one limb. */ + wsize = usize - (wp[usize-1]==0); + } + } + + w->nlimbs = wsize; + w->sign = wsign; +} + +void +mpi_sub(MPI w, MPI u, MPI v) +{ + if( w == v ) { + MPI vv = mpi_copy(v); + vv->sign = !vv->sign; + mpi_add( w, u, vv ); + mpi_free(vv); + } + else { + /* fixme: this is not thread-save (we temp. modify v) */ + v->sign = !v->sign; + mpi_add( w, u, v ); + v->sign = !v->sign; + } +} + + +void +mpi_addm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_add(w, u, v); + mpi_fdiv_r( w, w, m ); +} + +void +mpi_subm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_sub(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c new file mode 100644 index 000000000..fa6bf06e6 --- /dev/null +++ b/mpi/mpi-bit.c @@ -0,0 +1,262 @@ +/* mpi-bit.c - MPI bit level fucntions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "mpi-internal.h" +#include "longlong.h" + + +#ifdef MPI_INTERNAL_NEED_CLZ_TAB +#ifdef __STDC__ +const +#endif +unsigned char +__clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; +#endif + + +#define A_LIMB_1 ((mpi_limb_t)1) + + +/**************** + * Sometimes we have MSL (most significant limbs) which are 0; + * this is for some reasons not good, so this function removes them. + */ +void +mpi_normalize( MPI a ) +{ + if( mpi_is_protected(a) ) + return; + + for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- ) + ; +} + + + +/**************** + * Return the number of bits in A. + */ +unsigned +mpi_get_nbits( MPI a ) +{ + unsigned n; + + if( mpi_is_protected(a) ) { + n = mpi_get_nbit_info(a); + if( !n ) + n = a->nlimbs * BITS_PER_MPI_LIMB; + return n; + } + + mpi_normalize( a ); + if( a->nlimbs ) { + mpi_limb_t alimb = a->d[a->nlimbs-1]; + if( alimb ) + count_leading_zeros( n, alimb ); + else + n = BITS_PER_MPI_LIMB; + n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB; + } + else + n = 0; + return n; +} + + +/**************** + * Test whether bit N is set. + */ +int +mpi_test_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + mpi_limb_t limb; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return 0; /* too far left: this is a 0 */ + limb = a->d[limbno]; + return (limb & (A_LIMB_1 << bitno))? 1: 0; +} + + +/**************** + * Set bit N of A. + */ +void +mpi_set_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); +} + +/**************** + * Set bit N of A. and clear all bits above + */ +void +mpi_set_highbit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) { /* resize */ + if( a->alloced >= limbno ) + mpi_resize(a, limbno+1 ); + a->nlimbs = limbno+1; + } + a->d[limbno] |= (A_LIMB_1<<bitno); + for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * clear bit N of A and all bits above + */ +void +mpi_clear_highbit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* not allocated, so need to clear bits :-) */ + + for( ; bitno < BITS_PER_MPI_LIMB; bitno++ ) + a->d[limbno] &= ~(A_LIMB_1 << bitno); + a->nlimbs = limbno+1; +} + +/**************** + * Clear bit N of A. + */ +void +mpi_clear_bit( MPI a, unsigned n ) +{ + unsigned limbno, bitno; + + limbno = n / BITS_PER_MPI_LIMB; + bitno = n % BITS_PER_MPI_LIMB; + + if( limbno >= a->nlimbs ) + return; /* don't need to clear this bit, it's to far to left */ + a->d[limbno] &= ~(A_LIMB_1 << bitno); +} + + +/**************** + * Shift A by N bits to the right + * FIXME: should use alloc_limb if X and A are same. + */ +void +mpi_rshift( MPI x, MPI a, unsigned n ) +{ + mpi_ptr_t xp; + mpi_size_t xsize; + + xsize = a->nlimbs; + x->sign = a->sign; + RESIZE_IF_NEEDED(x, xsize); + xp = x->d; + + if( xsize ) { + mpihelp_rshift( xp, a->d, xsize, n); + MPN_NORMALIZE( xp, xsize); + } + x->nlimbs = xsize; +} + + +/**************** + * Shift A by COUNT limbs to the left + * This is used only within the MPI library + */ +void +mpi_lshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + int n = a->nlimbs; + int i; + + if( !count || !n ) + return; + + RESIZE_IF_NEEDED( a, n+count ); + + for( i = n-1; i >= 0; i-- ) + ap[i+count] = ap[i]; + for(i=0; i < count; i++ ) + ap[i] = 0; + a->nlimbs += count; +} + + +/**************** + * Shift A by COUNT limbs to the right + * This is used only within the MPI library + */ +void +mpi_rshift_limbs( MPI a, unsigned int count ) +{ + mpi_ptr_t ap = a->d; + mpi_size_t n = a->nlimbs; + unsigned int i; + + if( count >= n ) { + a->nlimbs = 0; + return; + } + + for( i = 0; i < n - count; i++ ) + ap[i] = ap[i+count]; + ap[i] = 0; + a->nlimbs -= count; +} + + diff --git a/mpi/mpi-cmp.c b/mpi/mpi-cmp.c new file mode 100644 index 000000000..612198885 --- /dev/null +++ b/mpi/mpi-cmp.c @@ -0,0 +1,74 @@ +/* mpi-cmp.c - MPI functions + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +int +mpi_cmp_ui( MPI u, unsigned long v ) +{ + mpi_limb_t limb = v; + + mpi_normalize( u ); + if( !u->nlimbs && !limb ) + return 0; + if( u->sign ) + return -1; + if( u->nlimbs > 1 ) + return 1; + + if( u->d[0] == limb ) + return 0; + else if( u->d[0] > limb ) + return 1; + else + return -1; +} + +int +mpi_cmp( MPI u, MPI v ) +{ + mpi_size_t usize, vsize; + int cmp; + + mpi_normalize( u ); + mpi_normalize( v ); + usize = u->nlimbs; + vsize = v->nlimbs; + if( !u->sign && v->sign ) + return 1; + if( u->sign && !v->sign ) + return -1; + if( usize != vsize && !u->sign && !v->sign ) + return usize - vsize; + if( usize != vsize && u->sign && v->sign ) + return vsize + usize; + if( !usize ) + return 0; + if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) ) + return 0; + if( (cmp < 0?1:0) == (u->sign?1:0)) + return 1; + return -1; +} + + diff --git a/mpi/mpi-div.c b/mpi/mpi-div.c new file mode 100644 index 000000000..a86df2daf --- /dev/null +++ b/mpi/mpi-div.c @@ -0,0 +1,322 @@ +/* mpi-div.c - MPI functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + + + +void +mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + /* We need the original value of the divisor after the remainder has been + * preliminary calculated. We have to copy it to temporary space if it's + * the same variable as REM. */ + if( rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_r( rem, dividend, divisor ); + + if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs ) + mpi_add( rem, rem, divisor); + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + + +/**************** + * Division rounding the quotient towards -infinity. + * The remainder gets the same sign as the denominator. + * rem is optional + */ + +ulong +mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor ) +{ + mpi_limb_t rlimb; + + rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); + if( rlimb && dividend->sign ) + rlimb = divisor - rlimb; + + if( rem ) { + rem->d[0] = rlimb; + rem->nlimbs = rlimb? 1:0; + } + return rlimb; +} + + +void +mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor ) +{ + MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) ); + mpi_fdiv_qr( quot, tmp, dividend, divisor); + mpi_free(tmp); +} + +void +mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor ) +{ + int divisor_sign = divisor->sign; + MPI temp_divisor = NULL; + + if( quot == divisor || rem == divisor ) { + temp_divisor = mpi_copy( divisor ); + divisor = temp_divisor; + } + + mpi_tdiv_qr( quot, rem, dividend, divisor ); + + if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) { + mpi_sub_ui( quot, quot, 1 ); + mpi_add( rem, rem, divisor); + } + + if( temp_divisor ) + mpi_free(temp_divisor); +} + + +/* If den == quot, den needs temporary storage. + * If den == rem, den needs temporary storage. + * If num == quot, num needs temporary storage. + * If den has temporary storage, it can be normalized while being copied, + * i.e no extra storage should be allocated. + */ + +void +mpi_tdiv_r( MPI rem, MPI num, MPI den) +{ + mpi_tdiv_qr(NULL, rem, num, den ); +} + +void +mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den) +{ + mpi_ptr_t np, dp; + mpi_ptr_t qp, rp; + mpi_size_t nsize = num->nlimbs; + mpi_size_t dsize = den->nlimbs; + mpi_size_t qsize, rsize; + mpi_size_t sign_remainder = num->sign; + mpi_size_t sign_quotient = num->sign ^ den->sign; + unsigned normalization_steps; + mpi_limb_t q_limb; + mpi_ptr_t marker[5]; + int markidx=0; + + /* Ensure space is enough for quotient and remainder. + * We need space for an extra limb in the remainder, because it's + * up-shifted (normalized) below. */ + rsize = nsize + 1; + mpi_resize( rem, rsize); + + qsize = rsize - dsize; /* qsize cannot be bigger than this. */ + if( qsize <= 0 ) { + if( num != rem ) { + rem->nlimbs = num->nlimbs; + rem->sign = num->sign; + MPN_COPY(rem->d, num->d, nsize); + } + if( quot ) { + /* This needs to follow the assignment to rem, in case the + * numerator and quotient are the same. */ + quot->nlimbs = 0; + quot->sign = 0; + } + return; + } + + if( quot ) + mpi_resize( quot, qsize); + + /* Read pointers here, when reallocation is finished. */ + np = num->d; + dp = den->d; + rp = rem->d; + + /* Optimize division by a single-limb divisor. */ + if( dsize == 1 ) { + mpi_limb_t rlimb; + if( quot ) { + qp = quot->d; + rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] ); + qsize -= qp[qsize - 1] == 0; + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + else + rlimb = mpihelp_mod_1( np, nsize, dp[0] ); + rp[0] = rlimb; + rsize = rlimb != 0?1:0; + rem->nlimbs = rsize; + rem->sign = sign_remainder; + return; + } + + + if( quot ) { + qp = quot->d; + /* Make sure QP and NP point to different objects. Otherwise the + * numerator would be gradually overwritten by the quotient limbs. */ + if(qp == np) { /* Copy NP object to temporary space. */ + np = marker[markidx++] = mpi_alloc_limb_space(nsize, + mpi_is_secure(quot)); + MPN_COPY(np, qp, nsize); + } + } + else /* Put quotient at top of remainder. */ + qp = rp + dsize; + + count_leading_zeros( normalization_steps, dp[dsize - 1] ); + + /* Normalize the denominator, i.e. make its most significant bit set by + * shifting it NORMALIZATION_STEPS bits to the left. Also shift the + * numerator the same number of steps (to keep the quotient the same!). + */ + if( normalization_steps ) { + mpi_ptr_t tp; + mpi_limb_t nlimb; + + /* Shift up the denominator setting the most significant bit of + * the most significant word. Use temporary storage not to clobber + * the original contents of the denominator. */ + tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den)); + mpihelp_lshift( tp, dp, dsize, normalization_steps ); + dp = tp; + + /* Shift up the numerator, possibly introducing a new most + * significant word. Move the shifted numerator in the remainder + * meanwhile. */ + nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps); + if( nlimb ) { + rp[nsize] = nlimb; + rsize = nsize + 1; + } + else + rsize = nsize; + } + else { + /* The denominator is already normalized, as required. Copy it to + * temporary space if it overlaps with the quotient or remainder. */ + if( dp == rp || (quot && (dp == qp))) { + mpi_ptr_t tp; + + tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den)); + MPN_COPY( tp, dp, dsize ); + dp = tp; + } + + /* Move the numerator to the remainder. */ + if( rp != np ) + MPN_COPY(rp, np, nsize); + + rsize = nsize; + } + + q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize ); + + if( quot ) { + qsize = rsize - dsize; + if(q_limb) { + qp[qsize] = q_limb; + qsize += 1; + } + + quot->nlimbs = qsize; + quot->sign = sign_quotient; + } + + rsize = dsize; + MPN_NORMALIZE (rp, rsize); + + if( normalization_steps && rsize ) { + mpihelp_rshift(rp, rp, rsize, normalization_steps); + rsize -= rp[rsize - 1] == 0?1:0; + } + + rem->nlimbs = rsize; + rem->sign = sign_remainder; + while( markidx ) + mpi_free_limb_space(marker[--markidx]); +} + +void +mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count ) +{ + mpi_size_t usize, wsize; + mpi_size_t limb_cnt; + + usize = u->nlimbs; + limb_cnt = count / BITS_PER_MPI_LIMB; + wsize = usize - limb_cnt; + if( limb_cnt >= usize ) + w->nlimbs = 0; + else { + mpi_ptr_t wp; + mpi_ptr_t up; + + RESIZE_IF_NEEDED( w, wsize ); + wp = w->d; + up = u->d; + + count %= BITS_PER_MPI_LIMB; + if( count ) { + mpihelp_rshift( wp, up + limb_cnt, wsize, count ); + wsize -= !wp[wsize - 1]; + } + else { + MPN_COPY_INCR( wp, up + limb_cnt, wsize); + } + + w->nlimbs = wsize; + } +} + +/**************** + * Check whether dividend is divisible by divisor + * (note: divisor must fit into a limb) + */ +int +mpi_divisible_ui(MPI dividend, ulong divisor ) +{ + return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor ); +} + diff --git a/mpi/mpi-gcd.c b/mpi/mpi-gcd.c new file mode 100644 index 000000000..efd703b32 --- /dev/null +++ b/mpi/mpi-gcd.c @@ -0,0 +1,54 @@ +/* mpi-gcd.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + +/**************** + * Find the greatest common divisor G of A and B. + * Return: true if this 1, false in all other cases + */ +int +mpi_gcd( MPI g, MPI xa, MPI xb ) +{ + MPI a, b; + + a = mpi_copy(xa); + b = mpi_copy(xb); + + /* TAOCP Vol II, 4.5.2, Algorithm A */ + a->sign = 0; + b->sign = 0; + while( mpi_cmp_ui( b, 0 ) ) { + mpi_fdiv_r( g, a, b ); /* g used as temorary variable */ + mpi_set(a,b); + mpi_set(b,g); + } + mpi_set(g, a); + + mpi_free(a); + mpi_free(b); + return !mpi_cmp_ui( g, 1); +} + + + diff --git a/mpi/mpi-inline.c b/mpi/mpi-inline.c new file mode 100644 index 000000000..787d897dd --- /dev/null +++ b/mpi/mpi-inline.c @@ -0,0 +1,36 @@ +/* mpi-inline.c + * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +/* put the inline functions as real functions into the lib */ +#define G10_MPI_INLINE_DECL + +#include "mpi-internal.h" + +/* always include the header becuase it is only + * included by mpi-internal if __GCC__ is defined but we + * need it here in all cases and the above definition of + * of the macro allows us to do so + */ +#include "mpi-inline.h" + diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h new file mode 100644 index 000000000..02481b67c --- /dev/null +++ b/mpi/mpi-inline.h @@ -0,0 +1,128 @@ +/* mpi-inline.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_INLINE_H +#define G10_MPI_INLINE_H + +#ifndef G10_MPI_INLINE_DECL + #define G10_MPI_INLINE_DECL extern __inline__ +#endif + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb += x; + *res_ptr++ = s2_limb; + if( s2_limb < x ) { /* sum is less than the left operand: handle carry */ + while( --s1_size ) { + x = *s1_ptr++ + 1; /* add carry */ + *res_ptr++ = x; /* and store */ + if( x ) /* not 0 (no overflow): we can stop */ + goto leave; + } + return 1; /* return carry (size of s1 to small) */ + } + + leave: + if( res_ptr != s1_ptr ) { /* not the same variable */ + mpi_size_t i; /* copy the rest */ + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; /* no carry */ +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size ); + + if( s1_size - s2_size ) + cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ) +{ + mpi_limb_t x; + + x = *s1_ptr++; + s2_limb = x - s2_limb; + *res_ptr++ = s2_limb; + if( s2_limb > x ) { + while( --s1_size ) { + x = *s1_ptr++; + *res_ptr++ = x - 1; + if( x ) + goto leave; + } + return 1; + } + + leave: + if( res_ptr != s1_ptr ) { + mpi_size_t i; + for( i=0; i < s1_size-1; i++ ) + res_ptr[i] = s1_ptr[i]; + } + return 0; +} + + + +G10_MPI_INLINE_DECL mpi_limb_t +mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size) +{ + mpi_limb_t cy = 0; + + if( s2_size ) + cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size); + + if( s1_size - s2_size ) + cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size, + s1_size - s2_size, cy); + return cy; +} + + +#endif /*G10_MPI_INLINE_H*/ diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h new file mode 100644 index 000000000..60d9e09ee --- /dev/null +++ b/mpi/mpi-internal.h @@ -0,0 +1,259 @@ +/* mpi-internal.h - Internal to the Multi Precision Integers + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#ifndef G10_MPI_INTERNAL_H +#define G10_MPI_INTERNAL_H + +#include "mpi.h" + +/* If KARATSUBA_THRESHOLD is not already defined, define it to a + * value which is good on most machines. */ + +/* tested 4, 16, 32 and 64, where 16 gave the best performance when + * checking a 768 and a 1024 bit ElGamal signature. + * (wk 22.12.97) */ +#ifndef KARATSUBA_THRESHOLD + #define KARATSUBA_THRESHOLD 16 +#endif + +/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */ +#if KARATSUBA_THRESHOLD < 2 + #undef KARATSUBA_THRESHOLD + #define KARATSUBA_THRESHOLD 2 +#endif + + +typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */ +typedef int mpi_size_t; /* (must be a signed type) */ + +#define ABS(x) (x >= 0 ? x : -x) +#define MIN(l,o) ((l) < (o) ? (l) : (o)) +#define MAX(h,i) ((h) > (i) ? (h) : (i)) +#define RESIZE_IF_NEEDED(a,b) \ + do { \ + if( (a)->alloced < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) + +/* Copy N limbs from S to D. */ +#define MPN_COPY( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +#define MPN_COPY_INCR( d, s, n) \ + do { \ + mpi_size_t _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = (d)[_i]; \ + } while (0) + +#define MPN_COPY_DECR( d, s, n ) \ + do { \ + mpi_size_t _i; \ + for( _i = (n)-1; _i >= 0; _i--) \ + (d)[_i] = (s)[_i]; \ + } while(0) + +/* Zero N limbs at D */ +#define MPN_ZERO(d, n) \ + do { \ + int _i; \ + for( _i = 0; _i < (n); _i++ ) \ + (d)[_i] = 0; \ + } while (0) + +#define MPN_NORMALIZE(d, n) \ + do { \ + while( (n) > 0 ) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_NORMALIZE_NOT_ZERO(d, n) \ + do { \ + for(;;) { \ + if( (d)[(n)-1] ) \ + break; \ + (n)--; \ + } \ + } while(0) + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + + +/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest + * limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB). + * If this would yield overflow, DI should be the largest possible number + * (i.e., only ones). For correct operation, the most significant bit of D + * has to be set. Put the quotient in Q and the remainder in R. + */ +#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \ + do { \ + mpi_limb_t _q, _ql, _r; \ + mpi_limb_t _xh, _xl; \ + umul_ppmm (_q, _ql, (nh), (di)); \ + _q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \ + umul_ppmm (_xh, _xl, _q, (d)); \ + sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \ + if( _xh ) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + if( _xh) { \ + sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \ + _q++; \ + } \ + } \ + if( _r >= (d) ) { \ + _r -= (d); \ + _q++; \ + } \ + (r) = _r; \ + (q) = _q; \ + } while (0) + + +/*-- mpiutil.c --*/ +#ifdef M_DEBUG + #define mpi_alloc_limb_space(n,f) mpi_debug_alloc_limb_space((n),(f), M_DBGINFO( __LINE__ ) ) + #define mpi_free_limb_space(n) mpi_debug_free_limb_space((n), M_DBGINFO( __LINE__ ) ) + mpi_ptr_t mpi_debug_alloc_limb_space( unsigned nlimbs, int sec, const char *info ); + void mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ); +#else + mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs, int sec ); + void mpi_free_limb_space( mpi_ptr_t a ); +#endif +void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ); + +/*-- mpi-bit.c --*/ +void mpi_rshift_limbs( MPI a, unsigned int count ); +void mpi_lshift_limbs( MPI a, unsigned int count ); + + +/*-- mpihelp-add.c --*/ +mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-sub.c --*/ +mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb ); +mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_ptr_t s2_ptr, mpi_size_t size); +mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size, + mpi_ptr_t s2_ptr, mpi_size_t s2_size); + +/*-- mpihelp-cmp.c --*/ +int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ); + +/*-- mpihelp-mul.c --*/ + +struct karatsuba_ctx { + struct karatsuba_ctx *next; + mpi_ptr_t tspace; + mpi_size_t tspace_size; + mpi_ptr_t tp; + mpi_size_t tp_size; +}; + +void mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ); + +mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); +void mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size); +mpi_limb_t mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize); +void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ); +void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, + mpi_ptr_t tspace); + +void mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ); + + +/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/ +mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, + mpi_size_t s1_size, mpi_limb_t s2_limb); + +/*-- mpihelp-div.c --*/ +mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); +mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize); +mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb); + +/*-- mpihelp-shift.c --*/ +mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); +mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize, + unsigned cnt); + + +/* Define stuff for longlong.h. */ +#define W_TYPE_SIZE BITS_PER_MPI_LIMB + typedef mpi_limb_t UWtype; + typedef unsigned int UHWtype; +#if defined (__GNUC__) + typedef unsigned int UQItype __attribute__ ((mode (QI))); + typedef int SItype __attribute__ ((mode (SI))); + typedef unsigned int USItype __attribute__ ((mode (SI))); + typedef int DItype __attribute__ ((mode (DI))); + typedef unsigned int UDItype __attribute__ ((mode (DI))); +#else + typedef unsigned char UQItype; + typedef long SItype; + typedef unsigned long USItype; +#endif + +#ifdef __GNUC__ + #include "mpi-inline.h" +#endif + +#endif /*G10_MPI_INTERNAL_H*/ diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c new file mode 100644 index 000000000..ad41cf2a5 --- /dev/null +++ b/mpi/mpi-inv.c @@ -0,0 +1,270 @@ +/* mpi-inv.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +/**************** + * Calculate the multiplicative inverse X of A mod N + * That is: Find the solution x for + * 1 = (a*x) mod n + */ +void +mpi_invm( MPI x, MPI a, MPI n ) +{ + #if 0 + MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3; + MPI ta, tb, tc; + + u = mpi_copy(a); + v = mpi_copy(n); + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_alloc_set_ui(0); + v2 = mpi_alloc_set_ui(1); + v3 = mpi_copy(v); + q = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t1 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t2 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + t3 = mpi_alloc( mpi_get_nlimbs(u)+1 ); + while( mpi_cmp_ui( v3, 0 ) ) { + mpi_fdiv_q( q, u3, v3 ); + mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q); + mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3); + mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3); + mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3); + } + /* log_debug("result:\n"); + log_mpidump("q =", q ); + log_mpidump("u1=", u1); + log_mpidump("u2=", u2); + log_mpidump("u3=", u3); + log_mpidump("v1=", v1); + log_mpidump("v2=", v2); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(q); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + mpi_free(u); + mpi_free(v); + #elif 0 + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 */ + + /* FIXME: we can simplify this in most cases (see Knuth) */ + MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3; + unsigned k; + int sign; + + u = mpi_copy(a); + v = mpi_copy(n); + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + + + u1 = mpi_alloc_set_ui(1); + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); /* !-- used as const 1 */ + v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u ); + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(u2); + mpi_free(u3); + mpi_free(v1); + mpi_free(v2); + mpi_free(v3); + mpi_free(t1); + mpi_free(t2); + mpi_free(t3); + #else + /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X) + * modified according to Michael Penk's solution for Exercice 35 + * with further enhancement */ + MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3; + unsigned k; + int sign; + int odd ; + + u = mpi_copy(a); + v = mpi_copy(n); + + for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) { + mpi_rshift(u, u, 1); + mpi_rshift(v, v, 1); + } + odd = mpi_test_bit(v,0); + + u1 = mpi_alloc_set_ui(1); + if( !odd ) + u2 = mpi_alloc_set_ui(0); + u3 = mpi_copy(u); + v1 = mpi_copy(v); + if( !odd ) { + v2 = mpi_alloc( mpi_get_nlimbs(u) ); + mpi_sub( v2, u1, u ); /* U is used as const 1 */ + } + v3 = mpi_copy(v); + if( mpi_test_bit(u, 0) ) { /* u is odd */ + t1 = mpi_alloc_set_ui(0); + if( !odd ) { + t2 = mpi_alloc_set_ui(1); t2->sign = 1; + } + t3 = mpi_copy(v); t3->sign = !t3->sign; + goto Y4; + } + else { + t1 = mpi_alloc_set_ui(1); + if( !odd ) + t2 = mpi_alloc_set_ui(0); + t3 = mpi_copy(u); + } + do { + do { + if( !odd ) { + if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */ + mpi_add(t1, t1, v); + mpi_sub(t2, t2, u); + } + mpi_rshift(t1, t1, 1); + mpi_rshift(t2, t2, 1); + mpi_rshift(t3, t3, 1); + } + else { + if( mpi_test_bit(t1, 0) ) + mpi_add(t1, t1, v); + mpi_rshift(t1, t1, 1); + mpi_rshift(t3, t3, 1); + } + Y4: + ; + } while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */ + + if( !t3->sign ) { + mpi_set(u1, t1); + if( !odd ) + mpi_set(u2, t2); + mpi_set(u3, t3); + } + else { + mpi_sub(v1, v, t1); + sign = u->sign; u->sign = !u->sign; + if( !odd ) + mpi_sub(v2, u, t2); + u->sign = sign; + sign = t3->sign; t3->sign = !t3->sign; + mpi_set(v3, t3); + t3->sign = sign; + } + mpi_sub(t1, u1, v1); + if( !odd ) + mpi_sub(t2, u2, v2); + mpi_sub(t3, u3, v3); + if( t1->sign ) { + mpi_add(t1, t1, v); + if( !odd ) + mpi_sub(t2, t2, u); + } + } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */ + /* mpi_lshift( u3, k ); */ + mpi_set(x, u1); + + mpi_free(u1); + mpi_free(v1); + mpi_free(t1); + if( !odd ) { + mpi_free(u2); + mpi_free(v2); + mpi_free(t2); + } + mpi_free(u3); + mpi_free(v3); + mpi_free(t3); + + mpi_free(u); + mpi_free(v); + #endif +} + + + diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c new file mode 100644 index 000000000..7c46fc65c --- /dev/null +++ b/mpi/mpi-mpow.c @@ -0,0 +1,101 @@ +/* mpi-mpow.c - MPI functions + * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" +#include <assert.h> + +static int +build_index( MPI *exparray, int k, int i, int t ) +{ + int j, bitno; + int index = 0; + + bitno = t-i; + for(j=k-1; j >= 0; j-- ) { + index <<= 1; + if( mpi_test_bit( exparray[j], bitno ) ) + index |= 1; + } + return index; +} + +/**************** + * RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M + */ +void +mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m) +{ + int k; /* number of elements */ + int t; /* bit size of largest exponent */ + int i, j, idx; + MPI *G; /* table with precomputed values of size 2^k */ + MPI tmp; + + for(k=0; basearray[k]; k++ ) + ; + assert(k); + for(t=0, i=0; (tmp=exparray[i]); i++ ) { + j = mpi_get_nbits(tmp); + if( j > t ) + t = j; + } + assert(i==k); + assert(t); + assert( k < 10 ); + + G = m_alloc_clear( (1<<k) * sizeof *G ); + /* and calculate */ + tmp = mpi_alloc( mpi_get_nlimbs(m)+1 ); + mpi_set_ui( res, 1 ); + for(i = 1; i <= t; i++ ) { + mpi_mulm(tmp, res, res, m ); + idx = build_index( exparray, k, i, t ); + assert( idx >= 0 && idx < (1<<k) ); + if( !G[idx] ) { + if( !idx ) + G[0] = mpi_alloc_set_ui( 1 ); + else { + for(j=0; j < k; j++ ) { + if( (idx & (1<<j) ) ) { + if( !G[idx] ) + G[idx] = mpi_copy( basearray[j] ); + else + mpi_mulm( G[idx], G[idx], basearray[j], m ); + } + } + if( !G[idx] ) + G[idx] = mpi_alloc(0); + } + } + mpi_mulm(res, tmp, G[idx], m ); + } + + /* cleanup */ + mpi_free(tmp); + for(i=0; i < (1<<k); i++ ) + mpi_free(G[i]); + m_free(G); +} + + diff --git a/mpi/mpi-mul.c b/mpi/mpi-mul.c new file mode 100644 index 000000000..8748a3863 --- /dev/null +++ b/mpi/mpi-mul.c @@ -0,0 +1,215 @@ +/* mpi-mul.c - MPI functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" + + +void +mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult ) +{ + mpi_size_t size, prod_size; + mpi_ptr_t prod_ptr; + mpi_limb_t cy; + int sign; + + size = mult->nlimbs; + sign = mult->sign; + + if( !size || !small_mult ) { + prod->nlimbs = 0; + prod->sign = 0; + return; + } + + prod_size = size + 1; + if( prod->alloced < prod_size ) + mpi_resize( prod, prod_size ); + prod_ptr = prod->d; + + cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult ); + if( cy ) + prod_ptr[size++] = cy; + prod->nlimbs = size; + prod->sign = sign; +} + + +void +mpi_mul_2exp( MPI w, MPI u, unsigned long cnt) +{ + mpi_size_t usize, wsize, limb_cnt; + mpi_ptr_t wp; + mpi_limb_t wlimb; + int usign, wsign; + + usize = u->nlimbs; + usign = u->sign; + + if( !usize ) { + w->nlimbs = 0; + w->sign = 0; + return; + } + + limb_cnt = cnt / BITS_PER_MPI_LIMB; + wsize = usize + limb_cnt + 1; + if( w->alloced < wsize ) + mpi_resize(w, wsize ); + wp = w->d; + wsize = usize + limb_cnt; + wsign = usign; + + cnt %= BITS_PER_MPI_LIMB; + if( cnt ) { + wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt ); + if( wlimb ) { + wp[wsize] = wlimb; + wsize++; + } + } + else { + MPN_COPY_DECR( wp + limb_cnt, u->d, usize ); + } + + /* Zero all whole limbs at low end. Do it here and not before calling + * mpn_lshift, not to lose for U == W. */ + MPN_ZERO( wp, limb_cnt ); + + w->nlimbs = wsize; + w->sign = wsign; +} + + + +void +mpi_mul( MPI w, MPI u, MPI v) +{ + mpi_size_t usize, vsize, wsize; + mpi_ptr_t up, vp, wp; + mpi_limb_t cy; + int usign, vsign, usecure, vsecure, sign_product; + int assign_wp=0; + mpi_ptr_t tmp_limb=NULL; + + + if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */ + usize = v->nlimbs; + usign = v->sign; + usecure = mpi_is_secure(v); + up = v->d; + vsize = u->nlimbs; + vsign = u->sign; + vsecure = mpi_is_secure(u); + vp = u->d; + } + else { + usize = u->nlimbs; + usign = u->sign; + usecure = mpi_is_secure(u); + up = u->d; + vsize = v->nlimbs; + vsign = v->sign; + vsecure = mpi_is_secure(v); + vp = v->d; + } + sign_product = usign ^ vsign; + wp = w->d; + + /* Ensure W has space enough to store the result. */ + wsize = usize + vsize; + if ( !mpi_is_secure (w) && (mpi_is_secure (u) || mpi_is_secure (v)) ) { + /* w is not allocated in secure space but u or v is. To make sure + * that no temporray results are stored in w, we temporary use + * a newly allocated limb space for w */ + wp = mpi_alloc_limb_space( wsize, 1 ); + assign_wp = 2; /* mark it as 2 so that we can later copy it back to + * mormal memory */ + } + else if( w->alloced < wsize ) { + if( wp == up || wp == vp ) { + wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) ); + assign_wp = 1; + } + else { + mpi_resize(w, wsize ); + wp = w->d; + } + } + else { /* Make U and V not overlap with W. */ + if( wp == up ) { + /* W and U are identical. Allocate temporary space for U. */ + up = tmp_limb = mpi_alloc_limb_space( usize, usecure ); + /* Is V identical too? Keep it identical with U. */ + if( wp == vp ) + vp = up; + /* Copy to the temporary space. */ + MPN_COPY( up, wp, usize ); + } + else if( wp == vp ) { + /* W and V are identical. Allocate temporary space for V. */ + vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure ); + /* Copy to the temporary space. */ + MPN_COPY( vp, wp, vsize ); + } + } + + if( !vsize ) + wsize = 0; + else { + cy = mpihelp_mul( wp, up, usize, vp, vsize ); + wsize -= cy? 0:1; + } + + if( assign_wp ) { + if (assign_wp == 2) { + /* copy the temp wp from secure memory back to normal memory */ + mpi_ptr_t tmp_wp = mpi_alloc_limb_space (wsize, 0); + MPN_COPY (tmp_wp, wp, wsize); + mpi_free_limb_space (wp); + wp = tmp_wp; + } + mpi_assign_limb_space( w, wp, wsize ); + } + w->nlimbs = wsize; + w->sign = sign_product; + if( tmp_limb ) + mpi_free_limb_space( tmp_limb ); +} + + +void +mpi_mulm( MPI w, MPI u, MPI v, MPI m) +{ + mpi_mul(w, u, v); + mpi_fdiv_r( w, w, m ); +} + diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c new file mode 100644 index 000000000..d65258b0f --- /dev/null +++ b/mpi/mpi-pow.c @@ -0,0 +1,294 @@ +/* mpi-pow.c - MPI functions + * Copyright (C) 1994, 1996, 1998, 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "mpi-internal.h" +#include "longlong.h" +#include <assert.h> + + +/**************** + * RES = BASE ^ EXP mod MOD + */ +void +mpi_powm( MPI res, MPI base, MPI exp, MPI mod) +{ + mpi_ptr_t rp, ep, mp, bp; + mpi_size_t esize, msize, bsize, rsize; + int esign, msign, bsign, rsign; + int esec, msec, bsec, rsec; + mpi_size_t size; + int mod_shift_cnt; + int negative_result; + mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL; + mpi_ptr_t xp_marker=NULL; + int assign_rp=0; + mpi_ptr_t tspace = NULL; + mpi_size_t tsize=0; /* to avoid compiler warning */ + /* fixme: we should check that the warning is void*/ + + esize = exp->nlimbs; + msize = mod->nlimbs; + size = 2 * msize; + esign = exp->sign; + msign = mod->sign; + + esec = mpi_is_secure(exp); + msec = mpi_is_secure(mod); + bsec = mpi_is_secure(base); + rsec = mpi_is_secure(res); + + rp = res->d; + ep = exp->d; + + if( !msize ) + msize = 1 / msize; /* provoke a signal */ + + if( !esize ) { + /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 + * depending on if MOD equals 1. */ + rp[0] = 1; + res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1; + res->sign = 0; + goto leave; + } + + /* Normalize MOD (i.e. make its most significant bit set) as required by + * mpn_divrem. This will make the intermediate values in the calculation + * slightly larger, but the correct result is obtained after a final + * reduction using the original MOD value. */ + mp = mp_marker = mpi_alloc_limb_space(msize, msec); + count_leading_zeros( mod_shift_cnt, mod->d[msize-1] ); + if( mod_shift_cnt ) + mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt ); + else + MPN_COPY( mp, mod->d, msize ); + + bsize = base->nlimbs; + bsign = base->sign; + if( bsize > msize ) { /* The base is larger than the module. Reduce it. */ + /* Allocate (BSIZE + 1) with space for remainder and quotient. + * (The quotient is (bsize - msize + 1) limbs.) */ + bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec ); + MPN_COPY( bp, base->d, bsize ); + /* We don't care about the quotient, store it above the remainder, + * at BP + MSIZE. */ + mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize ); + bsize = msize; + /* Canonicalize the base, since we are going to multiply with it + * quite a few times. */ + MPN_NORMALIZE( bp, bsize ); + } + else + bp = base->d; + + if( !bsize ) { + res->nlimbs = 0; + res->sign = 0; + goto leave; + } + + if( res->alloced < size ) { + /* We have to allocate more space for RES. If any of the input + * parameters are identical to RES, defer deallocation of the old + * space. */ + if( rp == ep || rp == mp || rp == bp ) { + rp = mpi_alloc_limb_space( size, rsec ); + assign_rp = 1; + } + else { + mpi_resize( res, size ); + rp = res->d; + } + } + else { /* Make BASE, EXP and MOD not overlap with RES. */ + if( rp == bp ) { + /* RES and BASE are identical. Allocate temp. space for BASE. */ + assert( !bp_marker ); + bp = bp_marker = mpi_alloc_limb_space( bsize, bsec ); + MPN_COPY(bp, rp, bsize); + } + if( rp == ep ) { + /* RES and EXP are identical. Allocate temp. space for EXP. */ + ep = ep_marker = mpi_alloc_limb_space( esize, esec ); + MPN_COPY(ep, rp, esize); + } + if( rp == mp ) { + /* RES and MOD are identical. Allocate temporary space for MOD.*/ + assert( !mp_marker ); + mp = mp_marker = mpi_alloc_limb_space( msize, msec ); + MPN_COPY(mp, rp, msize); + } + } + + MPN_COPY( rp, bp, bsize ); + rsize = bsize; + rsign = bsign; + + { + mpi_size_t i; + mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec ); + int c; + mpi_limb_t e; + mpi_limb_t carry_limb; + struct karatsuba_ctx karactx; + + memset( &karactx, 0, sizeof karactx ); + negative_result = (ep[0] & 1) && base->sign; + + i = esize - 1; + e = ep[i]; + count_leading_zeros (c, e); + e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ + c = BITS_PER_MPI_LIMB - 1 - c; + + /* Main loop. + * + * Make the result be pointed to alternately by XP and RP. This + * helps us avoid block copying, which would otherwise be necessary + * with the overlap restrictions of mpihelp_divmod. With 50% probability + * the result after this loop will be in the area originally pointed + * by RP (==RES->d), and with 50% probability in the area originally + * pointed to by XP. + */ + + for(;;) { + while( c ) { + mpi_ptr_t tp; + mpi_size_t xsize; + + /*mpihelp_mul_n(xp, rp, rp, rsize);*/ + if( rsize < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( xp, rp, rsize ); + else { + if( !tspace ) { + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + else if( tsize < (2*rsize) ) { + mpi_free_limb_space( tspace ); + tsize = 2 * rsize; + tspace = mpi_alloc_limb_space( tsize, 0 ); + } + mpih_sqr_n( xp, rp, rsize, tspace ); + } + + xsize = 2 * rsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + + if( (mpi_limb_signed_t)e < 0 ) { + /*mpihelp_mul( xp, rp, rsize, bp, bsize );*/ + if( bsize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( xp, rp, rsize, bp, bsize ); + } + else { + mpihelp_mul_karatsuba_case( + xp, rp, rsize, bp, bsize, &karactx ); + } + + xsize = rsize + bsize; + if( xsize > msize ) { + mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize); + xsize = msize; + } + + tp = rp; rp = xp; xp = tp; + rsize = xsize; + } + e <<= 1; + c--; + } + + i--; + if( i < 0 ) + break; + e = ep[i]; + c = BITS_PER_MPI_LIMB; + } + + /* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT + * steps. Adjust the result by reducing it with the original MOD. + * + * Also make sure the result is put in RES->d (where it already + * might be, see above). + */ + if( mod_shift_cnt ) { + carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt); + rp = res->d; + if( carry_limb ) { + rp[rsize] = carry_limb; + rsize++; + } + } + else { + MPN_COPY( res->d, rp, rsize); + rp = res->d; + } + + if( rsize >= msize ) { + mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize); + rsize = msize; + } + + /* Remove any leading zero words from the result. */ + if( mod_shift_cnt ) + mpihelp_rshift( rp, rp, rsize, mod_shift_cnt); + MPN_NORMALIZE (rp, rsize); + + mpihelp_release_karatsuba_ctx( &karactx ); + } + + if( negative_result && rsize ) { + if( mod_shift_cnt ) + mpihelp_rshift( mp, mp, msize, mod_shift_cnt); + mpihelp_sub( rp, mp, msize, rp, rsize); + rsize = msize; + rsign = msign; + MPN_NORMALIZE(rp, rsize); + } + res->nlimbs = rsize; + res->sign = rsign; + + leave: + if( assign_rp ) mpi_assign_limb_space( res, rp, size ); + if( mp_marker ) mpi_free_limb_space( mp_marker ); + if( bp_marker ) mpi_free_limb_space( bp_marker ); + if( ep_marker ) mpi_free_limb_space( ep_marker ); + if( xp_marker ) mpi_free_limb_space( xp_marker ); + if( tspace ) mpi_free_limb_space( tspace ); +} + diff --git a/mpi/mpi-scan.c b/mpi/mpi-scan.c new file mode 100644 index 000000000..abebe2208 --- /dev/null +++ b/mpi/mpi-scan.c @@ -0,0 +1,132 @@ +/* mpi-scan.c - MPI functions + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +/**************** + * Scan through an mpi and return byte for byte. a -1 is returned to indicate + * the end of the mpi. Scanning is done from the lsb to the msb, returned + * values are in the range of 0 .. 255. + * + * FIXME: This code is VERY ugly! + */ +int +mpi_getbyte( MPI a, unsigned idx ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb; + + ap = a->d; + for(n=0,i=0; i < a->nlimbs; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) + return (limb >> j*8) & 0xff; + } + return -1; +} + + +/**************** + * Put a value at position IDX into A. idx counts from lsb to msb + */ +void +mpi_putbyte( MPI a, unsigned idx, int xc ) +{ + int i, j; + unsigned n; + mpi_ptr_t ap; + mpi_limb_t limb, c; + + c = xc & 0xff; + ap = a->d; + for(n=0,i=0; i < a->alloced; i++ ) { + limb = ap[i]; + for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ ) + if( n == idx ) { + #if BYTES_PER_MPI_LIMB == 4 + if( j == 0 ) + limb = (limb & 0xffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xff00ffff) | (c<<16); + else + limb = (limb & 0x00ffffff) | (c<<24); + #elif BYTES_PER_MPI_LIMB == 8 + if( j == 0 ) + limb = (limb & 0xffffffffffffff00) | c; + else if( j == 1 ) + limb = (limb & 0xffffffffffff00ff) | (c<<8); + else if( j == 2 ) + limb = (limb & 0xffffffffff00ffff) | (c<<16); + else if( j == 3 ) + limb = (limb & 0xffffffff00ffffff) | (c<<24); + else if( j == 4 ) + limb = (limb & 0xffffff00ffffffff) | (c<<32); + else if( j == 5 ) + limb = (limb & 0xffff00ffffffffff) | (c<<40); + else if( j == 6 ) + limb = (limb & 0xff00ffffffffffff) | (c<<48); + else + limb = (limb & 0x00ffffffffffffff) | (c<<56); + #else + #error please enhance this function, its ugly - i know. + #endif + if( a->nlimbs <= i ) + a->nlimbs = i+1; + ap[i] = limb; + return; + } + } + abort(); /* index out of range */ +} + + +/**************** + * Count the number of zerobits at the low end of A + */ +unsigned +mpi_trailing_zeros( MPI a ) +{ + unsigned n, count = 0; + + for(n=0; n < a->nlimbs; n++ ) { + if( a->d[n] ) { + unsigned nn; + mpi_limb_t alimb = a->d[n]; + + count_trailing_zeros( nn, alimb ); + count += nn; + break; + } + count += BITS_PER_MPI_LIMB; + } + return count; + +} + + diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c new file mode 100644 index 000000000..f6d266fe7 --- /dev/null +++ b/mpi/mpicoder.c @@ -0,0 +1,446 @@ +/* mpicoder.c - Coder for the external representation of MPIs + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +#include "mpi.h" +#include "mpi-internal.h" +#include "iobuf.h" +#include "memory.h" +#include "util.h" + +#ifdef M_DEBUG + #undef mpi_read +#endif + +#define MAX_EXTERN_MPI_BITS 16384 + +/**************** + * write an mpi to out. + */ +int +mpi_write( IOBUF out, MPI a ) +{ + int rc; + unsigned nbits = mpi_get_nbits(a); + byte *p, *buf; + unsigned n; + + if( nbits > MAX_EXTERN_MPI_BITS ) + log_bug("mpi_encode: mpi too large (%u bits)\n", nbits); + + iobuf_put(out, (nbits >>8) ); + iobuf_put(out, (nbits) ); + + p = buf = mpi_get_buffer( a, &n, NULL ); + rc = iobuf_write( out, p, n ); + m_free(buf); + return rc; +} + + +/**************** + * Read an external representation of an mpi and return the MPI + * The external format is a 16 bit unsigned value stored in network byte order, + * giving the number of bits for the following integer. The integer is stored + * with MSB first (left padded with zeroes to align on a byte boundary). + */ +MPI +#ifdef M_DEBUG +mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info) +#else +mpi_read(IOBUF inp, unsigned *ret_nread, int secure) +#endif +{ + int c, i, j; + unsigned nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + MPI val = MPI_NULL; + + if( (c = iobuf_get(inp)) == -1 ) + goto leave; + nbits = c << 8; + if( (c = iobuf_get(inp)) == -1 ) + goto leave; + nbits |= c; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + #ifdef M_DEBUG + val = secure? mpi_debug_alloc_secure( nlimbs, info ) + : mpi_debug_alloc( nlimbs, info ); + #else + val = secure? mpi_alloc_secure( nlimbs ) + : mpi_alloc( nlimbs ); + #endif + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + val->nbits = nbits; + j= val->nlimbs = nlimbs; + val->sign = 0; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + a <<= 8; + a |= iobuf_get(inp) & 0xff; nread++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + if( nread > *ret_nread ) + log_bug("mpi crosses packet border"); + else + *ret_nread = nread; + return val; +} + + +MPI +mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure) +{ + int i, j; + unsigned nbits, nbytes, nlimbs, nread=0; + mpi_limb_t a; + MPI val = MPI_NULL; + + if( *ret_nread < 2 ) + goto leave; + nbits = buffer[0] << 8 | buffer[1]; + if( nbits > MAX_EXTERN_MPI_BITS ) { + log_error("mpi too large (%u bits)\n", nbits); + goto leave; + } + buffer += 2; + nread = 2; + + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + val = secure? mpi_alloc_secure( nlimbs ) + : mpi_alloc( nlimbs ); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + val->nbits = nbits; + j= val->nlimbs = nlimbs; + val->sign = 0; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + if( ++nread > *ret_nread ) + log_bug("mpi larger than buffer"); + a <<= 8; + a |= *buffer++; + } + i = 0; + val->d[j-1] = a; + } + + leave: + *ret_nread = nread; + return val; +} + + +/**************** + * Make an mpi from a character string. + */ +int +mpi_fromstr(MPI val, const char *str) +{ + int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2; + unsigned nbits, nbytes, nlimbs; + mpi_limb_t a; + + if( *str == '-' ) { + sign = 1; + str++; + } + if( *str == '0' && str[1] == 'x' ) + hexmode = 1; + else + return 1; /* other bases are not yet supported */ + str += 2; + + nbits = strlen(str)*4; + if( nbits % 8 ) + prepend_zero = 1; + nbytes = (nbits+7) / 8; + nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB; + if( val->alloced < nlimbs ) + mpi_resize(val, nlimbs ); + i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; + i %= BYTES_PER_MPI_LIMB; + j= val->nlimbs = nlimbs; + val->sign = sign; + for( ; j > 0; j-- ) { + a = 0; + for(; i < BYTES_PER_MPI_LIMB; i++ ) { + if( prepend_zero ) { + c1 = '0'; + prepend_zero = 0; + } + else + c1 = *str++; + assert(c1); + c2 = *str++; + assert(c2); + if( c1 >= '0' && c1 <= '9' ) + c = c1 - '0'; + else if( c1 >= 'a' && c1 <= 'f' ) + c = c1 - 'a' + 10; + else if( c1 >= 'A' && c1 <= 'F' ) + c = c1 - 'A' + 10; + else { + mpi_clear(val); + return 1; + } + c <<= 4; + if( c2 >= '0' && c2 <= '9' ) + c |= c2 - '0'; + else if( c2 >= 'a' && c2 <= 'f' ) + c |= c2 - 'a' + 10; + else if( c2 >= 'A' && c2 <= 'F' ) + c |= c2 - 'A' + 10; + else { + mpi_clear(val); + return 1; + } + a <<= 8; + a |= c; + } + i = 0; + val->d[j-1] = a; + } + + return 0; +} + + +/**************** + * print an MPI to the given stream and return the number of characters + * printed. + */ +int +mpi_print( FILE *fp, MPI a, int mode ) +{ + int i, n=0; + + if( a == MPI_NULL ) + return fprintf(fp, "[MPI_NULL]"); + if( !mode ) { + unsigned n1, n2; + n1 = mpi_get_nbits(a); + n2 = mpi_get_nbit_info(a); + if( n2 && n2 != n1 ) + n += fprintf(fp, "[%u bits (%u)]", n1, n2 ); + else + n += fprintf(fp, "[%u bits]", n1); + } + else { + if( a->sign ) + putc('-', fp); + #if BYTES_PER_MPI_LIMB == 2 + #define X "4" + #elif BYTES_PER_MPI_LIMB == 4 + #define X "8" + #elif BYTES_PER_MPI_LIMB == 8 + #define X "16" + #else + #error please define the format here + #endif + for(i=a->nlimbs; i > 0 ; i-- ) { + n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]); + #undef X + } + if( !a->nlimbs ) + putc('0', fp ); + } + return n; +} + + +void +g10_log_mpidump( const char *text, MPI a ) +{ + FILE *fp = log_stream(); + + g10_log_print_prefix(text); + mpi_print(fp, a, 1 ); + fputc('\n', fp); +} + +/**************** + * Special function to get the low 8 bytes from an mpi. + * This can be used as a keyid; KEYID is an 2 element array. + * Return the low 4 bytes. + */ +u32 +mpi_get_keyid( MPI a, u32 *keyid ) +{ +#if BYTES_PER_MPI_LIMB == 4 + if( keyid ) { + keyid[0] = a->nlimbs >= 2? a->d[1] : 0; + keyid[1] = a->nlimbs >= 1? a->d[0] : 0; + } + return a->nlimbs >= 1? a->d[0] : 0; +#elif BYTES_PER_MPI_LIMB == 8 + if( keyid ) { + keyid[0] = a->nlimbs? (u32)(a->d[0] >> 32) : 0; + keyid[1] = a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; + } + return a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0; +#else + #error Make this function work with other LIMB sizes +#endif +} + + +/**************** + * Return an m_alloced buffer with the MPI (msb first). + * NBYTES receives the length of this buffer. Caller must free the + * return string (This function does return a 0 byte buffer with NBYTES + * set to zero if the value of A is zero. If sign is not NULL, it will + * be set to the sign of the A. + */ +static byte * +do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure ) +{ + byte *p, *buffer; + mpi_limb_t alimb; + int i; + + if( sign ) + *sign = a->sign; + *nbytes = a->nlimbs * BYTES_PER_MPI_LIMB; + p = buffer = force_secure || mpi_is_secure(a) ? m_alloc_secure( *nbytes) + : m_alloc( *nbytes ); + + for(i=a->nlimbs-1; i >= 0; i-- ) { + alimb = a->d[i]; + #if BYTES_PER_MPI_LIMB == 4 + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; + #elif BYTES_PER_MPI_LIMB == 8 + *p++ = alimb >> 56; + *p++ = alimb >> 48; + *p++ = alimb >> 40; + *p++ = alimb >> 32; + *p++ = alimb >> 24; + *p++ = alimb >> 16; + *p++ = alimb >> 8; + *p++ = alimb ; + #else + #error please implement for this limb size. + #endif + } + + /* this is sub-optimal but we need to do the shift oepration because + * the caller has to free the returned buffer */ + for(p=buffer; !*p && *nbytes; p++, --*nbytes ) + ; + if( p != buffer ) + memmove(buffer,p, *nbytes); + return buffer; +} + + +byte * +mpi_get_buffer( MPI a, unsigned *nbytes, int *sign ) +{ + return do_get_buffer( a, nbytes, sign, 0 ); +} + +byte * +mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign ) +{ + return do_get_buffer( a, nbytes, sign, 1 ); +} + +/**************** + * Use BUFFER to update MPI. + */ +void +mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign ) +{ + const byte *p; + mpi_limb_t alimb; + int nlimbs; + int i; + + nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; + RESIZE_IF_NEEDED(a, nlimbs); + a->sign = sign; + + for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) { + #if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + alimb |= *p-- << 8 ; + alimb |= *p-- << 16 ; + alimb |= *p-- << 24 ; + #elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + alimb |= (mpi_limb_t)*p-- << 8 ; + alimb |= (mpi_limb_t)*p-- << 16 ; + alimb |= (mpi_limb_t)*p-- << 24 ; + alimb |= (mpi_limb_t)*p-- << 32 ; + alimb |= (mpi_limb_t)*p-- << 40 ; + alimb |= (mpi_limb_t)*p-- << 48 ; + alimb |= (mpi_limb_t)*p-- << 56 ; + #else + #error please implement for this limb size. + #endif + a->d[i++] = alimb; + } + if( p >= buffer ) { + #if BYTES_PER_MPI_LIMB == 4 + alimb = *p-- ; + if( p >= buffer ) alimb |= *p-- << 8 ; + if( p >= buffer ) alimb |= *p-- << 16 ; + if( p >= buffer ) alimb |= *p-- << 24 ; + #elif BYTES_PER_MPI_LIMB == 8 + alimb = (mpi_limb_t)*p-- ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ; + if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ; + #else + #error please implement for this limb size. + #endif + a->d[i++] = alimb; + } + a->nlimbs = i; + assert( i == nlimbs ); +} + diff --git a/mpi/mpih-cmp.c b/mpi/mpih-cmp.c new file mode 100644 index 000000000..03d41557c --- /dev/null +++ b/mpi/mpih-cmp.c @@ -0,0 +1,62 @@ +/* mpihelp-sub.c - MPI helper functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> + +#include "mpi-internal.h" + +/**************** + * Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE. + * There are no restrictions on the relative sizes of + * the two arguments. + * Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2. + */ +int +mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t op1_word, op2_word; + + for( i = size - 1; i >= 0 ; i--) { + op1_word = op1_ptr[i]; + op2_word = op2_ptr[i]; + if( op1_word != op2_word ) + goto diff; + } + return 0; + + diff: + /* This can *not* be simplified to + * op2_word - op2_word + * since that expression might give signed overflow. */ + return (op1_word > op2_word) ? 1 : -1; +} + diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c new file mode 100644 index 000000000..6eb0e1a34 --- /dev/null +++ b/mpi/mpih-div.c @@ -0,0 +1,537 @@ +/* mpihelp-div.c - MPI helper functions + * Copyright (C) 1994, 1996 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include "mpi-internal.h" +#include "longlong.h" + +#ifndef UMUL_TIME + #define UMUL_TIME 1 +#endif +#ifndef UDIV_TIME + #define UDIV_TIME UMUL_TIME +#endif + +/* FIXME: We should be using invert_limb (or invert_normalized_limb) + * here (not udiv_qrnnd). + */ + +mpi_limb_t +mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + /* Botch: Should this be handled at all? Rely on callers? */ + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV(dummy, r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + * + * Special case for DIVISOR_LIMB == 100...000. + */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + i--; + + for( ; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV(dummy, r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if( UDIV_NEEDS_NORMALIZATION ) { + int normalization_steps; + + count_leading_zeros(normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for(i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (dummy, r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + i--; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (dummy, r, r, n0, divisor_limb); + } + return r; + } +} + +/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write + * the NSIZE-DSIZE least significant quotient limbs at QP + * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is + * non-zero, generate that many fraction bits and append them after the + * other quotient limbs. + * Return the most significant limb of the quotient, this is always 0 or 1. + * + * Preconditions: + * 0. NSIZE >= DSIZE. + * 1. The most significant bit of the divisor must be set. + * 2. QP must either not overlap with the input operands at all, or + * QP + DSIZE >= NP must hold true. (This means that it's + * possible to put the quotient in the high part of NUM, right after the + * remainder in NUM. + * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero. + */ + +mpi_limb_t +mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, + mpi_ptr_t np, mpi_size_t nsize, + mpi_ptr_t dp, mpi_size_t dsize) +{ + mpi_limb_t most_significant_q_limb = 0; + + switch(dsize) { + case 0: + /* We are asked to divide by zero, so go ahead and do it! (To make + the compiler not remove this statement, return the value.) */ + return 1 / dsize; + + case 1: + { + mpi_size_t i; + mpi_limb_t n1; + mpi_limb_t d; + + d = dp[0]; + n1 = np[nsize - 1]; + + if( n1 >= d ) { + n1 -= d; + most_significant_q_limb = 1; + } + + qp += qextra_limbs; + for( i = nsize - 2; i >= 0; i--) + udiv_qrnnd( qp[i], n1, n1, np[i], d ); + qp -= qextra_limbs; + + for( i = qextra_limbs - 1; i >= 0; i-- ) + udiv_qrnnd (qp[i], n1, n1, 0, d); + + np[0] = n1; + } + break; + + case 2: + { + mpi_size_t i; + mpi_limb_t n1, n0, n2; + mpi_limb_t d1, d0; + + np += nsize - 2; + d1 = dp[1]; + d0 = dp[0]; + n1 = np[1]; + n0 = np[0]; + + if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) { + sub_ddmmss (n1, n0, n1, n0, d1, d0); + most_significant_q_limb = 1; + } + + for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) { + mpi_limb_t q; + mpi_limb_t r; + + if( i >= qextra_limbs ) + np--; + else + np[0] = 0; + + if( n1 == d1 ) { + /* Q should be either 111..111 or 111..110. Need special + * treatment of this rare case as normal division would + * give overflow. */ + q = ~(mpi_limb_t)0; + + r = n0 + d1; + if( r < d1 ) { /* Carry in the addition? */ + add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 ); + qp[i] = q; + continue; + } + n1 = d0 - (d0 != 0?1:0); + n0 = -d0; + } + else { + udiv_qrnnd (q, r, n1, n0, d1); + umul_ppmm (n1, n0, d0, q); + } + + n2 = np[0]; + q_test: + if( n1 > r || (n1 == r && n0 > n2) ) { + /* The estimated Q was too large. */ + q--; + sub_ddmmss (n1, n0, n1, n0, 0, d0); + r += d1; + if( r >= d1 ) /* If not carry, test Q again. */ + goto q_test; + } + + qp[i] = q; + sub_ddmmss (n1, n0, r, n2, n1, n0); + } + np[1] = n1; + np[0] = n0; + } + break; + + default: + { + mpi_size_t i; + mpi_limb_t dX, d1, n0; + + np += nsize - dsize; + dX = dp[dsize - 1]; + d1 = dp[dsize - 2]; + n0 = np[dsize - 1]; + + if( n0 >= dX ) { + if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) { + mpihelp_sub_n(np, np, dp, dsize); + n0 = np[dsize - 1]; + most_significant_q_limb = 1; + } + } + + for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { + mpi_limb_t q; + mpi_limb_t n1, n2; + mpi_limb_t cy_limb; + + if( i >= qextra_limbs ) { + np--; + n2 = np[dsize]; + } + else { + n2 = np[dsize - 1]; + MPN_COPY_DECR (np + 1, np, dsize - 1); + np[0] = 0; + } + + if( n0 == dX ) { + /* This might over-estimate q, but it's probably not worth + * the extra code here to find out. */ + q = ~(mpi_limb_t)0; + } + else { + mpi_limb_t r; + + udiv_qrnnd(q, r, n0, np[dsize - 1], dX); + umul_ppmm(n1, n0, d1, q); + + while( n1 > r || (n1 == r && n0 > np[dsize - 2])) { + q--; + r += dX; + if( r < dX ) /* I.e. "carry in previous addition?" */ + break; + n1 -= n0 < d1; + n0 -= d1; + } + } + + /* Possible optimization: We already have (q * n0) and (1 * n1) + * after the calculation of q. Taking advantage of that, we + * could make this loop make two iterations less. */ + cy_limb = mpihelp_submul_1(np, dp, dsize, q); + + if( n2 != cy_limb ) { + mpihelp_add_n(np, np, dp, dsize); + q--; + } + + qp[i] = q; + n0 = np[dsize - 1]; + } + } + } + + return most_significant_q_limb; +} + + +/**************** + * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB. + * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR. + * Return the single-limb remainder. + * There are no constraints on the value of the divisor. + * + * QUOT_PTR and DIVIDEND_PTR might point to the same limb. + */ + +mpi_limb_t +mpihelp_divmod_1( mpi_ptr_t quot_ptr, + mpi_ptr_t dividend_ptr, mpi_size_t dividend_size, + mpi_limb_t divisor_limb) +{ + mpi_size_t i; + mpi_limb_t n1, n0, r; + int dummy; + + if( !dividend_size ) + return 0; + + /* If multiplication is much faster than division, and the + * dividend is large, pre-invert the divisor, and use + * only multiplications in the inner loop. + * + * This test should be read: + * Does it ever help to use udiv_qrnnd_preinv? + * && Does what we save compensate for the inversion overhead? + */ + if( UDIV_TIME > (2 * UMUL_TIME + 6) + && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) { + int normalization_steps; + + count_leading_zeros( normalization_steps, divisor_limb ); + if( normalization_steps ) { + mpi_limb_t divisor_limb_inverted; + + divisor_limb <<= normalization_steps; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t)0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb, divisor_limb_inverted); + n1 = n0; + } + UDIV_QRNND_PREINV( quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb, divisor_limb_inverted); + return r >> normalization_steps; + } + else { + mpi_limb_t divisor_limb_inverted; + + /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The + * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the + * most significant bit (with weight 2**N) implicit. + */ + /* Special case for DIVISOR_LIMB == 100...000. */ + if( !(divisor_limb << 1) ) + divisor_limb_inverted = ~(mpi_limb_t) 0; + else + udiv_qrnnd(divisor_limb_inverted, dummy, + -divisor_limb, 0, divisor_limb); + + i = dividend_size - 1; + r = dividend_ptr[i]; + + if( r >= divisor_limb ) + r = 0; + else + quot_ptr[i--] = 0; + + for( ; i >= 0; i-- ) { + n0 = dividend_ptr[i]; + UDIV_QRNND_PREINV( quot_ptr[i], r, r, + n0, divisor_limb, divisor_limb_inverted); + } + return r; + } + } + else { + if(UDIV_NEEDS_NORMALIZATION) { + int normalization_steps; + + count_leading_zeros (normalization_steps, divisor_limb); + if( normalization_steps ) { + divisor_limb <<= normalization_steps; + + n1 = dividend_ptr[dividend_size - 1]; + r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps); + + /* Possible optimization: + * if (r == 0 + * && divisor_limb > ((n1 << normalization_steps) + * | (dividend_ptr[dividend_size - 2] >> ...))) + * ...one division less... + */ + for( i = dividend_size - 2; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd (quot_ptr[i + 1], r, r, + ((n1 << normalization_steps) + | (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))), + divisor_limb); + n1 = n0; + } + udiv_qrnnd (quot_ptr[0], r, r, + n1 << normalization_steps, + divisor_limb); + return r >> normalization_steps; + } + } + /* No normalization needed, either because udiv_qrnnd doesn't require + * it, or because DIVISOR_LIMB is already normalized. */ + i = dividend_size - 1; + r = dividend_ptr[i]; + + if(r >= divisor_limb) + r = 0; + else + quot_ptr[i--] = 0; + + for(; i >= 0; i--) { + n0 = dividend_ptr[i]; + udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb ); + } + return r; + } +} + + diff --git a/mpi/mpih-mul.c b/mpi/mpih-mul.c new file mode 100644 index 000000000..db6c1aeb8 --- /dev/null +++ b/mpi/mpih-mul.c @@ -0,0 +1,528 @@ +/* mpihelp-mul.c - MPI helper functions + * Copyright (C) 1994, 1996, 1998, 1999, + * 2000 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "mpi-internal.h" +#include "longlong.h" + + + +#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \ + do { \ + if( (size) < KARATSUBA_THRESHOLD ) \ + mul_n_basecase (prodp, up, vp, size); \ + else \ + mul_n (prodp, up, vp, size, tspace); \ + } while (0); + +#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \ + do { \ + if ((size) < KARATSUBA_THRESHOLD) \ + mpih_sqr_n_basecase (prodp, up, size); \ + else \ + mpih_sqr_n (prodp, up, size, tspace); \ + } while (0); + + + + +/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP), + * both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are + * always stored. Return the most significant limb. + * + * Argument constraints: + * 1. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + * + * + * Handle simple cases with traditional multiplication. + * + * This is the most critical code of multiplication. All multiplies rely + * on this, both small and huge. Small ones arrive here immediately. Huge + * ones arrive here as this is the base case for Karatsuba's recursive + * algorithm below. + */ + +static mpi_limb_t +mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, + mpi_ptr_t vp, mpi_size_t size) +{ + mpi_size_t i; + mpi_limb_t cy; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO( prodp, size ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < size; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy; + prodp++; + } + + return cy; +} + + +static void +mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, + mpi_size_t size, mpi_ptr_t tspace ) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] ); + prodp[esize + size] = cy_limb; + } + else { + /* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm. + * + * Split U in two pieces, U1 and U0, such that + * U = U0 + U1*(B**n), + * and V in V1 and V0, such that + * V = V0 + V1*(B**n). + * + * UV is then computed recursively using the identity + * + * 2n n n n + * UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V + * 1 1 1 0 0 1 0 0 + * + * Where B = 2**BITS_PER_MP_LIMB. + */ + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + int negflg; + + /* Product H. ________________ ________________ + * |_____U1 x V1____||____U0 x V0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(V0-V1)_| + */ + if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) { + mpihelp_sub_n(prodp, up + hsize, up, hsize); + negflg = 0; + } + else { + mpihelp_sub_n(prodp, up, up + hsize, hsize); + negflg = 1; + } + if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) { + mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize); + negflg ^= 1; + } + else { + mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize); + /* No change of NEGFLG. */ + } + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size); + + /* Add/copy product H. */ + MPN_COPY (prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n( prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number) */ + if(negflg) + cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size); + else + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x V0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. + */ + MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size); + + /* Add/copy Product L (twice) */ + + cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1(prodp + size, prodp + size, size, 1); + } +} + + +void +mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size ) +{ + mpi_size_t i; + mpi_limb_t cy_limb; + mpi_limb_t v_limb; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = up[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, size ); + else + MPN_ZERO(prodp, size); + cy_limb = 0; + } + else + cy_limb = mpihelp_mul_1( prodp, up, size, v_limb ); + + prodp[size] = cy_limb; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i=1; i < size; i++) { + v_limb = up[i]; + if( v_limb <= 1 ) { + cy_limb = 0; + if( v_limb == 1 ) + cy_limb = mpihelp_add_n(prodp, prodp, up, size); + } + else + cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb); + + prodp[size] = cy_limb; + prodp++; + } +} + + +void +mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace) +{ + if( size & 1 ) { + /* The size is odd, and the code below doesn't handle that. + * Multiply the least significant (size - 1) limbs with a recursive + * call, and handle the most significant limb of S1 and S2 + * separately. + * A slightly faster way to do this would be to make the Karatsuba + * code below behave as if the size were even, and let it check for + * odd size in the end. I.e., in essence move this code to the end. + * Doing so would save us a recursive call, and potentially make the + * stack grow a lot less. + */ + mpi_size_t esize = size - 1; /* even size */ + mpi_limb_t cy_limb; + + MPN_SQR_N_RECURSE( prodp, up, esize, tspace ); + cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] ); + prodp[esize + esize] = cy_limb; + cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] ); + + prodp[esize + size] = cy_limb; + } + else { + mpi_size_t hsize = size >> 1; + mpi_limb_t cy; + + /* Product H. ________________ ________________ + * |_____U1 x U1____||____U0 x U0_____| + * Put result in upper part of PROD and pass low part of TSPACE + * as new TSPACE. + */ + MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace); + + /* Product M. ________________ + * |_(U1-U0)(U0-U1)_| + */ + if( mpihelp_cmp( up + hsize, up, hsize) >= 0 ) + mpihelp_sub_n( prodp, up + hsize, up, hsize); + else + mpihelp_sub_n (prodp, up, up + hsize, hsize); + + /* Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size); + + /* Add/copy product H */ + MPN_COPY(prodp + hsize, prodp + size, hsize); + cy = mpihelp_add_n(prodp + size, prodp + size, + prodp + size + hsize, hsize); + + /* Add product M (if NEGFLG M is a negative number). */ + cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size); + + /* Product L. ________________ ________________ + * |________________||____U0 x U0_____| + * Read temporary operands from low part of PROD. + * Put result in low part of TSPACE using upper part of TSPACE + * as new TSPACE. */ + MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size); + + /* Add/copy Product L (twice). */ + cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size); + if( cy ) + mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, + hsize, cy); + + MPN_COPY(prodp, tspace, hsize); + cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize); + if( cy ) + mpihelp_add_1 (prodp + size, prodp + size, size, 1); + } +} + + +/* This should be made into an inline function in gmp.h. */ +void +mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size) +{ + int secure; + + if( up == vp ) { + if( size < KARATSUBA_THRESHOLD ) + mpih_sqr_n_basecase( prodp, up, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mpih_sqr_n( prodp, up, size, tspace ); + mpi_free_limb_space( tspace ); + } + } + else { + if( size < KARATSUBA_THRESHOLD ) + mul_n_basecase( prodp, up, vp, size ); + else { + mpi_ptr_t tspace; + secure = m_is_secure( up ) || m_is_secure( vp ); + tspace = mpi_alloc_limb_space( 2 * size, secure ); + mul_n (prodp, up, vp, size, tspace); + mpi_free_limb_space( tspace ); + } + } +} + + + +void +mpihelp_mul_karatsuba_case( mpi_ptr_t prodp, + mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize, + struct karatsuba_ctx *ctx ) +{ + mpi_limb_t cy; + + if( !ctx->tspace || ctx->tspace_size < vsize ) { + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + ctx->tspace = mpi_alloc_limb_space( 2 * vsize, + m_is_secure( up ) || m_is_secure( vp ) ); + ctx->tspace_size = vsize; + } + + MPN_MUL_N_RECURSE( prodp, up, vp, vsize, ctx->tspace ); + + prodp += vsize; + up += vsize; + usize -= vsize; + if( usize >= vsize ) { + if( !ctx->tp || ctx->tp_size < vsize ) { + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + ctx->tp = mpi_alloc_limb_space( 2 * vsize, m_is_secure( up ) + || m_is_secure( vp ) ); + ctx->tp_size = vsize; + } + + do { + MPN_MUL_N_RECURSE( ctx->tp, up, vp, vsize, ctx->tspace ); + cy = mpihelp_add_n( prodp, prodp, ctx->tp, vsize ); + mpihelp_add_1( prodp + vsize, ctx->tp + vsize, vsize, cy ); + prodp += vsize; + up += vsize; + usize -= vsize; + } while( usize >= vsize ); + } + + if( usize ) { + if( usize < KARATSUBA_THRESHOLD ) { + mpihelp_mul( ctx->tspace, vp, vsize, up, usize ); + } + else { + if( !ctx->next ) { + ctx->next = m_alloc_clear( sizeof *ctx ); + } + mpihelp_mul_karatsuba_case( ctx->tspace, + vp, vsize, + up, usize, + ctx->next ); + } + + cy = mpihelp_add_n( prodp, prodp, ctx->tspace, vsize); + mpihelp_add_1( prodp + vsize, ctx->tspace + vsize, usize, cy ); + } +} + + +void +mpihelp_release_karatsuba_ctx( struct karatsuba_ctx *ctx ) +{ + struct karatsuba_ctx *ctx2; + + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + for( ctx=ctx->next; ctx; ctx = ctx2 ) { + ctx2 = ctx->next; + if( ctx->tp ) + mpi_free_limb_space( ctx->tp ); + if( ctx->tspace ) + mpi_free_limb_space( ctx->tspace ); + m_free( ctx ); + } +} + +/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs) + * and v (pointed to by VP, with VSIZE limbs), and store the result at + * PRODP. USIZE + VSIZE limbs are always stored, but if the input + * operands are normalized. Return the most significant limb of the + * result. + * + * NOTE: The space pointed to by PRODP is overwritten before finished + * with U and V, so overlap is an error. + * + * Argument constraints: + * 1. USIZE >= VSIZE. + * 2. PRODP != UP and PRODP != VP, i.e. the destination + * must be distinct from the multiplier and the multiplicand. + */ + +mpi_limb_t +mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize, + mpi_ptr_t vp, mpi_size_t vsize) +{ + mpi_ptr_t prod_endp = prodp + usize + vsize - 1; + mpi_limb_t cy; + struct karatsuba_ctx ctx; + + if( vsize < KARATSUBA_THRESHOLD ) { + mpi_size_t i; + mpi_limb_t v_limb; + + if( !vsize ) + return 0; + + /* Multiply by the first limb in V separately, as the result can be + * stored (not added) to PROD. We also avoid a loop for zeroing. */ + v_limb = vp[0]; + if( v_limb <= 1 ) { + if( v_limb == 1 ) + MPN_COPY( prodp, up, usize ); + else + MPN_ZERO( prodp, usize ); + cy = 0; + } + else + cy = mpihelp_mul_1( prodp, up, usize, v_limb ); + + prodp[usize] = cy; + prodp++; + + /* For each iteration in the outer loop, multiply one limb from + * U with one limb from V, and add it to PROD. */ + for( i = 1; i < vsize; i++ ) { + v_limb = vp[i]; + if( v_limb <= 1 ) { + cy = 0; + if( v_limb == 1 ) + cy = mpihelp_add_n(prodp, prodp, up, usize); + } + else + cy = mpihelp_addmul_1(prodp, up, usize, v_limb); + + prodp[usize] = cy; + prodp++; + } + + return cy; + } + + memset( &ctx, 0, sizeof ctx ); + mpihelp_mul_karatsuba_case( prodp, up, usize, vp, vsize, &ctx ); + mpihelp_release_karatsuba_ctx( &ctx ); + return *prod_endp; +} + + diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c new file mode 100644 index 000000000..04e280caa --- /dev/null +++ b/mpi/mpiutil.c @@ -0,0 +1,471 @@ +/* mpiutil.ac - Utility functions for MPI + * Copyright (C) 1998, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "mpi.h" +#include "mpi-internal.h" +#include "memory.h" +#include "util.h" + + +#ifdef M_DEBUG + #undef mpi_alloc + #undef mpi_alloc_secure + #undef mpi_free +#endif + +/**************** + * Note: It was a bad idea to use the number of limbs to allocate + * because on a alpha the limbs are large but we normally need + * integers of n bits - So we should chnage this to bits (or bytes). + * + * But mpi_alloc is used in a lot of places :-) + */ +MPI +#ifdef M_DEBUG +mpi_debug_alloc( unsigned nlimbs, const char *info ) +#else +mpi_alloc( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); + #ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL; + #else + a = m_alloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL; + #endif + a->alloced = nlimbs; + a->nlimbs = 0; + a->sign = 0; + a->flags = 0; + a->nbits = 0; + return a; +} + +void +mpi_m_check( MPI a ) +{ + m_check(a); + m_check(a->d); +} + +MPI +#ifdef M_DEBUG +mpi_debug_alloc_secure( unsigned nlimbs, const char *info ) +#else +mpi_alloc_secure( unsigned nlimbs ) +#endif +{ + MPI a; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB ); + #ifdef M_DEBUG + a = m_debug_alloc( sizeof *a, info ); + a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL; + #else + a = m_alloc( sizeof *a ); + a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL; + #endif + a->alloced = nlimbs; + a->flags = 1; + a->nlimbs = 0; + a->sign = 0; + a->nbits = 0; + return a; +} + + +#if 0 +static void *unused_limbs_5; +static void *unused_limbs_32; +static void *unused_limbs_64; +#endif + +mpi_ptr_t +#ifdef M_DEBUG +mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info ) +#else +mpi_alloc_limb_space( unsigned nlimbs, int secure ) +#endif +{ + size_t len = nlimbs * sizeof(mpi_limb_t); + mpi_ptr_t p; + + if( DBG_MEMORY ) + log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 ); + #if 0 + if( !secure ) { + if( nlimbs == 5 && unused_limbs_5 ) { /* DSA 160 bits */ + p = unused_limbs_5; + unused_limbs_5 = *p; + return p; + } + else if( nlimbs == 32 && unused_limbs_32 ) { /* DSA 1024 bits */ + p = unused_limbs_32; + unused_limbs_32 = *p; + return p; + } + else if( nlimbs == 64 && unused_limbs_64 ) { /* DSA 2*1024 bits */ + p = unused_limbs_64; + unused_limbs_64 = *p; + return p; + } + } + #endif + + #ifdef M_DEBUG + p = secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info ); + #else + p = secure? m_alloc_secure( len ):m_alloc( len ); + #endif + + return p; +} + +void +#ifdef M_DEBUG +mpi_debug_free_limb_space( mpi_ptr_t a, const char *info ) +#else +mpi_free_limb_space( mpi_ptr_t a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 ); + + #if 0 + if( !m_is_secure(a) ) { + size_t nlimbs = m_size(a) / 4 ; + void *p = a; + + if( nlimbs == 5 ) { /* DSA 160 bits */ + *a = unused_limbs_5; + unused_limbs_5 = a; + return; + } + else if( nlimbs == 32 ) { /* DSA 1024 bits */ + *a = unused_limbs_32; + unused_limbs_32 = a; + return; + } + else if( nlimbs == 64 ) { /* DSA 2*1024 bits */ + *a = unused_limbs_64; + unused_limbs_64 = a; + return; + } + } + #endif + + + m_free(a); +} + + +void +mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs ) +{ + mpi_free_limb_space(a->d); + a->d = ap; + a->alloced = nlimbs; +} + + + +/**************** + * Resize the array of A to NLIMBS. the additional space is cleared + * (set to 0) [done by m_realloc()] + */ +void +#ifdef M_DEBUG +mpi_debug_resize( MPI a, unsigned nlimbs, const char *info ) +#else +mpi_resize( MPI a, unsigned nlimbs ) +#endif +{ + if( nlimbs <= a->alloced ) + return; /* no need to do it */ + /* Note: a->secure is not used - instead the realloc functions + * take care of it. Maybe we should drop a->secure completely + * and rely on a mpi_is_secure function, which would be + * a wrapper around m_is_secure + */ + #ifdef M_DEBUG + if( a->d ) + a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info ); + else + a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info ); + #else + if( a->d ) + a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) ); + else + a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) ); + #endif + a->alloced = nlimbs; +} + +void +mpi_clear( MPI a ) +{ + a->nlimbs = 0; + a->nbits = 0; + a->flags = 0; +} + + +void +#ifdef M_DEBUG +mpi_debug_free( MPI a, const char *info ) +#else +mpi_free( MPI a ) +#endif +{ + if( !a ) + return; + if( DBG_MEMORY ) + log_debug("mpi_free\n" ); + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, info); + #else + mpi_free_limb_space(a->d); + #endif + } + if( a->flags & ~7 ) + log_bug("invalid flag value in mpi\n"); + m_free(a); +} + + +void +mpi_set_secure( MPI a ) +{ + mpi_ptr_t ap, bp; + + if( (a->flags & 1) ) + return; + a->flags |= 1; + ap = a->d; + if( !a->nlimbs ) { + assert(!ap); + return; + } + #ifdef M_DEBUG + bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" ); + #else + bp = mpi_alloc_limb_space( a->nlimbs, 1 ); + #endif + MPN_COPY( bp, ap, a->nlimbs ); + a->d = bp; + #ifdef M_DEBUG + mpi_debug_free_limb_space(ap, "set_secure"); + #else + mpi_free_limb_space(ap); + #endif +} + + +MPI +mpi_set_opaque( MPI a, void *p, int len ) +{ + if( !a ) { + #ifdef M_DEBUG + a = mpi_debug_alloc(0,"alloc_opaque"); + #else + a = mpi_alloc(0); + #endif + } + + if( a->flags & 4 ) + m_free( a->d ); + else { + #ifdef M_DEBUG + mpi_debug_free_limb_space(a->d, "alloc_opaque"); + #else + mpi_free_limb_space(a->d); + #endif + } + + a->d = p; + a->alloced = 0; + a->nlimbs = 0; + a->nbits = len; + a->flags = 4; + return a; +} + + +void * +mpi_get_opaque( MPI a, int *len ) +{ + if( !(a->flags & 4) ) + log_bug("mpi_get_opaque on normal mpi\n"); + if( len ) + *len = a->nbits; + return a->d; +} + + +/**************** + * Note: This copy function should not interpret the MPI + * but copy it transparently. + */ +MPI +#ifdef M_DEBUG +mpi_debug_copy( MPI a, const char *info ) +#else +mpi_copy( MPI a ) +#endif +{ + int i; + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) + : m_alloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { + #ifdef M_DEBUG + b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) + : mpi_debug_alloc( a->nlimbs, info ); + #else + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + #endif + b->nlimbs = a->nlimbs; + b->sign = a->sign; + b->flags = a->flags; + b->nbits = a->nbits; + for(i=0; i < b->nlimbs; i++ ) + b->d[i] = a->d[i]; + } + else + b = NULL; + return b; +} + + +/**************** + * This function allocates an MPI which is optimized to hold + * a value as large as the one given in the arhgument and allocates it + * with the same flags as A. + */ +MPI +#ifdef M_DEBUG +mpi_debug_alloc_like( MPI a, const char *info ) +#else +mpi_alloc_like( MPI a ) +#endif +{ + MPI b; + + if( a && (a->flags & 4) ) { + void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits ) + : m_alloc( a->nbits ); + memcpy( p, a->d, a->nbits ); + b = mpi_set_opaque( NULL, p, a->nbits ); + } + else if( a ) { + #ifdef M_DEBUG + b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info ) + : mpi_debug_alloc( a->nlimbs, info ); + #else + b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs ) + : mpi_alloc( a->nlimbs ); + #endif + b->nlimbs = 0; + b->sign = 0; + b->flags = a->flags; + b->nbits = 0; + } + else + b = NULL; + return b; +} + + +void +mpi_set( MPI w, MPI u) +{ + mpi_ptr_t wp, up; + mpi_size_t usize = u->nlimbs; + int usign = u->sign; + + RESIZE_IF_NEEDED(w, usize); + wp = w->d; + up = u->d; + MPN_COPY( wp, up, usize ); + w->nlimbs = usize; + w->nbits = u->nbits; + w->flags = u->flags; + w->sign = usign; +} + + +void +mpi_set_ui( MPI w, unsigned long u) +{ + RESIZE_IF_NEEDED(w, 1); + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + w->nbits = 0; + w->flags = 0; +} + + +MPI +mpi_alloc_set_ui( unsigned long u) +{ + #ifdef M_DEBUG + MPI w = mpi_debug_alloc(1,"alloc_set_ui"); + #else + MPI w = mpi_alloc(1); + #endif + w->d[0] = u; + w->nlimbs = u? 1:0; + w->sign = 0; + return w; +} + + +void +mpi_swap( MPI a, MPI b) +{ + struct gcry_mpi tmp; + + tmp = *a; *a = *b; *b = tmp; +} + diff --git a/mpi/pa7100/distfiles b/mpi/pa7100/distfiles new file mode 100644 index 000000000..fece94310 --- /dev/null +++ b/mpi/pa7100/distfiles @@ -0,0 +1,3 @@ +mpih-lshift.S +mpih-rshift.S + diff --git a/mpi/pa7100/mpih-lshift.S b/mpi/pa7100/mpih-lshift.S new file mode 100644 index 000000000..76368fe78 --- /dev/null +++ b/mpi/pa7100/mpih-lshift.S @@ -0,0 +1,96 @@ +/* hppa lshift + * optimized for the PA7100, where it runs at 3.25 cycles/limb + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export mpihelp_lshift + .label mpihelp_lshift + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(0,%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ; compute carry out limb + ldws,mb -4(0,%r25),%r29 + addib,<= -5,%r24,L$rest + vshd %r22,%r29,%r20 + + .label L$loop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + vshd %r22,%r29,%r20 + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,> -4,%r24,L$loop + vshd %r22,%r29,%r20 + + .label L$rest + addib,= 4,%r24,L$end1 + nop + .label L$eloop + ldws,mb -4(0,%r25),%r22 + stws,mb %r20,-4(0,%r26) + addib,<= -1,%r24,L$end2 + vshd %r29,%r22,%r20 + ldws,mb -4(0,%r25),%r29 + stws,mb %r20,-4(0,%r26) + addib,> -1,%r24,L$eloop + vshd %r22,%r29,%r20 + + .label L$end1 + stws,mb %r20,-4(0,%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + .label L$end2 + stws,mb %r20,-4(0,%r26) + .label L$0004 + vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(0,%r26) + + .exit + .procend + + + diff --git a/mpi/pa7100/mpih-rshift.S b/mpi/pa7100/mpih-rshift.S new file mode 100644 index 000000000..3bada7ce9 --- /dev/null +++ b/mpi/pa7100/mpih-rshift.S @@ -0,0 +1,92 @@ +/* hppa rshift + * optimized for the PA7100, where it runs at 3.25 cycles/limb + * + * Copyright (C) 1992, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (gr26) + * mpi_ptr_t up, (gr25) + * mpi_size_t usize, (gr24) + * unsigned cnt) (gr23) + */ + + .code + .export mpihelp_rshift + .label mpihelp_rshift + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(0,%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$r004 + vshd %r22,%r0,%r28 ; compute carry out limb + ldws,ma 4(0,%r25),%r29 + addib,<= -5,%r24,L$rrest + vshd %r29,%r22,%r20 + + .label L$roop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + vshd %r29,%r22,%r20 + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,> -4,%r24,L$roop + vshd %r29,%r22,%r20 + + .label L$rrest + addib,= 4,%r24,L$rend1 + nop + .label L$eroop + ldws,ma 4(0,%r25),%r22 + stws,ma %r20,4(0,%r26) + addib,<= -1,%r24,L$rend2 + vshd %r22,%r29,%r20 + ldws,ma 4(0,%r25),%r29 + stws,ma %r20,4(0,%r26) + addib,> -1,%r24,L$eroop + vshd %r29,%r22,%r20 + + .label L$rend1 + stws,ma %r20,4(0,%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + .label L$rend2 + stws,ma %r20,4(0,%r26) + .label L$r004 + vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(0,%r26) + + .exit + .procend + + diff --git a/mpi/power/distfiles b/mpi/power/distfiles new file mode 100644 index 000000000..e664c8db6 --- /dev/null +++ b/mpi/power/distfiles @@ -0,0 +1,7 @@ +mpih-add1.S +mpih-lshift.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-rshift.S +mpih-sub1.S diff --git a/mpi/power/mpih-add1.S b/mpi/power/mpih-add1.S new file mode 100644 index 000000000..7313ac618 --- /dev/null +++ b/mpi/power/mpih-add1.S @@ -0,0 +1,86 @@ +/* IBM POWER add_n -- Add two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1996, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# s2_ptr r5 +# size r6 + */ + + .toc + .extern mpihelp_add_n[DS] + .extern .mpihelp_add_n +.csect [PR] + .align 2 + .globl mpihelp_add_n + .globl .mpihelp_add_n + .csect mpihelp_add_n[DS] +mpihelp_add_n: + .long .mpihelp_add_n, TOC[tc0], 0 + .csect [PR] +.mpihelp_add_n: + andil. 10,6,1 # odd or even number of limbs? + l 8,0(4) # load least significant s1 limb + l 0,0(5) # load least significant s2 limb + cal 3,-4(3) # offset res_ptr, it's updated before it's used + sri 10,6,1 # count for unrolled loop + a 7,0,8 # add least significant limbs, set cy + mtctr 10 # copy count into CTR + beq 0,Leven # branch if even # of limbs (# of limbs >= 2) + +# We have an odd # of limbs. Add the first limbs separately. + cmpi 1,10,0 # is count for unrolled loop zero? + bne 1,L1 # branch if not + st 7,4(3) + aze 3,10 # use the fact that r10 is zero... + br # return + +# We added least significant limbs. Now reload the next limbs to enter loop. +L1: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + stu 7,4(3) + ae 7,0,8 # add limbs, set cy +Leven: lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + bdz Lend # If done, skip loop + +Loop: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + ae 11,9,10 # add previous limbs with cy, set cy + stu 7,4(3) # + lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + ae 7,0,8 # add previous limbs with cy, set cy + stu 11,4(3) # + bdn Loop # decrement CTR and loop back + +Lend: ae 11,9,10 # add limbs with cy, set cy + st 7,4(3) # + st 11,8(3) # + lil 3,0 # load cy into ... + aze 3,3 # ... return value register + br + diff --git a/mpi/power/mpih-lshift.S b/mpi/power/mpih-lshift.S new file mode 100644 index 000000000..20cf45353 --- /dev/null +++ b/mpi/power/mpih-lshift.S @@ -0,0 +1,64 @@ +/* IBM POWER lshift + * + * Copyright (C) 1992, 1994, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s_ptr r4 +# size r5 +# cnt r6 + */ + + .toc + .extern mpihelp_lshift[DS] + .extern .mpihelp_lshift +.csect [PR] + .align 2 + .globl mpihelp_lshift + .globl .mpihelp_lshift + .csect mpihelp_lshift[DS] +mpihelp_lshift: + .long .mpihelp_lshift, TOC[tc0], 0 + .csect [PR] +.mpihelp_lshift: + sli 0,5,2 + cax 9,3,0 + cax 4,4,0 + sfi 8,6,32 + mtctr 5 # put limb count in CTR loop register + lu 0,-4(4) # read most significant limb + sre 3,0,8 # compute carry out limb, and init MQ register + bdz Lend2 # if just one limb, skip loop + lu 0,-4(4) # read 2:nd most significant limb + sreq 7,0,8 # compute most significant limb of result + bdz Lend # if just two limb, skip loop +Loop: lu 0,-4(4) # load next lower limb + stu 7,-4(9) # store previous result during read latency + sreq 7,0,8 # compute result limb + bdn Loop # loop back until CTR is zero +Lend: stu 7,-4(9) # store 2:nd least significant limb +Lend2: sle 7,0,6 # compute least significant limb + st 7,-4(9) # store it + br + diff --git a/mpi/power/mpih-mul1.S b/mpi/power/mpih-mul1.S new file mode 100644 index 000000000..03fff4f98 --- /dev/null +++ b/mpi/power/mpih-mul1.S @@ -0,0 +1,115 @@ +/* IBM POWER mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1994, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect .mpihelp_mul_1[PR] + .align 2 + .globl mpihelp_mul_1 + .globl .mpihelp_mul_1 + .csect mpihelp_mul_1[DS] +mpihelp_mul_1: + .long .mpihelp_mul_1[PR], TOC[tc0], 0 + .csect .mpihelp_mul_1[PR] +.mpihelp_mul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 8 + ai 0,0,0 # reset carry + cax 9,9,7 + blt Lneg +Lpos: bdz Lend +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 8,0,9 + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 8,0,10 + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + cax 10,10,0 # adjust high limb for negative s2_limb + mfmq 0 + ae 8,0,9 + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + cax 9,9,0 # adjust high limb for negative s2_limb + mfmq 0 + ae 8,0,10 + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/mpi/power/mpih-mul2.S b/mpi/power/mpih-mul2.S new file mode 100644 index 000000000..3d7fc153c --- /dev/null +++ b/mpi/power/mpih-mul2.S @@ -0,0 +1,130 @@ +/* IBM POWER addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1992, 1994, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect .mpihelp_addmul_1[PR] + .align 2 + .globl mpihelp_addmul_1 + .globl .mpihelp_addmul_1 + .csect mpihelp_addmul_1[DS] +mpihelp_addmul_1: + .long .mpihelp_addmul_1[PR], TOC[tc0], 0 + .csect .mpihelp_addmul_1[PR] +.mpihelp_addmul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 8 + cax 9,9,7 + l 7,4(3) + a 8,8,7 # add res_limb + blt Lneg +Lpos: bdz Lend + +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 8,0,9 # low limb + old_cy_limb + old cy + l 7,4(3) + aze 10,10 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 8,0,10 + l 7,4(3) + aze 9,9 + a 8,8,7 + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 7 + ae 8,7,9 + l 7,4(3) + ae 10,10,0 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 7 + ae 8,7,10 + l 7,4(3) + ae 9,9,0 # propagate cy to new cy_limb + a 8,8,7 # add res_limb + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/mpi/power/mpih-mul3.S b/mpi/power/mpih-mul3.S new file mode 100644 index 000000000..f94018ca9 --- /dev/null +++ b/mpi/power/mpih-mul3.S @@ -0,0 +1,135 @@ +/* IBM POWER submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1992, 1994, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* + +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# size r5 +# s2_limb r6 + +# The RS/6000 has no unsigned 32x32->64 bit multiplication instruction. To +# obtain that operation, we have to use the 32x32->64 signed multiplication +# instruction, and add the appropriate compensation to the high limb of the +# result. We add the multiplicand if the multiplier has its most significant +# bit set, and we add the multiplier if the multiplicand has its most +# significant bit set. We need to preserve the carry flag between each +# iteration, so we have to compute the compensation carefully (the natural, +# srai+and doesn't work). Since the POWER architecture has a branch unit +# we can branch in zero cycles, so that's how we perform the additions. + */ + + .toc + .csect .mpihelp_submul_1[PR] + .align 2 + .globl mpihelp_submul_1 + .globl .mpihelp_submul_1 + .csect mpihelp_submul_1[DS] +mpihelp_submul_1: + .long .mpihelp_submul_1[PR], TOC[tc0], 0 + .csect .mpihelp_submul_1[PR] +.mpihelp_submul_1: + + cal 3,-4(3) + l 0,0(4) + cmpi 0,6,0 + mtctr 5 + mul 9,0,6 + srai 7,0,31 + and 7,7,6 + mfmq 11 + cax 9,9,7 + l 7,4(3) + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + blt Lneg +Lpos: bdz Lend + +Lploop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 0 + ae 11,0,9 # low limb + old_cy_limb + old cy + l 7,4(3) + aze 10,10 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Lp0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Lp0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 0 + ae 11,0,10 + l 7,4(3) + aze 9,9 + sf 8,11,7 + a 11,8,11 # invert cy (r11 is junk) + bge Lp1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Lp1: bdn Lploop + + b Lend + +Lneg: cax 9,9,0 + bdz Lend +Lnloop: lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 10,0,6 + mfmq 7 + ae 11,7,9 + l 7,4(3) + ae 10,10,0 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Ln0 + cax 10,10,6 # adjust high limb for negative limb from s1 +Ln0: bdz Lend0 + lu 0,4(4) + stu 8,4(3) + cmpi 0,0,0 + mul 9,0,6 + mfmq 7 + ae 11,7,10 + l 7,4(3) + ae 9,9,0 # propagate cy to new cy_limb + sf 8,11,7 # add res_limb + a 11,8,11 # invert cy (r11 is junk) + bge Ln1 + cax 9,9,6 # adjust high limb for negative limb from s1 +Ln1: bdn Lnloop + b Lend + +Lend0: cal 9,0(10) +Lend: st 8,4(3) + aze 3,9 + br + diff --git a/mpi/power/mpih-rshift.S b/mpi/power/mpih-rshift.S new file mode 100644 index 000000000..04fb5942d --- /dev/null +++ b/mpi/power/mpih-rshift.S @@ -0,0 +1,64 @@ +/* IBM POWER rshift + * + * Copyright (C) 1992, 1994, 1999 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s_ptr r4 +# size r5 +# cnt r6 +*/ + + .toc + .extern mpihelp_rshift[DS] + .extern .mpihelp_rshift +.csect [PR] + .align 2 + .globl mpihelp_rshift + .globl .mpihelp_rshift + .csect mpihelp_rshift[DS] +mpihelp_rshift: + .long .mpihelp_rshift, TOC[tc0], 0 + .csect [PR] +.mpihelp_rshift: + sfi 8,6,32 + mtctr 5 # put limb count in CTR loop register + l 0,0(4) # read least significant limb + ai 9,3,-4 # adjust res_ptr since it's offset in the stu:s + sle 3,0,8 # compute carry limb, and init MQ register + bdz Lend2 # if just one limb, skip loop + lu 0,4(4) # read 2:nd least significant limb + sleq 7,0,8 # compute least significant limb of result + bdz Lend # if just two limb, skip loop +Loop: lu 0,4(4) # load next higher limb + stu 7,4(9) # store previous result during read latency + sleq 7,0,8 # compute result limb + bdn Loop # loop back until CTR is zero +Lend: stu 7,4(9) # store 2:nd most significant limb +Lend2: sre 7,0,6 # compute most significant limb + st 7,4(9) # store it + br + + diff --git a/mpi/power/mpih-sub1.S b/mpi/power/mpih-sub1.S new file mode 100644 index 000000000..375a5be88 --- /dev/null +++ b/mpi/power/mpih-sub1.S @@ -0,0 +1,88 @@ +/* IBM POWER sub_n -- Subtract two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1995, 1996, 1999 + * Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + +/* +# INPUT PARAMETERS +# res_ptr r3 +# s1_ptr r4 +# s2_ptr r5 +# size r6 + */ + + .toc + .extern mpihelp_sub_n[DS] + .extern .mpihelp_sub_n +.csect [PR] + .align 2 + .globl mpihelp_sub_n + .globl .mpihelp_sub_n + .csect mpihelp_sub_n[DS] +mpihelp_sub_n: + .long .mpihelp_sub_n, TOC[tc0], 0 + .csect [PR] +.mpihelp_sub_n: + andil. 10,6,1 # odd or even number of limbs? + l 8,0(4) # load least significant s1 limb + l 0,0(5) # load least significant s2 limb + cal 3,-4(3) # offset res_ptr, it's updated before it's used + sri 10,6,1 # count for unrolled loop + sf 7,0,8 # subtract least significant limbs, set cy + mtctr 10 # copy count into CTR + beq 0,Leven # branch if even # of limbs (# of limbs >= 2) + +# We have an odd # of limbs. Add the first limbs separately. + cmpi 1,10,0 # is count for unrolled loop zero? + bne 1,L1 # branch if not + st 7,4(3) + sfe 3,0,0 # load !cy into ... + sfi 3,3,0 # ... return value register + br # return + +# We added least significant limbs. Now reload the next limbs to enter loop. +L1: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + stu 7,4(3) + sfe 7,0,8 # subtract limbs, set cy +Leven: lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + bdz Lend # If done, skip loop + +Loop: lu 8,4(4) # load s1 limb and update s1_ptr + lu 0,4(5) # load s2 limb and update s2_ptr + sfe 11,10,9 # subtract previous limbs with cy, set cy + stu 7,4(3) # + lu 9,4(4) # load s1 limb and update s1_ptr + lu 10,4(5) # load s2 limb and update s2_ptr + sfe 7,0,8 # subtract previous limbs with cy, set cy + stu 11,4(3) # + bdn Loop # decrement CTR and loop back + +Lend: sfe 11,10,9 # subtract limbs with cy, set cy + st 7,4(3) # + st 11,8(3) # + sfe 3,0,0 # load !cy into ... + sfi 3,3,0 # ... return value register + br + diff --git a/mpi/powerpc32/distfiles b/mpi/powerpc32/distfiles new file mode 100644 index 000000000..af10d795b --- /dev/null +++ b/mpi/powerpc32/distfiles @@ -0,0 +1,9 @@ +mpih-add1.S +mpih-sub1.S +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S +mpih-lshift.S +mpih-rshift.S +syntax.h + diff --git a/mpi/powerpc32/mpih-add1.S b/mpi/powerpc32/mpih-add1.S new file mode 100644 index 000000000..81c4e20f7 --- /dev/null +++ b/mpi/powerpc32/mpih-add1.S @@ -0,0 +1,136 @@ +/* PowerPC-32 add_n -- Add two limb vectors of equal, non-zero length. + * + * Copyright (C) 1992, 1994, 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_ptr_t s2_ptr, (r5) + * mpi_size_t size) (r6) + */ + + .toc + .extern mpihelp_add_n[DS] + .extern .mpihelp_add_n +.csect [PR] + .align 2 + .globl mpihelp_add_n + .globl .mpihelp_add_n + .csect mpihelp_add_n[DS] +mpihelp_add_n: + .long .mpihelp_add_n, TOC[tc0], 0 + .csect [PR] +.mpihelp_add_n: + mtctr 6 # copy size into CTR + lwz 8,0(4) # load least significant s1 limb + lwz 0,0(5) # load least significant s2 limb + addi 3,3,-4 # offset res_ptr, it is updated before used + addc 7,0,8 # add least significant limbs, set cy + bdz Lend # If done, skip loop +Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr + lwzu 0,4(5) # load s2 limb and update s2_ptr + stwu 7,4(3) # store previous limb in load latency slot + adde 7,0,8 # add new limbs with cy, set cy + bdnz Loop # decrement CTR and loop back +Lend: stw 7,4(3) # store ultimate result limb + li 3,0 # load cy into ... + addze 3,3 # ... return value register + blr + +#else +/* Add two limb vectors of equal, non-zero length for PowerPC. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +/* mp_limb_t mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, + mp_size_t size) + Calculate s1+s2 and put result in res_ptr; return carry, 0 or 1. */ + +/* Note on optimisation: This code is optimal for the 601. Almost every other + possible 2-unrolled inner loop will not be. Also, watch out for the + alignment... */ + +EALIGN(mpihelp_add_n,3,0) +/* Set up for loop below. */ + mtcrf 0x01,%r6 + srwi. %r7,%r6,1 + li %r10,0 + mtctr %r7 + bt 31,2f + +/* Clear the carry. */ + addic %r0,%r0,0 +/* Adjust pointers for loop. */ + addi %r3,%r3,-4 + addi %r4,%r4,-4 + addi %r5,%r5,-4 + b 0f + +2: lwz %r7,0(%r5) + lwz %r6,0(%r4) + addc %r6,%r6,%r7 + stw %r6,0(%r3) + beq 1f + +/* The loop. */ + +/* Align start of loop to an odd word boundary to guarantee that the + last two words can be fetched in one access (for 601). */ +0: lwz %r9,4(%r4) + lwz %r8,4(%r5) + lwzu %r6,8(%r4) + lwzu %r7,8(%r5) + adde %r8,%r9,%r8 + stw %r8,4(%r3) + adde %r6,%r6,%r7 + stwu %r6,8(%r3) + bdnz 0b +/* Return the carry. */ +1: addze %r3,%r10 + blr +END(mpihelp_add_n) +#endif + diff --git a/mpi/powerpc32/mpih-lshift.S b/mpi/powerpc32/mpih-lshift.S new file mode 100644 index 000000000..20ca7f922 --- /dev/null +++ b/mpi/powerpc32/mpih-lshift.S @@ -0,0 +1,198 @@ +/* PowerPC-32 lshift + * + * Copyright (C) 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_lshift( mpi_ptr_t wp, (r3) + * mpi_ptr_t up, (r4) + * mpi_size_t usize, (r5) + * unsigned cnt) (r6) + */ + + .toc +.csect .text[PR] + .align 2 + .globl mpihelp_lshift + .globl .mpihelp_lshift + .csect mpihelp_lshift[DS] +mpihelp_lshift: + .long .mpihelp_lshift, TOC[tc0], 0 + .csect .text[PR] +.mpihelp_lshift: + mtctr 5 # copy size into CTR + slwi 0,5,2 + add 7,3,0 # make r7 point at end of res + add 4,4,0 # make r4 point at end of s1 + subfic 8,6,32 + lwzu 11,-4(4) # load first s1 limb + srw 3,11,8 # compute function return value + bdz Lend1 + +Loop: lwzu 10,-4(4) + slw 9,11,6 + srw 12,10,8 + or 9,9,12 + stwu 9,-4(7) + bdz Lend2 + lwzu 11,-4(4) + slw 9,10,6 + srw 12,11,8 + or 9,9,12 + stwu 9,-4(7) + bdnz Loop + +Lend1: slw 0,11,6 + stw 0,-4(7) + blr + +Lend2: slw 0,10,6 + stw 0,-4(7) + blr + +#else +/* Shift a limb left, low level routine. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_lshift (mp_ptr wp, mp_srcptr up, mp_size_t usize, + unsigned int cnt) */ + +EALIGN(mpihelp_lshift,3,0) + mtctr %r5 # copy size into CTR + cmplwi %cr0,%r5,16 # is size < 16 + slwi %r0,%r5,2 + add %r7,%r3,%r0 # make r7 point at end of res + add %r4,%r4,%r0 # make r4 point at end of s1 + lwzu %r11,-4(%r4) # load first s1 limb + subfic %r8,%r6,32 + srw %r3,%r11,%r8 # compute function return value + bge %cr0,L(big) # branch if size >= 16 + + bdz L(end1) + +0: lwzu %r10,-4(%r4) + slw %r9,%r11,%r6 + srw %r12,%r10,%r8 + or %r9,%r9,%r12 + stwu %r9,-4(%r7) + bdz L(end2) + lwzu %r11,-4(%r4) + slw %r9,%r10,%r6 + srw %r12,%r11,%r8 + or %r9,%r9,%r12 + stwu %r9,-4(%r7) + bdnz 0b + +L(end1):slw %r0,%r11,%r6 + stw %r0,-4(%r7) + blr + + +/* Guaranteed not to succeed. */ +L(boom): tweq %r0,%r0 + +/* We imitate a case statement, by using (yuk!) fixed-length code chunks, + of size 4*12 bytes. We have to do this (or something) to make this PIC. */ +L(big): mflr %r9 + bltl- %cr0,L(boom) # Never taken, only used to set LR. + slwi %r10,%r6,4 + mflr %r12 + add %r10,%r12,%r10 + slwi %r8,%r6,5 + add %r10,%r8,%r10 + mtctr %r10 + addi %r5,%r5,-1 + mtlr %r9 + bctr + +L(end2):slw %r0,%r10,%r6 + stw %r0,-4(%r7) + blr + +#define DO_LSHIFT(n) \ + mtctr %r5; \ +0: lwzu %r10,-4(%r4); \ + slwi %r9,%r11,n; \ + inslwi %r9,%r10,n,32-n; \ + stwu %r9,-4(%r7); \ + bdz- L(end2); \ + lwzu %r11,-4(%r4); \ + slwi %r9,%r10,n; \ + inslwi %r9,%r11,n,32-n; \ + stwu %r9,-4(%r7); \ + bdnz 0b; \ + b L(end1) + + DO_LSHIFT(1) + DO_LSHIFT(2) + DO_LSHIFT(3) + DO_LSHIFT(4) + DO_LSHIFT(5) + DO_LSHIFT(6) + DO_LSHIFT(7) + DO_LSHIFT(8) + DO_LSHIFT(9) + DO_LSHIFT(10) + DO_LSHIFT(11) + DO_LSHIFT(12) + DO_LSHIFT(13) + DO_LSHIFT(14) + DO_LSHIFT(15) + DO_LSHIFT(16) + DO_LSHIFT(17) + DO_LSHIFT(18) + DO_LSHIFT(19) + DO_LSHIFT(20) + DO_LSHIFT(21) + DO_LSHIFT(22) + DO_LSHIFT(23) + DO_LSHIFT(24) + DO_LSHIFT(25) + DO_LSHIFT(26) + DO_LSHIFT(27) + DO_LSHIFT(28) + DO_LSHIFT(29) + DO_LSHIFT(30) + DO_LSHIFT(31) + +END(mpihelp_lshift) +#endif diff --git a/mpi/powerpc32/mpih-mul1.S b/mpi/powerpc32/mpih-mul1.S new file mode 100644 index 000000000..b3cb62f3e --- /dev/null +++ b/mpi/powerpc32/mpih-mul1.S @@ -0,0 +1,120 @@ +/* PowerPC-32 mul_1 -- Multiply a limb vector with a limb and store + * the result in a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1995, + * 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_mul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + .toc + .csect .mpihelp_mul_1[PR] + .align 2 + .globl mpihelp_mul_1 + .globl .mpihelp_mul_1 + .csect mpihelp_mul_1[DS] +mpihelp_mul_1: + .long .mpihelp_mul_1[PR], TOC[tc0], 0 + .csect .mpihelp_mul_1[PR] +.mpihelp_mul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + addi 3,3,-4 # adjust res_ptr + addic 5,5,0 # clear cy with dummy insn + bdz Lend + +Loop: lwzu 0,4(4) + stwu 7,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + bdnz Loop + +Lend: stw 7,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* mp_limb_t mpn_mul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate s1*s2 and put result in res_ptr; return carry. */ + +ENTRY(mpihelp_mul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + addi %r3,%r3,-4 # adjust res_ptr + addic %r5,%r5,0 # clear cy with dummy insn + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r7,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + bdnz 0b + +1: stw %r7,4(%r3) + addze %r3,%r10 + blr +END(mpihelp_mul_1) +#endif diff --git a/mpi/powerpc32/mpih-mul2.S b/mpi/powerpc32/mpih-mul2.S new file mode 100644 index 000000000..d3b39bc01 --- /dev/null +++ b/mpi/powerpc32/mpih-mul2.S @@ -0,0 +1,127 @@ +/* PowerPC-32 addmul_1 -- Multiply a limb vector with a limb and add + * the result to a second limb vector. + * + * Copyright (C) 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_addmul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + + .toc + .csect .mpihelp_addmul_1[PR] + .align 2 + .globl mpihelp_addmul_1 + .globl .mpihelp_addmul_1 + .csect mpihelp_addmul_1[DS] +mpihelp_addmul_1: + .long .mpihelp_addmul_1[PR], TOC[tc0], 0 + .csect .mpihelp_addmul_1[PR] +.mpihelp_addmul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + lwz 9,0(3) + addc 8,7,9 + addi 3,3,-4 + bdz Lend + +Loop: lwzu 0,4(4) + stwu 8,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + lwz 9,4(3) + addze 10,10 + addc 8,7,9 + bdnz Loop + +Lend: stw 8,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a single limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* mp_limb_t mpn_addmul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate res+s1*s2 and put result back in res; return carry. */ +ENTRY(mpihelp_addmul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + lwz %r9,0(%r3) + addc %r8,%r7,%r9 + addi %r3,%r3,-4 /* adjust res_ptr */ + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r8,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + lwz %r9,4(%r3) + addze %r10,%r10 + addc %r8,%r7,%r9 + bdnz 0b + +1: stw %r8,4(%r3) + addze %r3,%r10 + blr +END(mpihelp_addmul_1) +#endif diff --git a/mpi/powerpc32/mpih-mul3.S b/mpi/powerpc32/mpih-mul3.S new file mode 100644 index 000000000..d84f853ba --- /dev/null +++ b/mpi/powerpc32/mpih-mul3.S @@ -0,0 +1,130 @@ +/* PowerPC-32 submul_1 -- Multiply a limb vector with a limb and subtract + * the result from a second limb vector. + * + * Copyright (C) 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_submul_1( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_size_t s1_size, (r5) + * mpi_limb_t s2_limb) (r6) + * + * This is a fairly straightforward implementation. The timing of the PC601 + * is hard to understand, so I will wait to optimize this until I have some + * hardware to play with. + * + * The code trivially generalizes to 64 bit limbs for the PC620. + */ + + .toc + .csect .mpihelp_submul_1[PR] + .align 2 + .globl mpihelp_submul_1 + .globl .mpihelp_submul_1 + .csect mpihelp_submul_1[DS] +mpihelp_submul_1: + .long .mpihelp_submul_1[PR], TOC[tc0], 0 + .csect .mpihelp_submul_1[PR] +.mpihelp_submul_1: + mtctr 5 + + lwz 0,0(4) + mullw 7,0,6 + mulhwu 10,0,6 + lwz 9,0(3) + subfc 8,7,9 + addc 7,7,8 # invert cy (r7 is junk) + addi 3,3,-4 + bdz Lend + +Loop: lwzu 0,4(4) + stwu 8,4(3) + mullw 8,0,6 + adde 7,8,10 + mulhwu 10,0,6 + lwz 9,4(3) + addze 10,10 + subfc 8,7,9 + addc 7,7,8 # invert cy (r7 is junk) + bdnz Loop + +Lend: stw 8,4(3) + addze 3,10 + blr + +#else +/* Multiply a limb vector by a single limb, for PowerPC. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_submul_1 (mp_ptr res_ptr, mp_srcptr s1_ptr, + mp_size_t s1_size, mp_limb_t s2_limb) + Calculate res-s1*s2 and put result back in res; return carry. */ + +ENTRY(mpihelp_submul_1) + mtctr %r5 + + lwz %r0,0(%r4) + mullw %r7,%r0,%r6 + mulhwu %r10,%r0,%r6 + lwz %r9,0(%r3) + subf %r8,%r7,%r9 + addc %r7,%r7,%r8 # invert cy (r7 is junk) + addi %r3,%r3,-4 # adjust res_ptr + bdz 1f + +0: lwzu %r0,4(%r4) + stwu %r8,4(%r3) + mullw %r8,%r0,%r6 + adde %r7,%r8,%r10 + mulhwu %r10,%r0,%r6 + lwz %r9,4(%r3) + addze %r10,%r10 + subf %r8,%r7,%r9 + addc %r7,%r7,%r8 # invert cy (r7 is junk) + bdnz 0b + +1: stw %r8,4(%r3) + addze %r3,%r10 + blr +END(mpihelp_submul_1) +#endif diff --git a/mpi/powerpc32/mpih-rshift.S b/mpi/powerpc32/mpih-rshift.S new file mode 100644 index 000000000..e9704db93 --- /dev/null +++ b/mpi/powerpc32/mpih-rshift.S @@ -0,0 +1,131 @@ +/* PowerPC-32 rshift + * + * Copyright (C) 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_rshift( mpi_ptr_t wp, (r3) + * mpi_ptr_t up, (r4) + * mpi_size_t usize, (r5) + * unsigned cnt) (r6) + */ + + .toc +.csect .text[PR] + .align 2 + .globl mpihelp_rshift + .globl .mpihelp_rshift + .csect mpihelp_rshift[DS] +mpihelp_rshift: + .long .mpihelp_rshift, TOC[tc0], 0 + .csect .text[PR] +.mpihelp_rshift: + mtctr 5 # copy size into CTR + addi 7,3,-4 # move adjusted res_ptr to free return reg + subfic 8,6,32 + lwz 11,0(4) # load first s1 limb + slw 3,11,8 # compute function return value + bdz Lend1 + +Loop: lwzu 10,4(4) + srw 9,11,6 + slw 12,10,8 + or 9,9,12 + stwu 9,4(7) + bdz Lend2 + lwzu 11,4(4) + srw 9,10,6 + slw 12,11,8 + or 9,9,12 + stwu 9,4(7) + bdnz Loop + +Lend1: srw 0,11,6 + stw 0,4(7) + blr + +Lend2: srw 0,10,6 + stw 0,4(7) + blr + +#else +/* Shift a limb right, low level routine. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +/* INPUT PARAMETERS + res_ptr r3 + s1_ptr r4 + size r5 + cnt r6 */ + +ENTRY(mpihelp_rshift) + mtctr 5 # copy size into CTR + addi 7,3,-4 # move adjusted res_ptr to free return reg + subfic 8,6,32 + lwz 11,0(4) # load first s1 limb + slw 3,11,8 # compute function return value + bdz 1f + +0: lwzu 10,4(4) + srw 9,11,6 + slw 12,10,8 + or 9,9,12 + stwu 9,4(7) + bdz 2f + lwzu 11,4(4) + srw 9,10,6 + slw 12,11,8 + or 9,9,12 + stwu 9,4(7) + bdnz 0b + +1: srw 0,11,6 + stw 0,4(7) + blr + +2: srw 0,10,6 + stw 0,4(7) + blr +END(mpihelp_rshift) +#endif diff --git a/mpi/powerpc32/mpih-sub1.S b/mpi/powerpc32/mpih-sub1.S new file mode 100644 index 000000000..8c67d988f --- /dev/null +++ b/mpi/powerpc32/mpih-sub1.S @@ -0,0 +1,132 @@ +/* PowerPC-32 sub_n -- Subtract two limb vectors of the same length > 0 + * and store difference in a third limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "sysdep.h" +#include "asm-syntax.h" + + +#ifndef USE_PPC_PATCHES + +/******************* + * mpi_limb_t + * mpihelp_sub_n( mpi_ptr_t res_ptr, (r3) + * mpi_ptr_t s1_ptr, (r4) + * mpi_ptr_t s2_ptr, (r5) + * mpi_size_t size) (r6) + */ + + .toc + .extern mpihelp_sub_n[DS] + .extern .mpihelp_sub_n +.csect [PR] + .align 2 + .globl mpihelp_sub_n + .globl .mpihelp_sub_n + .csect mpihelp_sub_n[DS] +mpihelp_sub_n: + .long .mpihelp_sub_n, TOC[tc0], 0 + .csect [PR] +.mpihelp_sub_n: + mtctr 6 # copy size into CTR + lwz 8,0(4) # load least significant s1 limb + lwz 0,0(5) # load least significant s2 limb + addi 3,3,-4 # offset res_ptr, it is updated before used + subfc 7,0,8 # add least significant limbs, set cy + bdz Lend # If done, skip loop +Loop: lwzu 8,4(4) # load s1 limb and update s1_ptr + lwzu 0,4(5) # load s2 limb and update s2_ptr + stwu 7,4(3) # store previous limb in load latency slot + subfe 7,0,8 # add new limbs with cy, set cy + bdnz Loop # decrement CTR and loop back +Lend: stw 7,4(3) # store ultimate result limb + subfe 3,0,0 # load !cy into ... + subfic 3,3,0 # ... return value register + blr + +#else +/* Subtract two limb vectors of equal, non-zero length for PowerPC. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* mp_limb_t mpn_sub_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr, + mp_size_t size) + Calculate s1-s2 and put result in res_ptr; return borrow, 0 or 1. */ + +/* Note on optimisation: This code is optimal for the 601. Almost every other + possible 2-unrolled inner loop will not be. Also, watch out for the + alignment... */ + +EALIGN(mpihelp_sub_n,3,1) +/* Set up for loop below. */ + mtcrf 0x01,%r6 + srwi. %r7,%r6,1 + mtctr %r7 + bt 31,2f + +/* Set the carry (clear the borrow). */ + subfc %r0,%r0,%r0 +/* Adjust pointers for loop. */ + addi %r3,%r3,-4 + addi %r4,%r4,-4 + addi %r5,%r5,-4 + b 0f + +2: lwz %r7,0(%r5) + lwz %r6,0(%r4) + subfc %r6,%r7,%r6 + stw %r6,0(%r3) + beq 1f + +/* Align start of loop to an odd word boundary to guarantee that the + last two words can be fetched in one access (for 601). This turns + out to be important. */ +0: + lwz %r9,4(%r4) + lwz %r8,4(%r5) + lwzu %r6,8(%r4) + lwzu %r7,8(%r5) + subfe %r8,%r8,%r9 + stw %r8,4(%r3) + subfe %r6,%r7,%r6 + stwu %r6,8(%r3) + bdnz 0b +/* Return the borrow. */ +1: subfe %r3,%r3,%r3 + neg %r3,%r3 + blr +END(mpihelp_sub_n) +#endif diff --git a/mpi/powerpc32/syntax.h b/mpi/powerpc32/syntax.h new file mode 100644 index 000000000..19f797273 --- /dev/null +++ b/mpi/powerpc32/syntax.h @@ -0,0 +1,75 @@ +/* gmp2-2.0.2-ppc/mpn/powerpc-linux/syntax.h Tue Oct 6 19:27:01 1998 */ +/* From glibc's sysdeps/unix/sysv/linux/powerpc/sysdep.h */ + +/* Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define USE_PPC_PATCHES 1 + +/* This seems to always be the case on PPC. */ +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name +#define ASM_GLOBAL_DIRECTIVE .globl + +#ifdef __STDC__ +# define C_LABEL(name) C_SYMBOL_NAME(name)##: +#else +# define C_LABEL(name) C_SYMBOL_NAME(name)/**/: +#endif + +#ifdef __STDC__ +# define L(body) .L##body +#else +# define L(body) .L/**/body +#endif + +/* No profiling of gmp's assembly for now... */ +#define CALL_MCOUNT /* no profiling */ + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define EALIGN_W_0 /* No words to insert. */ +#define EALIGN_W_1 nop +#define EALIGN_W_2 nop;nop +#define EALIGN_W_3 nop;nop;nop +#define EALIGN_W_4 EALIGN_W_3;nop +#define EALIGN_W_5 EALIGN_W_4;nop +#define EALIGN_W_6 EALIGN_W_5;nop +#define EALIGN_W_7 EALIGN_W_6;nop + +/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^align boundary. */ +#define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + C_LABEL(name) + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) + diff --git a/mpi/powerpc64/distfiles b/mpi/powerpc64/distfiles new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/mpi/powerpc64/distfiles diff --git a/mpi/sparc32/distfiles b/mpi/sparc32/distfiles new file mode 100644 index 000000000..95ff42882 --- /dev/null +++ b/mpi/sparc32/distfiles @@ -0,0 +1,6 @@ + +mpih-lshift.S +mpih-rshift.S +mpih-add1.S +udiv.S + diff --git a/mpi/sparc32/mpih-add1.S b/mpi/sparc32/mpih-add1.S new file mode 100644 index 000000000..b8faadb5f --- /dev/null +++ b/mpi/sparc32/mpih-add1.S @@ -0,0 +1,239 @@ +/* SPARC _add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright (C) 1995, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + + +/******************* + * mpi_limb_t + * mpihelp_add_n( mpi_ptr_t res_ptr, + * mpi_ptr_t s1_ptr, + * mpi_ptr_t s2_ptr, + * mpi_size_t size) + */ + +! INPUT PARAMETERS +#define res_ptr %o0 +#define s1_ptr %o1 +#define s2_ptr %o2 +#define size %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(mpihelp_add_n) +C_SYMBOL_NAME(mpihelp_add_n): + xor s2_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L1 ! branch if alignment differs + nop +! ** V1a ** +L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0 + be L_v1 ! if no, branch + nop +/* Add least significant limb separately to align res_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr +L_v1: addx %g0,%g0,%o4 ! save cy in register + cmp size,2 ! if size < 2 ... + bl Lend2 ! ... branch to tail code + subcc %g0,%o4,%g0 ! restore cy + + ld [s1_ptr+0],%g4 + addcc size,-10,size + ld [s1_ptr+4],%g1 + ldd [s2_ptr+0],%g2 + blt Lfin1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addxcc %g4,%g2,%o4 + ld [s1_ptr+16],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+20],%g1 + ldd [s2_ptr+16],%g2 + std %o4,[res_ptr+8] + addxcc %g4,%g2,%o4 + ld [s1_ptr+24],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+28],%g1 + ldd [s2_ptr+24],%g2 + std %o4,[res_ptr+16] + addxcc %g4,%g2,%o4 + ld [s1_ptr+32],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+36],%g1 + ldd [s2_ptr+32],%g2 + std %o4,[res_ptr+24] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop1 + subcc %g0,%o4,%g0 ! restore cy + +Lfin1: addcc size,8-2,size + blt Lend1 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 2 limbs until less than 2 limbs remain */ +Loope1: addxcc %g4,%g2,%o4 + ld [s1_ptr+8],%g4 + addxcc %g1,%g3,%o5 + ld [s1_ptr+12],%g1 + ldd [s2_ptr+8],%g2 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope1 + subcc %g0,%o4,%g0 ! restore cy +Lend1: addxcc %g4,%g2,%o4 + addxcc %g1,%g3,%o5 + std %o4,[res_ptr+0] + addx %g0,%g0,%o4 ! save cy in register + + andcc size,1,%g0 + be Lret1 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ + ld [s1_ptr+8],%g4 + ld [s2_ptr+8],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr+8] + +Lret1: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + +L1: xor s1_ptr,res_ptr,%g1 + andcc %g1,4,%g0 + bne L2 + nop +! ** V1b ** + mov s2_ptr,%g1 + mov s1_ptr,s2_ptr + b L0 + mov %g1,s1_ptr + +! ** V2 ** +/* If we come here, the alignment of s1_ptr and res_ptr as well as the + alignment of s2_ptr and res_ptr differ. Since there are only two ways + things can be aligned (that we care about) we now know that the alignment + of s1_ptr and s2_ptr are the same. */ + +L2: cmp size,1 + be Ljone + nop + andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0 + be L_v2 ! if no, branch + nop +/* Add least significant limb separately to align s1_ptr and s2_ptr */ + ld [s1_ptr],%g4 + add s1_ptr,4,s1_ptr + ld [s2_ptr],%g2 + add s2_ptr,4,s2_ptr + add size,-1,size + addcc %g4,%g2,%o4 + st %o4,[res_ptr] + add res_ptr,4,res_ptr + +L_v2: addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + blt Lfin2 + subcc %g0,%o4,%g0 ! restore cy +/* Add blocks of 8 limbs until less than 8 limbs remain */ +Loop2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + ldd [s1_ptr+8],%g2 + ldd [s2_ptr+8],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+8] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+12] + ldd [s1_ptr+16],%g2 + ldd [s2_ptr+16],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+16] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+20] + ldd [s1_ptr+24],%g2 + ldd [s2_ptr+24],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+24] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+28] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-8,size + add s1_ptr,32,s1_ptr + add s2_ptr,32,s2_ptr + add res_ptr,32,res_ptr + bge Loop2 + subcc %g0,%o4,%g0 ! restore cy + +Lfin2: addcc size,8-2,size + blt Lend2 + subcc %g0,%o4,%g0 ! restore cy +Loope2: ldd [s1_ptr+0],%g2 + ldd [s2_ptr+0],%o4 + addxcc %g2,%o4,%g2 + st %g2,[res_ptr+0] + addxcc %g3,%o5,%g3 + st %g3,[res_ptr+4] + addx %g0,%g0,%o4 ! save cy in register + addcc size,-2,size + add s1_ptr,8,s1_ptr + add s2_ptr,8,s2_ptr + add res_ptr,8,res_ptr + bge Loope2 + subcc %g0,%o4,%g0 ! restore cy +Lend2: andcc size,1,%g0 + be Lret2 + subcc %g0,%o4,%g0 ! restore cy +/* Add last limb */ +Ljone: ld [s1_ptr],%g4 + ld [s2_ptr],%g2 + addxcc %g4,%g2,%o4 + st %o4,[res_ptr] + +Lret2: retl + addx %g0,%g0,%o0 ! return carry-out from most sign. limb + + + diff --git a/mpi/sparc32/mpih-lshift.S b/mpi/sparc32/mpih-lshift.S new file mode 100644 index 000000000..b217d5e62 --- /dev/null +++ b/mpi/sparc32/mpih-lshift.S @@ -0,0 +1,97 @@ +/* sparc lshift + * + * Copyright (C) 1995, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +! INPUT PARAMETERS +! res_ptr %o0 +! src_ptr %o1 +! size %o2 +! cnt %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(mpihelp_lshift) +C_SYMBOL_NAME(mpihelp_lshift): + sll %o2,2,%g1 + add %o1,%g1,%o1 ! make %o1 point at end of src + ld [%o1-4],%g2 ! load first limb + sub %g0,%o3,%o5 ! negate shift count + add %o0,%g1,%o0 ! make %o0 point at end of res + add %o2,-1,%o2 + andcc %o2,4-1,%g4 ! number of limbs in first loop + srl %g2,%o5,%g1 ! compute function result + be L0 ! if multiple of 4 limbs, skip first loop + st %g1,[%sp+80] + + sub %o2,%g4,%o2 ! adjust count for main loop + +Loop0: ld [%o1-8],%g3 + add %o0,-4,%o0 + add %o1,-4,%o1 + addcc %g4,-1,%g4 + sll %g2,%o3,%o4 + srl %g3,%o5,%g1 + mov %g3,%g2 + or %o4,%g1,%o4 + bne Loop0 + st %o4,[%o0+0] + +L0: tst %o2 + be Lend + nop + +Loop: ld [%o1-8],%g3 + add %o0,-16,%o0 + addcc %o2,-4,%o2 + sll %g2,%o3,%o4 + srl %g3,%o5,%g1 + + ld [%o1-12],%g2 + sll %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0+12] + srl %g2,%o5,%g1 + + ld [%o1-16],%g3 + sll %g2,%o3,%o4 + or %g4,%g1,%g4 + st %g4,[%o0+8] + srl %g3,%o5,%g1 + + ld [%o1-20],%g2 + sll %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0+4] + srl %g2,%o5,%g1 + + add %o1,-16,%o1 + or %g4,%g1,%g4 + bne Loop + st %g4,[%o0+0] + +Lend: sll %g2,%o3,%g2 + st %g2,[%o0-4] + retl + ld [%sp+80],%o0 + diff --git a/mpi/sparc32/mpih-rshift.S b/mpi/sparc32/mpih-rshift.S new file mode 100644 index 000000000..62902cbe3 --- /dev/null +++ b/mpi/sparc32/mpih-rshift.S @@ -0,0 +1,93 @@ +/* sparc rshift + * + * Copyright (C) 1995, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +! INPUT PARAMETERS +! res_ptr %o0 +! src_ptr %o1 +! size %o2 +! cnt %o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(mpihelp_rshift) +C_SYMBOL_NAME(mpihelp_rshift): + ld [%o1],%g2 ! load first limb + sub %g0,%o3,%o5 ! negate shift count + add %o2,-1,%o2 + andcc %o2,4-1,%g4 ! number of limbs in first loop + sll %g2,%o5,%g1 ! compute function result + be L0 ! if multiple of 4 limbs, skip first loop + st %g1,[%sp+80] + + sub %o2,%g4,%o2 ! adjust count for main loop + +Loop0: ld [%o1+4],%g3 + add %o0,4,%o0 + add %o1,4,%o1 + addcc %g4,-1,%g4 + srl %g2,%o3,%o4 + sll %g3,%o5,%g1 + mov %g3,%g2 + or %o4,%g1,%o4 + bne Loop0 + st %o4,[%o0-4] + +L0: tst %o2 + be Lend + nop + +Loop: ld [%o1+4],%g3 + add %o0,16,%o0 + addcc %o2,-4,%o2 + srl %g2,%o3,%o4 + sll %g3,%o5,%g1 + + ld [%o1+8],%g2 + srl %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0-16] + sll %g2,%o5,%g1 + + ld [%o1+12],%g3 + srl %g2,%o3,%o4 + or %g4,%g1,%g4 + st %g4,[%o0-12] + sll %g3,%o5,%g1 + + ld [%o1+16],%g2 + srl %g3,%o3,%g4 + or %o4,%g1,%o4 + st %o4,[%o0-8] + sll %g2,%o5,%g1 + + add %o1,16,%o1 + or %g4,%g1,%g4 + bne Loop + st %g4,[%o0-4] + +Lend: srl %g2,%o3,%g2 + st %g2,[%o0-0] + retl + ld [%sp+80],%o0 + diff --git a/mpi/sparc32/udiv.S b/mpi/sparc32/udiv.S new file mode 100644 index 000000000..752d07193 --- /dev/null +++ b/mpi/sparc32/udiv.S @@ -0,0 +1,197 @@ +/* SPARC v7 __udiv_qrnnd division support, used from longlong.h. + * This is for v7 CPUs without a floating-point unit. + * + * Copyright (C) 1993, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +! INPUT PARAMETERS +! rem_ptr o0 +! n1 o1 +! n0 o2 +! d o3 + +#include "sysdep.h" + + .text + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + tst %o3 + bneg Largedivisor + mov 8,%g1 + + b Lp1 + addxcc %o2,%o2,%o2 + +Lplop: bcc Ln1 + addxcc %o2,%o2,%o2 +Lp1: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln2 + addxcc %o2,%o2,%o2 +Lp2: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln3 + addxcc %o2,%o2,%o2 +Lp3: addx %o1,%o1,%o1 + subcc %o1,%o3,%o4 + bcc Ln4 + addxcc %o2,%o2,%o2 +Lp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne Lplop + subcc %o1,%o3,%o4 + bcc Ln5 + addxcc %o2,%o2,%o2 +Lp5: st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +Lnlop: bcc Lp1 + addxcc %o2,%o2,%o2 +Ln1: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp2 + addxcc %o2,%o2,%o2 +Ln2: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp3 + addxcc %o2,%o2,%o2 +Ln3: addx %o4,%o4,%o4 + subcc %o4,%o3,%o1 + bcc Lp4 + addxcc %o2,%o2,%o2 +Ln4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne Lnlop + subcc %o4,%o3,%o1 + bcc Lp5 + addxcc %o2,%o2,%o2 +Ln5: st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Largedivisor: + and %o2,1,%o5 ! %o5 = n0 & 1 + + srl %o2,1,%o2 + sll %o1,31,%g2 + or %g2,%o2,%o2 ! %o2 = lo(n1n0 >> 1) + srl %o1,1,%o1 ! %o1 = hi(n1n0 >> 1) + + and %o3,1,%g2 + srl %o3,1,%g3 ! %g3 = floor(d / 2) + add %g3,%g2,%g3 ! %g3 = ceil(d / 2) + + b LLp1 + addxcc %o2,%o2,%o2 + +LLplop: bcc LLn1 + addxcc %o2,%o2,%o2 +LLp1: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn2 + addxcc %o2,%o2,%o2 +LLp2: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn3 + addxcc %o2,%o2,%o2 +LLp3: addx %o1,%o1,%o1 + subcc %o1,%g3,%o4 + bcc LLn4 + addxcc %o2,%o2,%o2 +LLp4: addx %o1,%o1,%o1 + addcc %g1,-1,%g1 + bne LLplop + subcc %o1,%g3,%o4 + bcc LLn5 + addxcc %o2,%o2,%o2 +LLp5: add %o1,%o1,%o1 ! << 1 + tst %g2 + bne Oddp + add %o5,%o1,%o1 + st %o1,[%o0] + retl + xnor %g0,%o2,%o0 + +LLnlop: bcc LLp1 + addxcc %o2,%o2,%o2 +LLn1: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp2 + addxcc %o2,%o2,%o2 +LLn2: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp3 + addxcc %o2,%o2,%o2 +LLn3: addx %o4,%o4,%o4 + subcc %o4,%g3,%o1 + bcc LLp4 + addxcc %o2,%o2,%o2 +LLn4: addx %o4,%o4,%o4 + addcc %g1,-1,%g1 + bne LLnlop + subcc %o4,%g3,%o1 + bcc LLp5 + addxcc %o2,%o2,%o2 +LLn5: add %o4,%o4,%o4 ! << 1 + tst %g2 + bne Oddn + add %o5,%o4,%o4 + st %o4,[%o0] + retl + xnor %g0,%o2,%o0 + +Oddp: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o1 + addcc %o1,%o2,%o1 + bcc LLp6 + addx %o2,0,%o2 + sub %o1,%o3,%o1 +LLp6: subcc %o1,%o3,%g0 + bcs LLp7 + subx %o2,-1,%o2 + sub %o1,%o3,%o1 +LLp7: st %o1,[%o0] + retl + mov %o2,%o0 + +Oddn: xnor %g0,%o2,%o2 + ! q' in %o2. r' in %o4 + addcc %o4,%o2,%o4 + bcc LLn6 + addx %o2,0,%o2 + sub %o4,%o3,%o4 +LLn6: subcc %o4,%o3,%g0 + bcs LLn7 + subx %o2,-1,%o2 + sub %o4,%o3,%o4 +LLn7: st %o4,[%o0] + retl + mov %o2,%o0 diff --git a/mpi/sparc32v8/distfiles b/mpi/sparc32v8/distfiles new file mode 100644 index 000000000..5789f35b3 --- /dev/null +++ b/mpi/sparc32v8/distfiles @@ -0,0 +1,5 @@ + +mpih-mul1.S +mpih-mul2.S +mpih-mul3.S + diff --git a/mpi/sparc32v8/mpih-mul1.S b/mpi/sparc32v8/mpih-mul1.S new file mode 100644 index 000000000..551450060 --- /dev/null +++ b/mpi/sparc32v8/mpih-mul1.S @@ -0,0 +1,111 @@ +/* SPARC v8 __mpn_mul_1 -- Multiply a limb vector with a single limb and + * store the product in a second limb vector. + * + * Copyright (C) 1992, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 8 + .global C_SYMBOL_NAME(mpihelp_mul_1) +C_SYMBOL_NAME(mpihelp_mul_1): + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + ld [%o1+0],%o4 ! 1 +LL: +LL00: add %o0,-4,%o0 + add %o1,-4,%o1 + b Loop00 /* 4, 8, 12, ... */ + orcc %g0,%g0,%g2 +LL01: b Loop01 /* 1, 5, 9, ... */ + orcc %g0,%g0,%g2 + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + add %o1,4,%o1 + b Loop10 + orcc %g0,%g0,%g2 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + add %o1,-8,%o1 + b Loop11 + orcc %g0,%g0,%g2 + +Loop: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + st %g3,[%o0+0] ! 1 + rd %y,%g2 ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + st %g3,[%o0+4] ! 2 + rd %y,%g2 ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + add %o1,16,%o1 + st %g3,[%o0+8] ! 3 + rd %y,%g2 ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg Loop + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + st %g3,[%o0+0] ! 4 + rd %y,%g2 ! 4 + + retl + addx %g0,%g2,%o0 + + diff --git a/mpi/sparc32v8/mpih-mul2.S b/mpi/sparc32v8/mpih-mul2.S new file mode 100644 index 000000000..55f37814b --- /dev/null +++ b/mpi/sparc32v8/mpih-mul2.S @@ -0,0 +1,134 @@ +/* SPARC v8 __mpn_addmul_1 -- Multiply a limb vector with a limb and + * add the result to a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1995, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(mpihelp_addmul_1) +C_SYMBOL_NAME(mpihelp_addmul_1): + orcc %g0,%g0,%g2 + ld [%o1+0],%o4 ! 1 + + sll %o2,4,%g1 + and %g1,(4-1)<<4,%g1 +#if PIC + mov %o7,%g4 ! Save return address register + call 1f + add %o7,LL-1f,%g3 +1: mov %g4,%o7 ! Restore return address register +#else + sethi %hi(LL),%g3 + or %g3,%lo(LL),%g3 +#endif + jmp %g3+%g1 + nop +LL: +LL00: add %o0,-4,%o0 + b Loop00 /* 4, 8, 12, ... */ + add %o1,-4,%o1 + nop +LL01: b Loop01 /* 1, 5, 9, ... */ + nop + nop + nop +LL10: add %o0,-12,%o0 /* 2, 6, 10, ... */ + b Loop10 + add %o1,4,%o1 + nop +LL11: add %o0,-8,%o0 /* 3, 7, 11, ... */ + b Loop11 + add %o1,-8,%o1 + nop + +1: addcc %g3,%g2,%g3 ! 1 + ld [%o1+4],%o4 ! 2 + rd %y,%g2 ! 1 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 1 +Loop00: umul %o4,%o3,%g3 ! 2 + ld [%o0+4],%g1 ! 2 + addxcc %g3,%g2,%g3 ! 2 + ld [%o1+8],%o4 ! 3 + rd %y,%g2 ! 2 + addx %g0,%g2,%g2 + nop + addcc %g1,%g3,%g3 + st %g3,[%o0+4] ! 2 +Loop11: umul %o4,%o3,%g3 ! 3 + addxcc %g3,%g2,%g3 ! 3 + ld [%o1+12],%o4 ! 4 + rd %y,%g2 ! 3 + add %o1,16,%o1 + addx %g0,%g2,%g2 + ld [%o0+8],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+8] ! 3 +Loop10: umul %o4,%o3,%g3 ! 4 + addxcc %g3,%g2,%g3 ! 4 + ld [%o1+0],%o4 ! 1 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+12],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+12] ! 4 + add %o0,16,%o0 + addx %g0,%g2,%g2 +Loop01: addcc %o2,-4,%o2 + bg 1b + umul %o4,%o3,%g3 ! 1 + + addcc %g3,%g2,%g3 ! 4 + rd %y,%g2 ! 4 + addx %g0,%g2,%g2 + ld [%o0+0],%g1 ! 2 + addcc %g1,%g3,%g3 + st %g3,[%o0+0] ! 4 + addx %g0,%g2,%o0 + + retl + nop + + +! umul, ld, addxcc, rd, st + +! umul, ld, addxcc, rd, ld, addcc, st, addx + diff --git a/mpi/sparc32v8/mpih-mul3.S b/mpi/sparc32v8/mpih-mul3.S new file mode 100644 index 000000000..cfd0a1576 --- /dev/null +++ b/mpi/sparc32v8/mpih-mul3.S @@ -0,0 +1,69 @@ +/* SPARC v8 __mpn_submul_1 -- Multiply a limb vector with a limb and + * subtract the result from a second limb vector. + * + * Copyright (C) 1992, 1993, 1994, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + +! INPUT PARAMETERS +! res_ptr o0 +! s1_ptr o1 +! size o2 +! s2_limb o3 + +#include "sysdep.h" + +.text + .align 4 + .global C_SYMBOL_NAME(mpihelp_submul_1) +C_SYMBOL_NAME(mpihelp_submul_1): + sub %g0,%o2,%o2 ! negate ... + sll %o2,2,%o2 ! ... and scale size + sub %o1,%o2,%o1 ! o1 is offset s1_ptr + sub %o0,%o2,%g1 ! g1 is offset res_ptr + + mov 0,%o0 ! clear cy_limb + +Loop: ld [%o1+%o2],%o4 + ld [%g1+%o2],%g2 + umul %o4,%o3,%o5 + rd %y,%g3 + addcc %o5,%o0,%o5 + addx %g3,0,%o0 + subcc %g2,%o5,%g2 + addx %o0,0,%o0 + st %g2,[%g1+%o2] + + addcc %o2,4,%o2 + bne Loop + nop + + retl + nop + + diff --git a/mpi/supersparc/distfiles b/mpi/supersparc/distfiles new file mode 100644 index 000000000..5506c419b --- /dev/null +++ b/mpi/supersparc/distfiles @@ -0,0 +1,3 @@ + +udiv.S + diff --git a/mpi/supersparc/udiv.S b/mpi/supersparc/udiv.S new file mode 100644 index 000000000..31b7387c7 --- /dev/null +++ b/mpi/supersparc/udiv.S @@ -0,0 +1,120 @@ +/* SuperSPARC __udiv_qrnnd division support, used from longlong.h. + * This is for SuperSPARC only, to compensate for its + * semi-functional udiv instruction. + * + * Copyright (C) 1993, 1994, 1996, 1998, + * 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Note: This code is heavily based on the GNU MP Library. + * Actually it's the same code with only minor changes in the + * way the data is stored; this is to support the abstraction + * of an optional secure memory allocation which may be used + * to avoid revealing of sensitive data due to paging etc. + * The GNU MP Library itself is published under the LGPL; + * however I decided to publish this code under the plain GPL. + */ + + + +! INPUT PARAMETERS +! rem_ptr i0 +! n1 i1 +! n0 i2 +! d i3 + +#include "sysdep.h" +#undef ret /* Kludge for glibc */ + + .text + .align 8 +LC0: .double 0r4294967296 +LC1: .double 0r2147483648 + + .align 4 + .global C_SYMBOL_NAME(__udiv_qrnnd) +C_SYMBOL_NAME(__udiv_qrnnd): + !#PROLOGUE# 0 + save %sp,-104,%sp + !#PROLOGUE# 1 + st %i1,[%fp-8] + ld [%fp-8],%f10 + sethi %hi(LC0),%o7 + fitod %f10,%f4 + ldd [%o7+%lo(LC0)],%f8 + cmp %i1,0 + bge L248 + mov %i0,%i5 + faddd %f4,%f8,%f4 +L248: + st %i2,[%fp-8] + ld [%fp-8],%f10 + fmuld %f4,%f8,%f6 + cmp %i2,0 + bge L249 + fitod %f10,%f2 + faddd %f2,%f8,%f2 +L249: + st %i3,[%fp-8] + faddd %f6,%f2,%f2 + ld [%fp-8],%f10 + cmp %i3,0 + bge L250 + fitod %f10,%f4 + faddd %f4,%f8,%f4 +L250: + fdivd %f2,%f4,%f2 + sethi %hi(LC1),%o7 + ldd [%o7+%lo(LC1)],%f4 + fcmped %f2,%f4 + nop + fbge,a L251 + fsubd %f2,%f4,%f2 + fdtoi %f2,%f2 + st %f2,[%fp-8] + b L252 + ld [%fp-8],%i4 +L251: + fdtoi %f2,%f2 + st %f2,[%fp-8] + ld [%fp-8],%i4 + sethi %hi(-2147483648),%g2 + xor %i4,%g2,%i4 +L252: + umul %i3,%i4,%g3 + rd %y,%i0 + subcc %i2,%g3,%o7 + subxcc %i1,%i0,%g0 + be L253 + cmp %o7,%i3 + + add %i4,-1,%i0 + add %o7,%i3,%o7 + st %o7,[%i5] + ret + restore +L253: + blu L246 + mov %i4,%i0 + add %i4,1,%i0 + sub %o7,%i3,%o7 +L246: + st %o7,[%i5] + ret + restore + |