summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL207
-rw-r--r--README18
-rw-r--r--cipher/Makefile.am1
-rw-r--r--cipher/Makefile.in1
-rw-r--r--cipher/md.c197
-rw-r--r--cipher/md.h60
-rw-r--r--cipher/md5.c123
-rw-r--r--cipher/md5.h17
-rw-r--r--cipher/random.c15
-rw-r--r--cipher/rmd.h27
-rw-r--r--cipher/rmd160.c129
-rw-r--r--cipher/sha1.c122
-rw-r--r--cipher/sha1.h26
-rw-r--r--mpi/config.links18
-rw-r--r--mpi/sparc32/distfiles4
-rw-r--r--mpi/sparc32/mpih-add1.S237
-rw-r--r--mpi/sparc32/udiv.S188
-rw-r--r--mpi/sparc32v8/distfiles5
-rw-r--r--mpi/sparc32v8/mpih-mul1.S101
-rw-r--r--mpi/sparc32v8/mpih-mul2.S124
-rw-r--r--mpi/sparc32v8/mpih-mul3.S60
-rw-r--r--mpi/supersparc/distfiles3
-rw-r--r--mpi/supersparc/udiv.S110
23 files changed, 1316 insertions, 477 deletions
diff --git a/INSTALL b/INSTALL
index bf72ad4d..c5242221 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,26 +1,183 @@
-
- 1) Configure for your machine:
-
- ./configure
-
- or use
-
- ./configure --enable-m-debug
-
- to enable the integrated malloc debugging stuff.
-
-
- 2) Run make:
-
- make
-
-
- 3) Install
-
- make install
-
-
- 4) You end up with a binary "g10" in /usr/local/bin
-
-
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+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' that
+supports the `VPATH' variable, such as GNU `make'. `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 `..'.
+
+ 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
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/README b/README
index 18301898..55be1b29 100644
--- a/README
+++ b/README
@@ -42,6 +42,24 @@
+ Installation
+ ------------
+
+ 1) "./configure"
+
+ to enable the integrated malloc debugging stuff, use:
+
+ "./configure --enable-m-debug"
+
+ 2) "make"
+
+ 3) "make install"
+
+ 4) You end up with a binary "g10" in /usr/local/bin
+
+
+
+
Resources
---------
G10 needs a directory "~/.g10" to store the default keyrings
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 0855d7da..ecd91a73 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
@@ -23,6 +23,7 @@ cipher_SOURCES = blowfish.c \
dsa.h \
dsa.c \
md.c \
+ md.h \
misc.c \
smallprime.c
diff --git a/cipher/Makefile.in b/cipher/Makefile.in
index 7bd7691f..221efdd2 100644
--- a/cipher/Makefile.in
+++ b/cipher/Makefile.in
@@ -60,6 +60,7 @@ cipher_SOURCES = blowfish.c \
dsa.h \
dsa.c \
md.c \
+ md.h \
misc.c \
smallprime.c
diff --git a/cipher/md.c b/cipher/md.c
index 67f5356a..e88a45c7 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -27,146 +27,135 @@
#include "errors.h"
-int
-md_okay( int algo )
-{
- return check_digest_algo( algo );
-}
-
-
-MD_HANDLE *
+/****************
+ * Open a message digest handle for use with algorithm ALGO.
+ * More algorithms may be added by md_enable(). The initial algorithm
+ * may be 0.
+ */
+MD_HANDLE
md_open( int algo, int secure )
{
- MD_HANDLE *hd;
-
- hd = m_alloc( sizeof *hd + 19 );
- hd->algo = algo;
- hd->datalen = 0;
- if( algo == DIGEST_ALGO_MD5 )
- hd->u.md5 = md5_open( secure );
- else if( algo == DIGEST_ALGO_RMD160 )
- hd->u.rmd= rmd160_open( secure );
- else if( algo == DIGEST_ALGO_SHA1 )
- hd->u.sha1 = sha1_open( secure );
- else
- return NULL;
+ MD_HANDLE hd;
+ hd = secure ? m_alloc_secure_clear( sizeof *hd )
+ : m_alloc_clear( sizeof *hd );
+ if( algo )
+ md_enable( hd, algo );
return hd;
}
-
-MD_HANDLE *
-md_copy( MD_HANDLE *a )
+void
+md_enable( MD_HANDLE h, int algo )
{
- MD_HANDLE *hd;
-
- hd = m_alloc( sizeof *hd + 19 );
- hd->algo = a->algo;
- hd->datalen = 0;
- if( a->algo == DIGEST_ALGO_MD5 )
- hd->u.md5 = md5_copy( a->u.md5 );
- else if( a->algo == DIGEST_ALGO_RMD160 )
- hd->u.rmd= rmd160_copy( a->u.rmd );
- else if( a->algo == DIGEST_ALGO_SHA1 )
- hd->u.sha1= sha1_copy( a->u.sha1 );
+ if( algo == DIGEST_ALGO_MD5 ) {
+ md5_init( &h->md5 );
+ h->use_md5 = 1;
+ }
+ else if( algo == DIGEST_ALGO_RMD160 ) {
+ rmd160_init( &h->rmd160 );
+ h->use_rmd160 = 1;
+ }
+ else if( algo == DIGEST_ALGO_SHA1 ) {
+ sha1_init( &h->sha1 );
+ h->use_sha1 = 1;
+ }
else
- log_bug(NULL);
- return hd;
+ log_bug("md_enable(%d)", algo );
}
-/* used for a BAD Kludge in rmd160.c, md5.c */
-MD_HANDLE *
-md_makecontainer( int algo )
+MD_HANDLE
+md_copy( MD_HANDLE a )
{
- MD_HANDLE *hd;
-
- hd = m_alloc( sizeof *hd + 19 );
- hd->algo = algo;
- hd->datalen = 0;
- if( algo == DIGEST_ALGO_MD5 )
- ;
- else if( algo == DIGEST_ALGO_RMD160 )
- ;
- else if( algo == DIGEST_ALGO_SHA1 )
- ;
- else
- log_bug(NULL);
- return hd;
+ MD_HANDLE b;
+
+ b = m_is_secure(a)? m_alloc_secure( sizeof *b )
+ : m_alloc( sizeof *b );
+ memcpy( b, a, sizeof *a );
+ return b;
}
+
void
-md_close(MD_HANDLE *a)
+md_close(MD_HANDLE a)
{
if( !a )
return;
- if( a->algo == DIGEST_ALGO_MD5 )
- md5_close( a->u.md5 );
- else if( a->algo == DIGEST_ALGO_RMD160 )
- rmd160_close( a->u.rmd );
- else if( a->algo == DIGEST_ALGO_SHA1 )
- sha1_close( a->u.sha1 );
- else
- log_bug(NULL);
m_free(a);
}
void
-md_write( MD_HANDLE *a, byte *inbuf, size_t inlen)
+md_write( MD_HANDLE a, byte *inbuf, size_t inlen)
{
- if( a->algo == DIGEST_ALGO_MD5 )
- md5_write( a->u.md5, inbuf, inlen );
- else if( a->algo == DIGEST_ALGO_RMD160 )
- rmd160_write( a->u.rmd, inbuf, inlen );
- else if( a->algo == DIGEST_ALGO_SHA1 )
- sha1_write( a->u.sha1, inbuf, inlen );
- else
- log_bug(NULL);
+ if( a->use_rmd160 ) {
+ rmd160_write( &a->rmd160, a->buffer, a->bufcount );
+ rmd160_write( &a->rmd160, inbuf, inlen );
+ }
+ if( a->use_sha1 ) {
+ sha1_write( &a->sha1, a->buffer, a->bufcount );
+ sha1_write( &a->sha1, inbuf, inlen );
+ }
+ if( a->use_md5 ) {
+ md5_write( &a->md5, a->buffer, a->bufcount );
+ md5_write( &a->md5, inbuf, inlen );
+ }
+ a->bufcount = 0;
}
+
void
-md_putchar( MD_HANDLE *a, int c )
+md_final(MD_HANDLE a)
{
- if( a->algo == DIGEST_ALGO_MD5 )
- md5_putchar( a->u.md5, c );
- else if( a->algo == DIGEST_ALGO_RMD160 )
- rmd160_putchar( a->u.rmd, c );
- else if( a->algo == DIGEST_ALGO_SHA1 )
- sha1_putchar( a->u.sha1, c );
- else
- log_bug(NULL);
+ if( a->bufcount )
+ md_write( a, NULL, 0 );
+ if( a->use_rmd160 ) {
+ byte *p;
+ rmd160_final( &a->rmd160 );
+ p = rmd160_read( &a->rmd160 );
+ }
+ if( a->use_sha1 )
+ sha1_final( &a->sha1 );
+ if( a->use_md5 )
+ md5_final( &a->md5 );
}
+/****************
+ * if ALGO is null get the digest for the used algo (which should be only one)
+ */
byte *
-md_final(MD_HANDLE *a)
+md_read( MD_HANDLE a, int algo )
{
- if( a->algo == DIGEST_ALGO_MD5 ) {
- if( !a->datalen ) {
- md5_final( a->u.md5 );
- memcpy(a->data, md5_read( a->u.md5 ), 16);
- a->datalen = 16;
- }
- return a->data;
+ if( !algo ) {
+ if( a->use_rmd160 )
+ return rmd160_read( &a->rmd160 );
+ if( a->use_sha1 )
+ return sha1_read( &a->sha1 );
+ if( a->use_md5 )
+ return md5_read( &a->md5 );
}
- else if( a->algo == DIGEST_ALGO_RMD160 ) {
- if( !a->datalen ) {
- memcpy(a->data, rmd160_final( a->u.rmd ), 20 );
- a->datalen = 20;
- }
- return a->data;
+ else {
+ if( algo == DIGEST_ALGO_RMD160 )
+ return rmd160_read( &a->rmd160 );
+ if( algo == DIGEST_ALGO_SHA1 )
+ return sha1_read( &a->sha1 );
+ if( algo == DIGEST_ALGO_MD5 )
+ return md5_read( &a->md5 );
}
- else if( a->algo == DIGEST_ALGO_SHA1 ) {
- if( !a->datalen ) {
- memcpy(a->data, sha1_final( a->u.sha1 ), 20 );
- a->datalen = 20;
- }
- return a->data;
- }
- else
- log_bug(NULL);
+ log_bug(NULL);
}
+int
+md_get_algo( MD_HANDLE a )
+{
+ if( a->use_rmd160 )
+ return DIGEST_ALGO_RMD160;
+ if( a->use_sha1 )
+ return DIGEST_ALGO_SHA1;
+ if( a->use_md5 )
+ return DIGEST_ALGO_MD5;
+ return 0;
+}
diff --git a/cipher/md.h b/cipher/md.h
new file mode 100644
index 00000000..8a7886d0
--- /dev/null
+++ b/cipher/md.h
@@ -0,0 +1,60 @@
+/* md.h - digest functions
+ * Copyright (c) 1997 by Werner Koch (dd9jn)
+ *
+ * This file is part of G10.
+ *
+ * G10 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.
+ *
+ * G10 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 G10_MD_H
+#define G10_MD_H
+
+#include "types.h"
+#include "rmd.h"
+#include "sha1.h"
+#include "md5.h"
+
+#define MD_BUFFER_SIZE 512
+
+typedef struct {
+ int use_rmd160;
+ RMD160_CONTEXT rmd160;
+ int use_sha1;
+ SHA1_CONTEXT sha1;
+ int use_md5;
+ MD5_CONTEXT md5;
+ byte buffer[MD_BUFFER_SIZE]; /* primary buffer */
+ int bufcount;
+} *MD_HANDLE;
+
+
+#define md_putc(h,c) \
+ do { \
+ if( (h)->bufcount == MD_BUFFER_SIZE ) \
+ md_write( (h), NULL, 0 ); \
+ (h)->buffer[(h)->bufcount++] = (c) & 0xff; \
+ } while(0)
+
+/*-- md.c --*/
+MD_HANDLE md_open( int algo, int secure );
+void md_enable( MD_HANDLE hd, int algo );
+MD_HANDLE md_copy( MD_HANDLE a );
+void md_close(MD_HANDLE a);
+void md_write( MD_HANDLE a, byte *inbuf, size_t inlen);
+void md_final(MD_HANDLE a);
+byte *md_read( MD_HANDLE a, int algo );
+int md_get_algo( MD_HANDLE a );
+
+
+#endif /*G10_MD_H*/
diff --git a/cipher/md5.c b/cipher/md5.c
index be260269..6906503d 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -61,7 +61,6 @@
#include <assert.h>
#include "util.h"
#include "md5.h"
-#include "cipher.h" /* kludge for md5_copy2md() */
#include "memory.h"
@@ -74,7 +73,7 @@
#endif
-static void Init( MD5HANDLE mdContext);
+static void Init( MD5_CONTEXT *mdContext);
static void Transform(u32 *buf,u32 *in);
static byte PADDING[64] = {
@@ -120,56 +119,9 @@ static byte PADDING[64] = {
(a) += (b); \
}
-/* The routine Init initializes the message-digest context
- * mdContext. All fields are set to zero.
- * mode should be zero is reserved for extensions.
- */
-
-MD5HANDLE
-md5_open(int secure)
-{
- MD5HANDLE mdContext;
-
- mdContext = secure? m_alloc_secure( sizeof *mdContext )
- : m_alloc( sizeof *mdContext );
- Init(mdContext);
- return mdContext;
-}
-
-
-MD5HANDLE
-md5_copy( MD5HANDLE a )
-{
- MD5HANDLE mdContext;
-
- assert(a);
- mdContext = m_is_secure(a)? m_alloc_secure( sizeof *mdContext )
- : m_alloc( sizeof *mdContext );
- memcpy( mdContext, a, sizeof *a );
- return mdContext;
-}
-
-
-/* BAD Kludge!!! */
-MD_HANDLE *
-md5_copy2md( MD5HANDLE a )
-{
- MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_MD5 );
- md->u.md5 = md5_copy( a );
- return md;
-}
-
void
-md5_close(MD5HANDLE hd)
-{
- if( hd )
- m_free(hd);
-}
-
-
-static void
-Init( MD5HANDLE mdContext)
+md5_init( MD5_CONTEXT *mdContext)
{
mdContext->i[0] = mdContext->i[1] = (u32)0;
/* Load magic initialization constants.
@@ -178,7 +130,7 @@ Init( MD5HANDLE mdContext)
mdContext->buf[1] = (u32)0xefcdab89L;
mdContext->buf[2] = (u32)0x98badcfeL;
mdContext->buf[3] = (u32)0x10325476L;
- mdContext->bufcount = 0;
+ mdContext->count = 0;
}
/* The routine Update updates the message-digest context to
@@ -186,15 +138,15 @@ Init( MD5HANDLE mdContext)
* in the message whose digest is being computed.
*/
void
-md5_write( MD5HANDLE mdContext, byte *inBuf, size_t inLen)
+md5_write( MD5_CONTEXT *mdContext, byte *inBuf, size_t inLen)
{
register int i, ii;
int mdi;
u32 in[16];
- if(mdContext->bufcount) { /* flush the buffer */
- i = mdContext->bufcount;
- mdContext->bufcount = 0;
+ if(mdContext->count) { /* flush the buffer */
+ i = mdContext->count;
+ mdContext->count = 0;
md5_write( mdContext, mdContext->digest, i);
}
if( !inBuf )
@@ -227,20 +179,6 @@ md5_write( MD5HANDLE mdContext, byte *inBuf, size_t inLen)
}
-/****************
- * Process a single character, this character will be buffered to
- * increase performance. The digest-field is used as a buffer.
- */
-
-void
-md5_putchar( MD5HANDLE mdContext, int c )
-{
- if(mdContext->bufcount == 16)
- md5_write( mdContext, NULL, 0 );
- mdContext->digest[mdContext->bufcount++] = c & 0xff;
-}
-
-
/* The routine final terminates the message-digest computation and
* ends with the desired message digest in mdContext->digest[0...15].
@@ -249,14 +187,14 @@ md5_putchar( MD5HANDLE mdContext, int c )
*/
void
-md5_final(MD5HANDLE mdContext)
+md5_final( MD5_CONTEXT *mdContext )
{
u32 in[16];
int mdi;
unsigned int i, ii;
unsigned int padLen;
- if(mdContext->bufcount) /* flush buffer */
+ if(mdContext->count) /* flush buffer */
md5_write(mdContext, NULL, 0 );
/* save number of bits */
in[14] = mdContext->i[0];
@@ -284,49 +222,6 @@ md5_final(MD5HANDLE mdContext)
mdContext->digest[ii+2] = (byte)((mdContext->buf[i] >> 16) & 0xFF);
mdContext->digest[ii+3] = (byte)((mdContext->buf[i] >> 24) & 0xFF);
}
- Init(mdContext);
-}
-
-/**********
- * Returns 16 bytes representing the digest.
- */
-byte *
-md5_read(MD5HANDLE mdContext)
-{
- return mdContext->digest;
-}
-
-
-
-/****************
- * Converts the result form Read into a printable representation.
- * This should only be used direct after a md5_read(), because it uses
- * In-Place conversion.
- * Returns digest.
- */
-
-char *
-md5_tostring( byte *digest )
-{
- static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ."
- "abcdefghijklmnopqrstuvwxyz_"
- "0123456789";
- int i;
- byte *d, *s;
-
- memmove(digest+8,digest, 16); /* make some room */
- d = digest;
- s = digest+8;
- for(i=0; i < 5; i++, s += 3 ) {
- *d++ = bintoasc[(*s >> 2) & 077];
- *d++ = bintoasc[(((*s << 4) & 060) | ((s[1] >> 4) & 017)) & 077];
- *d++ = bintoasc[(((s[1] << 2) & 074) | ((s[2] >> 6) & 03)) & 077];
- *d++ = bintoasc[s[2] & 077];
- }
- *d++ = bintoasc[(*s >> 2) & 077];
- *d++ = bintoasc[((*s << 4) & 060) & 077];
- *d = 0;
- return (char*)digest;
}
diff --git a/cipher/md5.h b/cipher/md5.h
index fa401a16..c46075a3 100644
--- a/cipher/md5.h
+++ b/cipher/md5.h
@@ -25,20 +25,15 @@
typedef struct {
u32 i[2]; /* number of _bits_ handled mod 2^64 */
u32 buf[4]; /* scratch buffer */
+ int count;
byte in[64]; /* input buffer */
byte digest[16+8+1]; /* actual digest after Final call */
- byte bufcount; /* extra room for bintoascii */
-} *MD5HANDLE;
+} MD5_CONTEXT;
-/*-- md5.c --*/
-MD5HANDLE md5_open(int);
-MD5HANDLE md5_copy(MD5HANDLE a);
-void md5_write(MD5HANDLE hd, byte *inBuf, size_t inLen);
-void md5_putchar(MD5HANDLE hd, int c );
-void md5_final(MD5HANDLE hd);
-byte *md5_read(MD5HANDLE hd);
-char *md5_tostring( byte *digest );
-void md5_close(MD5HANDLE hd);
+void md5_init( MD5_CONTEXT *c );
+void md5_write( MD5_CONTEXT *hd, byte *inbuf, size_t inlen);
+void md5_final( MD5_CONTEXT *hd);
+#define md5_read(h) ( (h)->digest )
#endif /*G10_MD5_H*/
diff --git a/cipher/random.c b/cipher/random.c
index a95e7e50..41f001e7 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -82,13 +82,12 @@ open_device( const char *name, int minor )
log_fatal("can't open %s: %s\n", name, strerror(errno) );
if( fstat( fd, &sb ) )
log_fatal("stat() off %s failed: %s\n", name, strerror(errno) );
- if( !S_ISCHR(sb.st_mode)
- #ifdef __linux__
- || (sb.st_rdev >> 8) != 1
- || (sb.st_rdev & 0xff) != minor
- #endif
- )
+ #if defined(__sparc__) && defined(__linux__)
+ #warning something is wrong with UltraPenguin /dev/random
+ #else
+ if( !S_ISCHR(sb.st_mode) )
log_fatal("invalid random device!\n" );
+ #endif
return fd;
}
@@ -140,6 +139,10 @@ the OS a chance to collect more entropy! (Need %d more bytes)\n", length );
assert( length < 200 );
do {
n = read(fd, buffer, length );
+ if( n > length ) {
+ log_error("bogus read from random device (n=%d)\n", n );
+ n = length;
+ }
} while( n == -1 && errno == EINTR );
if( n == -1 )
log_fatal("read error on random device: %s\n", strerror(errno) );
diff --git a/cipher/rmd.h b/cipher/rmd.h
index 3d260cdc..8f53634d 100644
--- a/cipher/rmd.h
+++ b/cipher/rmd.h
@@ -25,27 +25,14 @@
typedef struct {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
- byte buffer[64];
- int bufcount;
-} *RMDHANDLE;
+ byte buf[64];
+ int count;
+} RMD160_CONTEXT;
-/****************
- * Process a single character, this character will be buffered to
- * increase performance.
- */
-#define rmd160_putchar(h,c) \
- do { \
- if( (h)->bufcount == 64 ) \
- rmd160_write( (h), NULL, 0 ); \
- (h)->buffer[(h)->bufcount++] = (c) & 0xff; \
- } while(0)
-
-RMDHANDLE rmd160_open( int secure );
-RMDHANDLE rmd160_copy( RMDHANDLE a );
-void rmd160_close(RMDHANDLE hd);
-void rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen);
-byte * rmd160_final(RMDHANDLE hd);
-
+void rmd160_init( RMD160_CONTEXT *c );
+void rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen);
+void rmd160_final(RMD160_CONTEXT *hd);
+#define rmd160_read(h) ( (h)->buf )
#endif /*G10_RMD_H*/
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index e8c424fa..0b501d77 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -25,7 +25,6 @@
#include <assert.h>
#include "util.h"
#include "memory.h"
-#include "cipher.h" /* grrrr */
#include "rmd.h"
/*********************************
@@ -139,16 +138,16 @@
*/
-static void
-initialize( RMDHANDLE hd )
+void
+rmd160_init( RMD160_CONTEXT *hd )
{
hd->h0 = 0x67452301;
hd->h1 = 0xEFCDAB89;
hd->h2 = 0x98BADCFE;
hd->h3 = 0x10325476;
hd->h4 = 0xC3D2E1F0;
- hd->bufcount = 0;
hd->nblocks = 0;
+ hd->count = 0;
}
@@ -156,7 +155,7 @@ initialize( RMDHANDLE hd )
* Transform the message X which consists of 16 32-bit-words
*/
static void
-transform( RMDHANDLE hd, byte *data )
+transform( RMD160_CONTEXT *hd, byte *data )
{
static int r[80] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
@@ -257,68 +256,22 @@ transform( RMDHANDLE hd, byte *data )
-
-RMDHANDLE
-rmd160_open( int secure )
-{
- RMDHANDLE hd;
-
- hd = secure? m_alloc_secure( sizeof *hd )
- : m_alloc( sizeof *hd );
- initialize(hd);
- return hd;
-}
-
-
-RMDHANDLE
-rmd160_copy( RMDHANDLE a )
-{
- RMDHANDLE b;
-
- assert(a);
- b = m_is_secure(a)? m_alloc_secure( sizeof *b )
- : m_alloc( sizeof *b );
- memcpy( b, a, sizeof *a );
- return b;
-}
-
-
-/* BAD Kludge!!! */
-MD_HANDLE *
-rmd160_copy2md( RMDHANDLE a )
-{
- MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_RMD160 );
- md->u.rmd = rmd160_copy( a );
- return md;
-}
-
-
-
-void
-rmd160_close(RMDHANDLE hd)
-{
- if( hd )
- m_free(hd);
-}
-
-
-
/* Update the message digest with the contents
* of INBUF with length INLEN.
*/
void
-rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen)
+rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen)
{
- if( hd->bufcount == 64 ) { /* flush the buffer */
- transform( hd, hd->buffer );
- hd->bufcount = 0;
+ if( hd->count == 64 ) { /* flush the buffer */
+ transform( hd, hd->buf );
+ hd->count = 0;
hd->nblocks++;
}
if( !inbuf )
return;
- if( hd->bufcount ) {
- for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
+ if( hd->count ) {
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
rmd160_write( hd, NULL, 0 );
if( !inlen )
return;
@@ -326,25 +279,21 @@ rmd160_write( RMDHANDLE hd, byte *inbuf, size_t inlen)
while( inlen >= 64 ) {
transform( hd, inbuf );
- hd->bufcount = 0;
+ hd->count = 0;
hd->nblocks++;
inlen -= 64;
inbuf += 64;
}
- for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
}
-/* The routine final terminates the computation and
- * returns the digest.
- * The handle is prepared for a new cycle, but adding bytes to the
- * handle will the destroy the returned buffer.
- * Returns: 20 bytes representing the digest.
+/* The routine terminates the computation
*/
-byte *
-rmd160_final(RMDHANDLE hd)
+void
+rmd160_final( RMD160_CONTEXT *hd )
{
u32 t, msb, lsb;
byte *p;
@@ -357,37 +306,37 @@ rmd160_final(RMDHANDLE hd)
msb++;
msb += t >> 26;
t = lsb;
- if( (lsb = t + hd->bufcount) < t ) /* add the bufcount */
+ if( (lsb = t + hd->count) < t ) /* add the count */
msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
msb++;
msb += t >> 29;
- if( hd->bufcount < 56 ) { /* enough room */
- hd->buffer[hd->bufcount++] = 0x80; /* pad */
- while( hd->bufcount < 56 )
- hd->buffer[hd->bufcount++] = 0; /* pad */
+ if( hd->count < 56 ) { /* enough room */
+ hd->buf[hd->count++] = 0x80; /* pad */
+ while( hd->count < 56 )
+ hd->buf[hd->count++] = 0; /* pad */
}
else { /* need one extra block */
- hd->buffer[hd->bufcount++] = 0x80; /* pad character */
- while( hd->bufcount < 64 )
- hd->buffer[hd->bufcount++] = 0;
+ hd->buf[hd->count++] = 0x80; /* pad character */
+ while( hd->count < 64 )
+ hd->buf[hd->count++] = 0;
rmd160_write(hd, NULL, 0); /* flush */;
- memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */
+ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
}
/* append the 64 bit count */
- hd->buffer[56] = lsb ;
- hd->buffer[57] = lsb >> 8;
- hd->buffer[58] = lsb >> 16;
- hd->buffer[59] = lsb >> 24;
- hd->buffer[60] = msb ;
- hd->buffer[61] = msb >> 8;
- hd->buffer[62] = msb >> 16;
- hd->buffer[63] = msb >> 24;
- transform( hd, hd->buffer );
-
- p = hd->buffer;
+ hd->buf[56] = lsb ;
+ hd->buf[57] = lsb >> 8;
+ hd->buf[58] = lsb >> 16;
+ hd->buf[59] = lsb >> 24;
+ hd->buf[60] = msb ;
+ hd->buf[61] = msb >> 8;
+ hd->buf[62] = msb >> 16;
+ hd->buf[63] = msb >> 24;
+ transform( hd, hd->buf );
+
+ p = hd->buf;
#ifdef BIG_ENDIAN_HOST
#define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \
*p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0)
@@ -400,10 +349,6 @@ rmd160_final(RMDHANDLE hd)
X(3);
X(4);
#undef X
-
- initialize( hd ); /* prepare for next cycle */
- return hd->buffer; /* now contains the digest */
}
-
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 1685058f..51029c45 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -84,7 +84,6 @@
#include <assert.h>
#include "util.h"
#include "memory.h"
-#include "cipher.h" /* grrrr */
#include "sha1.h"
@@ -110,16 +109,16 @@
( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
-static void
-initialize( SHA1HANDLE hd )
+void
+sha1_init( SHA1_CONTEXT *hd )
{
hd->h0 = 0x67452301;
hd->h1 = 0xefcdab89;
hd->h2 = 0x98badcfe;
hd->h3 = 0x10325476;
hd->h4 = 0xc3d2e1f0;
- hd->bufcount = 0;
hd->nblocks = 0;
+ hd->count = 0;
}
@@ -127,7 +126,7 @@ initialize( SHA1HANDLE hd )
* Transform the message X which consists of 16 32-bit-words
*/
static void
-transform( SHA1HANDLE hd, byte *data )
+transform( SHA1_CONTEXT *hd, byte *data )
{
u32 A, B, C, D, E; /* Local vars */
u32 eData[ 16 ]; /* Expanded data */
@@ -247,69 +246,22 @@ transform( SHA1HANDLE hd, byte *data )
}
-
-
-SHA1HANDLE
-sha1_open( int secure )
-{
- SHA1HANDLE hd;
-
- hd = secure? m_alloc_secure( sizeof *hd )
- : m_alloc( sizeof *hd );
- initialize(hd);
- return hd;
-}
-
-
-SHA1HANDLE
-sha1_copy( SHA1HANDLE a )
-{
- SHA1HANDLE b;
-
- assert(a);
- b = m_is_secure(a)? m_alloc_secure( sizeof *b )
- : m_alloc( sizeof *b );
- memcpy( b, a, sizeof *a );
- return b;
-}
-
-
-/* BAD Kludge!!! */
-MD_HANDLE *
-sha1_copy2md( SHA1HANDLE a )
-{
- MD_HANDLE *md = md_makecontainer( DIGEST_ALGO_SHA1 );
- md->u.sha1 = sha1_copy( a );
- return md;
-}
-
-
-
-void
-sha1_close(SHA1HANDLE hd)
-{
- if( hd )
- m_free(hd);
-}
-
-
-
/* Update the message digest with the contents
* of INBUF with length INLEN.
*/
void
-sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen)
+sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen)
{
- if( hd->bufcount == 64 ) { /* flush the buffer */
- transform( hd, hd->buffer );
- hd->bufcount = 0;
+ if( hd->count == 64 ) { /* flush the buffer */
+ transform( hd, hd->buf );
+ hd->count = 0;
hd->nblocks++;
}
if( !inbuf )
return;
- if( hd->bufcount ) {
- for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
+ if( hd->count ) {
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
sha1_write( hd, NULL, 0 );
if( !inlen )
return;
@@ -317,13 +269,13 @@ sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen)
while( inlen >= 64 ) {
transform( hd, inbuf );
- hd->bufcount = 0;
+ hd->count = 0;
hd->nblocks++;
inlen -= 64;
inbuf += 64;
}
- for( ; inlen && hd->bufcount < 64; inlen-- )
- hd->buffer[hd->bufcount++] = *inbuf++;
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
}
@@ -334,8 +286,8 @@ sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen)
* Returns: 20 bytes representing the digest.
*/
-byte *
-sha1_final(SHA1HANDLE hd)
+void
+sha1_final(SHA1_CONTEXT *hd)
{
u32 t, msb, lsb;
byte *p;
@@ -348,37 +300,37 @@ sha1_final(SHA1HANDLE hd)
msb++;
msb += t >> 26;
t = lsb;
- if( (lsb = t + hd->bufcount) < t ) /* add the bufcount */
+ if( (lsb = t + hd->count) < t ) /* add the count */
msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
msb++;
msb += t >> 29;
- if( hd->bufcount < 56 ) { /* enough room */
- hd->buffer[hd->bufcount++] = 0x80; /* pad */
- while( hd->bufcount < 56 )
- hd->buffer[hd->bufcount++] = 0; /* pad */
+ if( hd->count < 56 ) { /* enough room */
+ hd->buf[hd->count++] = 0x80; /* pad */
+ while( hd->count < 56 )
+ hd->buf[hd->count++] = 0; /* pad */
}
else { /* need one extra block */
- hd->buffer[hd->bufcount++] = 0x80; /* pad character */
- while( hd->bufcount < 64 )
- hd->buffer[hd->bufcount++] = 0;
+ hd->buf[hd->count++] = 0x80; /* pad character */
+ while( hd->count < 64 )
+ hd->buf[hd->count++] = 0;
sha1_write(hd, NULL, 0); /* flush */;
- memset(hd->buffer, 0, 56 ); /* fill next block with zeroes */
+ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
}
/* append the 64 bit count */
- hd->buffer[56] = msb >> 24;
- hd->buffer[57] = msb >> 16;
- hd->buffer[58] = msb >> 8;
- hd->buffer[59] = msb ;
- hd->buffer[60] = lsb >> 24;
- hd->buffer[61] = lsb >> 16;
- hd->buffer[62] = lsb >> 8;
- hd->buffer[63] = lsb ;
- transform( hd, hd->buffer );
-
- p = hd->buffer;
+ hd->buf[56] = msb >> 24;
+ hd->buf[57] = msb >> 16;
+ hd->buf[58] = msb >> 8;
+ hd->buf[59] = msb ;
+ hd->buf[60] = lsb >> 24;
+ hd->buf[61] = lsb >> 16;
+ hd->buf[62] = lsb >> 8;
+ hd->buf[63] = lsb ;
+ transform( hd, hd->buf );
+
+ p = hd->buf;
#ifdef BIG_ENDIAN_HOST
#define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0)
#else /* little endian */
@@ -392,8 +344,6 @@ sha1_final(SHA1HANDLE hd)
X(4);
#undef X
- initialize( hd ); /* prepare for next cycle */
- return hd->buffer; /* now contains the digest */
}
diff --git a/cipher/sha1.h b/cipher/sha1.h
index ca03936f..93af2cac 100644
--- a/cipher/sha1.h
+++ b/cipher/sha1.h
@@ -25,26 +25,14 @@
typedef struct {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
- byte buffer[64];
- int bufcount;
-} *SHA1HANDLE;
+ byte buf[64];
+ int count;
+} SHA1_CONTEXT;
-/****************
- * Process a single character, this character will be buffered to
- * increase performance.
- */
-#define sha1_putchar(h,c) \
- do { \
- if( (h)->bufcount == 64 ) \
- sha1_write( (h), NULL, 0 ); \
- (h)->buffer[(h)->bufcount++] = (c) & 0xff; \
- } while(0)
-
-SHA1HANDLE sha1_open( int secure );
-SHA1HANDLE sha1_copy( SHA1HANDLE a );
-void sha1_close( SHA1HANDLE hd );
-void sha1_write( SHA1HANDLE hd, byte *inbuf, size_t inlen );
-byte * sha1_final( SHA1HANDLE hd );
+void sha1_init( SHA1_CONTEXT *c );
+void sha1_write( SHA1_CONTEXT *hd, byte *inbuf, size_t inlen);
+void sha1_final( SHA1_CONTEXT *hd);
+#define sha1_read(h) ( (h)->buf )
#endif /*G10_SHA1_H*/
diff --git a/mpi/config.links b/mpi/config.links
index 9ee1d056..fd580e51 100644
--- a/mpi/config.links
+++ b/mpi/config.links
@@ -48,6 +48,24 @@ case "${target}" in
path="pa7100 hppa1_1 hppa"
mpi_extra_modules="udiv-qrnnd"
;;
+ 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"
+ ;;
+ 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"
+ ;;
*)
echo '/* No assembler modules configured */' >>./mpi/asm-syntax.h
path=""
diff --git a/mpi/sparc32/distfiles b/mpi/sparc32/distfiles
new file mode 100644
index 00000000..7933edc8
--- /dev/null
+++ b/mpi/sparc32/distfiles
@@ -0,0 +1,4 @@
+
+mpih-add1.S
+udiv.S
+
diff --git a/mpi/sparc32/mpih-add1.S b/mpi/sparc32/mpih-add1.S
new file mode 100644
index 00000000..04315d10
--- /dev/null
+++ b/mpi/sparc32/mpih-add1.S
@@ -0,0 +1,237 @@
+! SPARC __mpn_add_n -- Add two limb vectors of the same length > 0 and store
+! sum in a third limb vector.
+
+! Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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.
+
+
+/*******************
+ * 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/udiv.S b/mpi/sparc32/udiv.S
new file mode 100644
index 00000000..3e2376cf
--- /dev/null
+++ b/mpi/sparc32/udiv.S
@@ -0,0 +1,188 @@
+! 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 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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
+! 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 00000000..5789f35b
--- /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 00000000..8bc1db57
--- /dev/null
+++ b/mpi/sparc32v8/mpih-mul1.S
@@ -0,0 +1,101 @@
+! 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 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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 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 00000000..9055f89e
--- /dev/null
+++ b/mpi/sparc32v8/mpih-mul2.S
@@ -0,0 +1,124 @@
+! 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 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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 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 00000000..efd83de4
--- /dev/null
+++ b/mpi/sparc32v8/mpih-mul3.S
@@ -0,0 +1,60 @@
+! 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 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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 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 00000000..5506c419
--- /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 00000000..07d904c7
--- /dev/null
+++ b/mpi/supersparc/udiv.S
@@ -0,0 +1,110 @@
+! 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 Free Software Foundation, Inc.
+
+! This file is part of the GNU MP Library.
+
+! The GNU MP 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 MP 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 MP 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
+! 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
+