3a69b3aca6
Cherrypick from master 1991-04-04 18:19:53 UTC K. Richard Pixley <rich@cygnus> 'Initial revision': gas/COPYING gas/ChangeLog gas/Makefile.in gas/README gas/app.c gas/as.c gas/as.h gas/atof-generic.c gas/bignum-copy.c gas/bignum.h gas/cond.c gas/config/atof-ieee.c gas/config/atof-vax.c gas/config/obj-aout.c gas/config/obj-aout.h gas/config/obj-bout.c gas/config/obj-bout.h gas/config/obj-coff.c gas/config/obj-coff.h gas/config/tc-a29k.c gas/config/tc-a29k.h gas/config/tc-generic.c gas/config/tc-generic.h gas/config/tc-i386.c gas/config/tc-i386.h gas/config/tc-i860.c gas/config/tc-i860.h gas/config/tc-i960.c gas/config/tc-i960.h gas/config/tc-m68851.h gas/config/tc-m68k.c gas/config/tc-m68k.h gas/config/tc-ns32k.c gas/config/tc-ns32k.h gas/config/tc-sparc.c gas/config/tc-sparc.h gas/config/tc-vax.c gas/config/tc-vax.h gas/config/te-generic.h gas/config/te-ic960.h gas/config/te-sun3.h gas/config/vax-inst.h gas/configure gas/configure.in gas/debug.c gas/expr.c gas/expr.h gas/flonum-copy.c gas/flonum-mult.c gas/flonum.h gas/frags.c gas/frags.h gas/hash.c gas/hash.h gas/input-file.c gas/input-file.h gas/input-scrub.c gas/messages.c gas/obj.h gas/output-file.c gas/output-file.h gas/read.c gas/read.h gas/struc-symbol.h gas/subsegs.c gas/subsegs.h gas/symbols.c gas/symbols.h gas/tc.h gas/write.c gas/write.h ld/ld.h ld/ldexp.c ld/ldfile.c ld/ldfile.h ld/ldlang.h ld/ldlex.h ld/ldmain.h ld/ldmisc.h ld/ldwrite.h Cherrypick from master 1991-03-21 21:29:06 UTC David Henkel-Wallace <gumby@cygnus> 'Initial revision': ld/ldexp.h ld/ldgram.y ld/ldlang.c ld/ldlex.l ld/ldmain.c ld/ldmisc.c ld/ldwrite.c Cherrypick from master 1991-01-17 15:34:55 UTC Roland Pesch <pesch@cygnus> 'Initial revision': gas/doc/as.texinfo
201 lines
5.1 KiB
C
201 lines
5.1 KiB
C
/* flonum_multip.c - multiply two flonums
|
||
Copyright (C) 1987, 1990, 1991 Free Software Foundation, Inc.
|
||
|
||
This file is part of Gas, the GNU Assembler.
|
||
|
||
The GNU assembler is distributed in the hope that it will be
|
||
useful, but WITHOUT ANY WARRANTY. No author or distributor
|
||
accepts responsibility to anyone for the consequences of using it
|
||
or for whether it serves any particular purpose or works at all,
|
||
unless he says so in writing. Refer to the GNU Assembler General
|
||
Public License for full details.
|
||
|
||
Everyone is granted permission to copy, modify and redistribute
|
||
the GNU Assembler, but only under the conditions described in the
|
||
GNU Assembler General Public License. A copy of this license is
|
||
supposed to have been given to you along with the GNU Assembler
|
||
so you can know your rights and responsibilities. It should be
|
||
in a file named COPYING. Among other things, the copyright
|
||
notice and this notice must be preserved on all copies. */
|
||
|
||
/* static const char rcsid[] = "$Id$"; */
|
||
|
||
#include "flonum.h"
|
||
|
||
/* plan for a . b => p(roduct)
|
||
|
||
|
||
+-------+-------+-/ /-+-------+-------+
|
||
| a | a | ... | a | a |
|
||
| A | A-1 | | 1 | 0 |
|
||
+-------+-------+-/ /-+-------+-------+
|
||
|
||
|
||
+-------+-------+-/ /-+-------+-------+
|
||
| b | b | ... | b | b |
|
||
| B | B-1 | | 1 | 0 |
|
||
+-------+-------+-/ /-+-------+-------+
|
||
|
||
|
||
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
|
||
| p | p | ... | p | ... | p | p |
|
||
| A+B+1| A+B | | N | | 1 | 0 |
|
||
+-------+-------+-/ /-+-------+-/ /-+-------+-------+
|
||
|
||
/^\
|
||
(carry) a .b ... | ... a .b a .b
|
||
A B | 0 1 0 0
|
||
|
|
||
... | ... a .b
|
||
| 1 0
|
||
|
|
||
| ...
|
||
|
|
||
|
|
||
|
|
||
| ___
|
||
| \
|
||
+----- P = > a .b
|
||
N /__ i j
|
||
|
||
N = 0 ... A+B
|
||
|
||
for all i,j where i+j=N
|
||
[i,j integers > 0]
|
||
|
||
a[], b[], p[] may not intersect.
|
||
Zero length factors signify 0 significant bits: treat as 0.0.
|
||
0.0 factors do the right thing.
|
||
Zero length product OK.
|
||
|
||
I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
|
||
because I felt the ForTran way was more intuitive. The C way would
|
||
probably yield better code on most C compilers. Dean Elsner.
|
||
(C style also gives deeper insight [to me] ... oh well ...)
|
||
*/
|
||
|
||
void flonum_multip (a, b, product)
|
||
const FLONUM_TYPE *a;
|
||
const FLONUM_TYPE *b;
|
||
FLONUM_TYPE *product;
|
||
{
|
||
int size_of_a; /* 0 origin */
|
||
int size_of_b; /* 0 origin */
|
||
int size_of_product; /* 0 origin */
|
||
int size_of_sum; /* 0 origin */
|
||
int extra_product_positions;/* 1 origin */
|
||
unsigned long work;
|
||
unsigned long carry;
|
||
long exponent;
|
||
LITTLENUM_TYPE * q;
|
||
long significant; /* TRUE when we emit a non-0 littlenum */
|
||
/* ForTran accent follows. */
|
||
int P; /* Scan product low-order -> high. */
|
||
int N; /* As in sum above. */
|
||
int A; /* Which [] of a? */
|
||
int B; /* Which [] of b? */
|
||
|
||
if((a->sign!='-' && a->sign!='+') || (b->sign!='-' && b->sign!='+')) {
|
||
/* ...
|
||
Got to fail somehow. Any suggestions? */
|
||
product->sign=0;
|
||
return;
|
||
}
|
||
product -> sign = (a->sign == b->sign) ? '+' : '-';
|
||
size_of_a = a -> leader - a -> low;
|
||
size_of_b = b -> leader - b -> low;
|
||
exponent = a -> exponent + b -> exponent;
|
||
size_of_product = product -> high - product -> low;
|
||
size_of_sum = size_of_a + size_of_b;
|
||
extra_product_positions = size_of_product - size_of_sum;
|
||
if (extra_product_positions < 0)
|
||
{
|
||
P = extra_product_positions; /* P < 0 */
|
||
exponent -= extra_product_positions; /* Increases exponent. */
|
||
}
|
||
else
|
||
{
|
||
P = 0;
|
||
}
|
||
carry = 0;
|
||
significant = 0;
|
||
for (N = 0;
|
||
N <= size_of_sum;
|
||
N++)
|
||
{
|
||
work = carry;
|
||
carry = 0;
|
||
for (A = 0;
|
||
A <= N;
|
||
A ++)
|
||
{
|
||
B = N - A;
|
||
if (A <= size_of_a && B <= size_of_b && B >= 0)
|
||
{
|
||
#ifdef TRACE
|
||
printf("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n", A, a->low[A], B, b->low[B], work);
|
||
#endif
|
||
work += a -> low [A] * b -> low [B];
|
||
carry += work >> LITTLENUM_NUMBER_OF_BITS;
|
||
work &= LITTLENUM_MASK;
|
||
#ifdef TRACE
|
||
printf("work=%08x carry=%04x\n", work, carry);
|
||
#endif
|
||
}
|
||
}
|
||
significant |= work;
|
||
if (significant || P<0)
|
||
{
|
||
if (P >= 0)
|
||
{
|
||
product -> low [P] = work;
|
||
#ifdef TRACE
|
||
printf("P=%d. work[p]:=%04x\n", P, work);
|
||
#endif
|
||
}
|
||
P ++;
|
||
}
|
||
else
|
||
{
|
||
extra_product_positions ++;
|
||
exponent ++;
|
||
}
|
||
}
|
||
/*
|
||
* [P]-> position # size_of_sum + 1.
|
||
* This is where 'carry' should go.
|
||
*/
|
||
#ifdef TRACE
|
||
printf("final carry =%04x\n", carry);
|
||
#endif
|
||
if (carry)
|
||
{
|
||
if (extra_product_positions > 0)
|
||
{
|
||
product -> low [P] = carry;
|
||
}
|
||
else
|
||
{
|
||
/* No room at high order for carry littlenum. */
|
||
/* Shift right 1 to make room for most significant littlenum. */
|
||
exponent ++;
|
||
P --;
|
||
for (q = product -> low + P;
|
||
q >= product -> low;
|
||
q --)
|
||
{
|
||
work = * q;
|
||
* q = carry;
|
||
carry = work;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
P --;
|
||
}
|
||
product -> leader = product -> low + P;
|
||
product -> exponent = exponent;
|
||
}
|
||
|
||
/* end: flonum_multip.c */
|