gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gas / flonum-mult.c
index c5aa0e86400f25ad44ccffd42bd5f035ffbfd065..fe7ecc1f31a566eaa77915473c3b84f780e3b31f 100644 (file)
@@ -1,45 +1,43 @@
-/* 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.  */
+/* flonum_mult.c - multiply two flonums
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
+   This file is part of GAS, the GNU Assembler.
+
+   GAS 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 3, or (at your option)
+   any later version.
+
+   GAS 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 GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "ansidecl.h"
 #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
        |                 \
        +-----  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 ...)
-       */
+       (C style also gives deeper insight [to me] ... oh well ...)  */
 \f
-void flonum_multip (a, b, product)
-const FLONUM_TYPE *a;
-const FLONUM_TYPE *b;
-FLONUM_TYPE *product;
+void
+flonum_multip (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++)
+  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)
            {
-                   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);
+             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;
+             /* Watch out for sign extension!  Without the casts, on
+                the DEC Alpha, the multiplication result is *signed*
+                int, which gets sign-extended to convert to the
+                unsigned long!  */
+             work += (unsigned long) a->low[A] * (unsigned long) b->low[B];
+             carry += work >> LITTLENUM_NUMBER_OF_BITS;
+             work &= LITTLENUM_MASK;
 #ifdef TRACE
-                                           printf("work=%08x carry=%04x\n", work, carry);
+             printf ("work=%08x carry=%04x\n", work, carry);
 #endif
-                                   }
-                       }
-                   significant |= work;
-                   if (significant || P<0)
-                       {
-                               if (P >= 0)
-                                   {
-                                           product -> low [P] = work;
+           }
+       }
+      significant |= work;
+      if (significant || P < 0)
+       {
+         if (P >= 0)
+           {
+             product->low[P] = work;
 #ifdef TRACE
-                                           printf("P=%d. work[p]:=%04x\n", P, work);
+             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.
-        */
+         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);
+  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
+  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--)
            {
-                   P --;
+             work = *q;
+             *q = carry;
+             carry = work;
            }
-       product -> leader       = product -> low + P;
-       product -> exponent     = exponent;
+       }
+    }
+  else
+    P--;
+  product->leader = product->low + P;
+  product->exponent = exponent;
 }
-
-/* end: flonum_multip.c */
This page took 0.037501 seconds and 4 git commands to generate.