Coverage Report

Created: 2024-05-21 06:29

/src/binutils-gdb/gas/flonum-mult.c
Line
Count
Source (jump to first uncovered line)
1
/* flonum_mult.c - multiply two flonums
2
   Copyright (C) 1987-2024 Free Software Foundation, Inc.
3
4
   This file is part of GAS, the GNU Assembler.
5
6
   GAS is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
11
   GAS is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with GAS; see the file COPYING.  If not, write to the Free
18
   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19
   02110-1301, USA.  */
20
21
#include "ansidecl.h"
22
#include "flonum.h"
23
24
/*  plan for a . b => p(roduct)
25
26
  +-------+-------+-/   /-+-------+-------+
27
  | a | a |  ...  | a | a |
28
  |  A  |  A-1  | |  1  |  0  |
29
  +-------+-------+-/   /-+-------+-------+
30
31
  +-------+-------+-/   /-+-------+-------+
32
  | b | b |  ...  | b | b |
33
  |  B  |  B-1  | |  1  |  0  |
34
  +-------+-------+-/   /-+-------+-------+
35
36
  +-------+-------+-/   /-+-------+-/   /-+-------+-------+
37
  | p | p |  ...  | p |  ...  | p | p |
38
  |  A+B+1|  A+B  | |  N  | |  1  |  0  |
39
  +-------+-------+-/   /-+-------+-/   /-+-------+-------+
40
41
  /^\
42
  (carry) a .b     ...      |    ...   a .b  a .b
43
  A  B        |     0  1    0  0
44
  |
45
  ...     |    ...   a .b
46
  |     1  0
47
  |
48
  |    ...
49
  |
50
  |
51
  |
52
  |     ___
53
  |     \
54
  +-----  P  =   >  a .b
55
  N   /__  i  j
56
57
  N = 0 ... A+B
58
59
  for all i,j where i+j=N
60
  [i,j integers > 0]
61
62
  a[], b[], p[] may not intersect.
63
  Zero length factors signify 0 significant bits: treat as 0.0.
64
  0.0 factors do the right thing.
65
  Zero length product OK.
66
67
  I chose the ForTran accent "foo[bar]" instead of the C accent "*garply"
68
  because I felt the ForTran way was more intuitive. The C way would
69
  probably yield better code on most C compilers. Dean Elsner.
70
  (C style also gives deeper insight [to me] ... oh well ...)  */
71

72
void
73
flonum_multip (const FLONUM_TYPE *a, const FLONUM_TYPE *b,
74
         FLONUM_TYPE *product)
75
22.1k
{
76
22.1k
  int size_of_a;    /* 0 origin  */
77
22.1k
  int size_of_b;    /* 0 origin  */
78
22.1k
  int size_of_product;    /* 0 origin  */
79
22.1k
  int size_of_sum;    /* 0 origin  */
80
22.1k
  int extra_product_positions;  /* 1 origin  */
81
22.1k
  unsigned long work;
82
22.1k
  unsigned long carry;
83
22.1k
  long exponent;
84
22.1k
  LITTLENUM_TYPE *q;
85
22.1k
  long significant;   /* TRUE when we emit a non-0 littlenum  */
86
  /* ForTran accent follows.  */
87
22.1k
  int P;      /* Scan product low-order -> high.  */
88
22.1k
  int N;      /* As in sum above.  */
89
22.1k
  int A;      /* Which [] of a?  */
90
22.1k
  int B;      /* Which [] of b?  */
91
92
22.1k
  if ((a->sign != '-' && a->sign != '+')
93
22.1k
      || (b->sign != '-' && b->sign != '+'))
94
0
    {
95
      /* Got to fail somehow.  Any suggestions?  */
96
0
      product->sign = 0;
97
0
      return;
98
0
    }
99
22.1k
  product->sign = (a->sign == b->sign) ? '+' : '-';
100
22.1k
  size_of_a = a->leader - a->low;
101
22.1k
  size_of_b = b->leader - b->low;
102
22.1k
  exponent = a->exponent + b->exponent;
103
22.1k
  size_of_product = product->high - product->low;
104
22.1k
  size_of_sum = size_of_a + size_of_b;
105
22.1k
  extra_product_positions = size_of_product - size_of_sum;
106
22.1k
  if (extra_product_positions < 0)
107
16.6k
    {
108
16.6k
      P = extra_product_positions;  /* P < 0  */
109
16.6k
      exponent -= extra_product_positions;  /* Increases exponent.  */
110
16.6k
    }
111
5.44k
  else
112
5.44k
    {
113
5.44k
      P = 0;
114
5.44k
    }
115
22.1k
  carry = 0;
116
22.1k
  significant = 0;
117
318k
  for (N = 0; N <= size_of_sum; N++)
118
296k
    {
119
296k
      work = carry;
120
296k
      carry = 0;
121
3.32M
      for (A = 0; A <= N; A++)
122
3.02M
  {
123
3.02M
    B = N - A;
124
3.02M
    if (A <= size_of_a && B <= size_of_b && B >= 0)
125
716k
      {
126
#ifdef TRACE
127
        printf ("a:low[%d.]=%04x b:low[%d.]=%04x work_before=%08x\n",
128
          A, a->low[A], B, b->low[B], work);
129
#endif
130
        /* Watch out for sign extension!  Without the casts, on
131
     the DEC Alpha, the multiplication result is *signed*
132
     int, which gets sign-extended to convert to the
133
     unsigned long!  */
134
716k
        work += (unsigned long) a->low[A] * (unsigned long) b->low[B];
135
716k
        carry += work >> LITTLENUM_NUMBER_OF_BITS;
136
716k
        work &= LITTLENUM_MASK;
137
#ifdef TRACE
138
        printf ("work=%08x carry=%04x\n", work, carry);
139
#endif
140
716k
      }
141
3.02M
  }
142
296k
      significant |= work;
143
296k
      if (significant || P < 0)
144
296k
  {
145
296k
    if (P >= 0)
146
136k
      {
147
136k
        product->low[P] = work;
148
#ifdef TRACE
149
        printf ("P=%d. work[p]:=%04x\n", P, work);
150
#endif
151
136k
      }
152
296k
    P++;
153
296k
  }
154
42
      else
155
42
  {
156
42
    extra_product_positions++;
157
42
    exponent++;
158
42
  }
159
296k
    }
160
  /* [P]-> position # size_of_sum + 1.
161
     This is where 'carry' should go.  */
162
#ifdef TRACE
163
  printf ("final carry =%04x\n", carry);
164
#endif
165
22.1k
  if (carry)
166
1.95k
    {
167
1.95k
      if (extra_product_positions > 0)
168
20
  product->low[P] = carry;
169
1.93k
      else
170
1.93k
  {
171
    /* No room at high order for carry littlenum.  */
172
    /* Shift right 1 to make room for most significant littlenum.  */
173
1.93k
    exponent++;
174
1.93k
    P--;
175
16.8k
    for (q = product->low + P; q >= product->low; q--)
176
14.9k
      {
177
14.9k
        work = *q;
178
14.9k
        *q = carry;
179
14.9k
        carry = work;
180
14.9k
      }
181
1.93k
  }
182
1.95k
    }
183
20.1k
  else
184
20.1k
    P--;
185
22.1k
  product->leader = product->low + P;
186
22.1k
  product->exponent = exponent;
187
22.1k
}