OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [libbid/] [bid128_mul.c] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* Copyright (C) 2007, 2009  Free Software Foundation, Inc.
2
 
3
This file is part of GCC.
4
 
5
GCC is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free
7
Software Foundation; either version 3, or (at your option) any later
8
version.
9
 
10
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11
WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13
for more details.
14
 
15
Under Section 7 of GPL version 3, you are granted additional
16
permissions described in the GCC Runtime Library Exception, version
17
3.1, as published by the Free Software Foundation.
18
 
19
You should have received a copy of the GNU General Public License and
20
a copy of the GCC Runtime Library Exception along with this program;
21
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22
<http://www.gnu.org/licenses/>.  */
23
 
24
#include "bid_internal.h"
25
 
26
#if DECIMAL_CALL_BY_REFERENCE
27
void
28
bid64dq_mul (UINT64 * pres, UINT64 * px, UINT128 * py
29
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
30
             _EXC_INFO_PARAM) {
31
  UINT64 x = *px;
32
#if !DECIMAL_GLOBAL_ROUNDING
33
  unsigned int rnd_mode = *prnd_mode;
34
#endif
35
#else
36
UINT64
37
bid64dq_mul (UINT64 x, UINT128 y
38
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
39
             _EXC_INFO_PARAM) {
40
#endif
41
  UINT64 res = 0xbaddbaddbaddbaddull;
42
  UINT128 x1;
43
 
44
#if DECIMAL_CALL_BY_REFERENCE
45
  bid64_to_bid128 (&x1, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
46
  bid64qq_mul (&res, &x1, py
47
               _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
48
               _EXC_INFO_ARG);
49
#else
50
  x1 = bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
51
  res = bid64qq_mul (x1, y
52
                     _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
53
                     _EXC_INFO_ARG);
54
#endif
55
  BID_RETURN (res);
56
}
57
 
58
 
59
#if DECIMAL_CALL_BY_REFERENCE
60
void
61
bid64qd_mul (UINT64 * pres, UINT128 * px, UINT64 * py
62
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
63
             _EXC_INFO_PARAM) {
64
  UINT64 y = *py;
65
#if !DECIMAL_GLOBAL_ROUNDING
66
  unsigned int rnd_mode = *prnd_mode;
67
#endif
68
#else
69
UINT64
70
bid64qd_mul (UINT128 x, UINT64 y
71
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
72
             _EXC_INFO_PARAM) {
73
#endif
74
  UINT64 res = 0xbaddbaddbaddbaddull;
75
  UINT128 y1;
76
 
77
#if DECIMAL_CALL_BY_REFERENCE
78
  bid64_to_bid128 (&y1, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
79
  bid64qq_mul (&res, px, &y1
80
               _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
81
               _EXC_INFO_ARG);
82
#else
83
  y1 = bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
84
  res = bid64qq_mul (x, y1
85
                     _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
86
                     _EXC_INFO_ARG);
87
#endif
88
  BID_RETURN (res);
89
}
90
 
91
 
92
#if DECIMAL_CALL_BY_REFERENCE
93
void
94
bid64qq_mul (UINT64 * pres, UINT128 * px, UINT128 * py
95
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
96
             _EXC_INFO_PARAM) {
97
  UINT128 x = *px, y = *py;
98
#if !DECIMAL_GLOBAL_ROUNDING
99
  unsigned int rnd_mode = *prnd_mode;
100
#endif
101
#else
102
UINT64
103
bid64qq_mul (UINT128 x, UINT128 y
104
             _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
105
             _EXC_INFO_PARAM) {
106
#endif
107
 
108
  UINT128 z = { {0x0000000000000000ull, 0x5ffe000000000000ull}
109
  };
110
  UINT64 res = 0xbaddbaddbaddbaddull;
111
  UINT64 x_sign, y_sign, p_sign;
112
  UINT64 x_exp, y_exp, p_exp;
113
  int true_p_exp;
114
  UINT128 C1, C2;
115
 
116
  BID_SWAP128 (z);
117
  // skip cases where at least one operand is NaN or infinity
118
  if (!(((x.w[HIGH_128W] & MASK_NAN) == MASK_NAN) ||
119
        ((y.w[HIGH_128W] & MASK_NAN) == MASK_NAN) ||
120
        ((x.w[HIGH_128W] & MASK_ANY_INF) == MASK_INF) ||
121
        ((y.w[HIGH_128W] & MASK_ANY_INF) == MASK_INF))) {
122
    // x, y are 0 or f but not inf or NaN => unpack the arguments and check
123
    // for non-canonical values
124
 
125
    x_sign = x.w[HIGH_128W] & MASK_SIGN;        // 0 for positive, MASK_SIGN for negative
126
    C1.w[1] = x.w[HIGH_128W] & MASK_COEFF;
127
    C1.w[0] = x.w[LOW_128W];
128
    // check for non-canonical values - treated as zero
129
    if ((x.w[HIGH_128W] & 0x6000000000000000ull) ==
130
        0x6000000000000000ull) {
131
      // G0_G1=11 => non-canonical
132
      x_exp = (x.w[HIGH_128W] << 2) & MASK_EXP; // biased and shifted left 49 bits
133
      C1.w[1] = 0;       // significand high
134
      C1.w[0] = 0;        // significand low
135
    } else {    // G0_G1 != 11
136
      x_exp = x.w[HIGH_128W] & MASK_EXP;        // biased and shifted left 49 bits
137
      if (C1.w[1] > 0x0001ed09bead87c0ull ||
138
          (C1.w[1] == 0x0001ed09bead87c0ull &&
139
           C1.w[0] > 0x378d8e63ffffffffull)) {
140
        // x is non-canonical if coefficient is larger than 10^34 -1
141
        C1.w[1] = 0;
142
        C1.w[0] = 0;
143
      } else {  // canonical          
144
        ;
145
      }
146
    }
147
    y_sign = y.w[HIGH_128W] & MASK_SIGN;        // 0 for positive, MASK_SIGN for negative
148
    C2.w[1] = y.w[HIGH_128W] & MASK_COEFF;
149
    C2.w[0] = y.w[LOW_128W];
150
    // check for non-canonical values - treated as zero
151
    if ((y.w[HIGH_128W] & 0x6000000000000000ull) ==
152
        0x6000000000000000ull) {
153
      // G0_G1=11 => non-canonical
154
      y_exp = (y.w[HIGH_128W] << 2) & MASK_EXP; // biased and shifted left 49 bits
155
      C2.w[1] = 0;       // significand high
156
      C2.w[0] = 0;        // significand low 
157
    } else {    // G0_G1 != 11
158
      y_exp = y.w[HIGH_128W] & MASK_EXP;        // biased and shifted left 49 bits
159
      if (C2.w[1] > 0x0001ed09bead87c0ull ||
160
          (C2.w[1] == 0x0001ed09bead87c0ull &&
161
           C2.w[0] > 0x378d8e63ffffffffull)) {
162
        // y is non-canonical if coefficient is larger than 10^34 -1
163
        C2.w[1] = 0;
164
        C2.w[0] = 0;
165
      } else {  // canonical
166
        ;
167
      }
168
    }
169
    p_sign = x_sign ^ y_sign;   // sign of the product
170
 
171
    true_p_exp = (x_exp >> 49) - 6176 + (y_exp >> 49) - 6176;
172
    // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0 
173
    if (true_p_exp < -398)
174
      p_exp = 0; // cannot be less than EXP_MIN
175
    else if (true_p_exp > 369)
176
      p_exp = (UINT64) (369 + 398) << 53;       // cannot be more than EXP_MAX
177
    else
178
      p_exp = (UINT64) (true_p_exp + 398) << 53;
179
 
180
    if ((C1.w[1] == 0x0 && C1.w[0] == 0x0) ||
181
        (C2.w[1] == 0x0 && C2.w[0] == 0x0)) {
182
      // x = 0 or y = 0
183
      // the result is 0
184
      res = p_sign | p_exp;     // preferred exponent in [EXP_MIN, EXP_MAX]
185
      BID_RETURN (res)
186
    }   // else continue
187
  }
188
  // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
189
#if DECIMAL_CALL_BY_REFERENCE
190
  bid64qqq_fma (&res, &y, &x, &z
191
                _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
192
                _EXC_INFO_ARG);
193
#else
194
  res = bid64qqq_fma (y, x, z
195
                      _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
196
                      _EXC_INFO_ARG);
197
#endif
198
  BID_RETURN (res);
199
}
200
 
201
 
202
#if DECIMAL_CALL_BY_REFERENCE
203
void
204
bid128dd_mul (UINT128 * pres, UINT64 * px, UINT64 * py
205
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
206
              _EXC_INFO_PARAM) {
207
  UINT64 x = *px, y = *py;
208
#if !DECIMAL_GLOBAL_ROUNDING
209
  unsigned int rnd_mode = *prnd_mode;
210
#endif
211
#else
212
UINT128
213
bid128dd_mul (UINT64 x, UINT64 y
214
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
215
              _EXC_INFO_PARAM) {
216
#endif
217
  UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
218
  };
219
  UINT128 x1, y1;
220
 
221
#if DECIMAL_CALL_BY_REFERENCE
222
  bid64_to_bid128 (&x1, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
223
  bid64_to_bid128 (&y1, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
224
  bid128_mul (&res, &x1, &y1
225
              _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
226
              _EXC_INFO_ARG);
227
#else
228
  x1 = bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
229
  y1 = bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
230
  res = bid128_mul (x1, y1
231
                    _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
232
                    _EXC_INFO_ARG);
233
#endif
234
  BID_RETURN (res);
235
}
236
 
237
 
238
#if DECIMAL_CALL_BY_REFERENCE
239
void
240
bid128dq_mul (UINT128 * pres, UINT64 * px, UINT128 * py
241
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
242
              _EXC_INFO_PARAM) {
243
  UINT64 x = *px;
244
#if !DECIMAL_GLOBAL_ROUNDING
245
  unsigned int rnd_mode = *prnd_mode;
246
#endif
247
#else
248
UINT128
249
bid128dq_mul (UINT64 x, UINT128 y
250
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
251
              _EXC_INFO_PARAM) {
252
#endif
253
  UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
254
  };
255
  UINT128 x1;
256
 
257
#if DECIMAL_CALL_BY_REFERENCE
258
  bid64_to_bid128 (&x1, &x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
259
  bid128_mul (&res, &x1, py
260
              _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
261
              _EXC_INFO_ARG);
262
#else
263
  x1 = bid64_to_bid128 (x _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
264
  res = bid128_mul (x1, y
265
                    _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
266
                    _EXC_INFO_ARG);
267
#endif
268
  BID_RETURN (res);
269
}
270
 
271
 
272
#if DECIMAL_CALL_BY_REFERENCE
273
void
274
bid128qd_mul (UINT128 * pres, UINT128 * px, UINT64 * py
275
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
276
              _EXC_INFO_PARAM) {
277
  UINT64 y = *py;
278
#if !DECIMAL_GLOBAL_ROUNDING
279
  unsigned int rnd_mode = *prnd_mode;
280
#endif
281
#else
282
UINT128
283
bid128qd_mul (UINT128 x, UINT64 y
284
              _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
285
              _EXC_INFO_PARAM) {
286
#endif
287
  UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
288
  };
289
  UINT128 y1;
290
 
291
#if DECIMAL_CALL_BY_REFERENCE
292
  bid64_to_bid128 (&y1, &y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
293
  bid128_mul (&res, px, &y1
294
              _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
295
              _EXC_INFO_ARG);
296
#else
297
  y1 = bid64_to_bid128 (y _EXC_FLAGS_ARG _EXC_MASKS_ARG _EXC_INFO_ARG);
298
  res = bid128_mul (x, y1
299
                    _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
300
                    _EXC_INFO_ARG);
301
#endif
302
  BID_RETURN (res);
303
}
304
 
305
 
306
// bid128_mul stands for bid128qq_mul
307
#if DECIMAL_CALL_BY_REFERENCE
308
void
309
bid128_mul (UINT128 * pres, UINT128 * px,
310
            UINT128 *
311
            py _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
312
            _EXC_INFO_PARAM) {
313
  UINT128 x = *px, y = *py;
314
 
315
#if !DECIMAL_GLOBAL_ROUNDING
316
  unsigned int rnd_mode = *prnd_mode;
317
 
318
#endif
319
#else
320
UINT128
321
bid128_mul (UINT128 x,
322
            UINT128 y _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
323
            _EXC_INFO_PARAM) {
324
 
325
#endif
326
  UINT128 z = { {0x0000000000000000ull, 0x5ffe000000000000ull}
327
  };
328
  UINT128 res = { {0xbaddbaddbaddbaddull, 0xbaddbaddbaddbaddull}
329
  };
330
  UINT64 x_sign, y_sign, p_sign;
331
  UINT64 x_exp, y_exp, p_exp;
332
  int true_p_exp;
333
  UINT128 C1, C2;
334
 
335
  BID_SWAP128 (x);
336
  BID_SWAP128 (y);
337
  // skip cases where at least one operand is NaN or infinity
338
  if (!(((x.w[1] & MASK_NAN) == MASK_NAN) ||
339
        ((y.w[1] & MASK_NAN) == MASK_NAN) ||
340
        ((x.w[1] & MASK_ANY_INF) == MASK_INF) ||
341
        ((y.w[1] & MASK_ANY_INF) == MASK_INF))) {
342
    // x, y are 0 or f but not inf or NaN => unpack the arguments and check
343
    // for non-canonical values
344
 
345
    x_sign = x.w[1] & MASK_SIGN;        // 0 for positive, MASK_SIGN for negative
346
    C1.w[1] = x.w[1] & MASK_COEFF;
347
    C1.w[0] = x.w[0];
348
    // check for non-canonical values - treated as zero
349
    if ((x.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) {
350
      // G0_G1=11 => non-canonical
351
      x_exp = (x.w[1] << 2) & MASK_EXP; // biased and shifted left 49 bits
352
      C1.w[1] = 0;       // significand high
353
      C1.w[0] = 0;        // significand low
354
    } else {    // G0_G1 != 11
355
      x_exp = x.w[1] & MASK_EXP;        // biased and shifted left 49 bits
356
      if (C1.w[1] > 0x0001ed09bead87c0ull ||
357
          (C1.w[1] == 0x0001ed09bead87c0ull &&
358
           C1.w[0] > 0x378d8e63ffffffffull)) {
359
        // x is non-canonical if coefficient is larger than 10^34 -1
360
        C1.w[1] = 0;
361
        C1.w[0] = 0;
362
      } else {  // canonical          
363
        ;
364
      }
365
    }
366
    y_sign = y.w[1] & MASK_SIGN;        // 0 for positive, MASK_SIGN for negative
367
    C2.w[1] = y.w[1] & MASK_COEFF;
368
    C2.w[0] = y.w[0];
369
    // check for non-canonical values - treated as zero
370
    if ((y.w[1] & 0x6000000000000000ull) == 0x6000000000000000ull) {
371
      // G0_G1=11 => non-canonical
372
      y_exp = (y.w[1] << 2) & MASK_EXP; // biased and shifted left 49 bits
373
      C2.w[1] = 0;       // significand high
374
      C2.w[0] = 0;        // significand low 
375
    } else {    // G0_G1 != 11
376
      y_exp = y.w[1] & MASK_EXP;        // biased and shifted left 49 bits
377
      if (C2.w[1] > 0x0001ed09bead87c0ull ||
378
          (C2.w[1] == 0x0001ed09bead87c0ull &&
379
           C2.w[0] > 0x378d8e63ffffffffull)) {
380
        // y is non-canonical if coefficient is larger than 10^34 -1
381
        C2.w[1] = 0;
382
        C2.w[0] = 0;
383
      } else {  // canonical
384
        ;
385
      }
386
    }
387
    p_sign = x_sign ^ y_sign;   // sign of the product
388
 
389
    true_p_exp = (x_exp >> 49) - 6176 + (y_exp >> 49) - 6176;
390
    // true_p_exp, p_exp are used only for 0 * 0, 0 * f, or f * 0 
391
    if (true_p_exp < -6176)
392
      p_exp = 0; // cannot be less than EXP_MIN
393
    else if (true_p_exp > 6111)
394
      p_exp = (UINT64) (6111 + 6176) << 49;     // cannot be more than EXP_MAX
395
    else
396
      p_exp = (UINT64) (true_p_exp + 6176) << 49;
397
 
398
    if ((C1.w[1] == 0x0 && C1.w[0] == 0x0) ||
399
        (C2.w[1] == 0x0 && C2.w[0] == 0x0)) {
400
      // x = 0 or y = 0
401
      // the result is 0
402
      res.w[1] = p_sign | p_exp;        // preferred exponent in [EXP_MIN, EXP_MAX]
403
      res.w[0] = 0x0;
404
      BID_SWAP128 (res);
405
      BID_RETURN (res)
406
    }   // else continue
407
  }
408
 
409
  BID_SWAP128 (x);
410
  BID_SWAP128 (y);
411
  BID_SWAP128 (z);
412
  // swap x and y - ensure that a NaN in x has 'higher precedence' than one in y
413
#if DECIMAL_CALL_BY_REFERENCE
414
  bid128_fma (&res, &y, &x, &z
415
              _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
416
              _EXC_INFO_ARG);
417
#else
418
  res = bid128_fma (y, x, z
419
                    _RND_MODE_ARG _EXC_FLAGS_ARG _EXC_MASKS_ARG
420
                    _EXC_INFO_ARG);
421
#endif
422
  BID_RETURN (res);
423
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.