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

Subversion Repositories openrisc

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

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
/*****************************************************************************
25
 *    BID64 remainder
26
 *****************************************************************************
27
 *
28
 *  Algorithm description:
29
 *
30
 *  if(exponent_x < exponent_y)
31
 *    scale coefficient_y so exponents are aligned
32
 *    perform coefficient divide (64-bit integer divide), unless
33
 *            coefficient_y is longer than 64 bits (clearly larger
34
 *                                               than coefficient_x)
35
 *  else  // exponent_x > exponent_y
36
 *     use a loop to scale coefficient_x to 18_digits, divide by
37
 *         coefficient_y (64-bit integer divide), calculate remainder
38
 *         as new_coefficient_x and repeat until final remainder is obtained
39
 *         (when new_exponent_x < exponent_y)
40
 *
41
 ****************************************************************************/
42
 
43
#include "bid_internal.h"
44
 
45
#define MAX_FORMAT_DIGITS     16
46
#define DECIMAL_EXPONENT_BIAS 398
47
#define MASK_BINARY_EXPONENT  0x7ff0000000000000ull
48
#define BINARY_EXPONENT_BIAS  0x3ff
49
#define UPPER_EXPON_LIMIT     51
50
 
51
#if DECIMAL_CALL_BY_REFERENCE
52
 
53
void
54
bid64_rem (UINT64 * pres, UINT64 * px,
55
           UINT64 *
56
           py _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
57
  UINT64 x, y;
58
#else
59
 
60
UINT64
61
bid64_rem (UINT64 x,
62
           UINT64 y _EXC_FLAGS_PARAM _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
63
#endif
64
  UINT128 CY;
65
  UINT64 sign_x, sign_y, coefficient_x, coefficient_y, res;
66
  UINT64 Q, R, R2, T, valid_y, valid_x;
67
  int_float tempx;
68
  int exponent_x, exponent_y, bin_expon, e_scale;
69
  int digits_x, diff_expon;
70
 
71
#if DECIMAL_CALL_BY_REFERENCE
72
  x = *px;
73
  y = *py;
74
#endif
75
 
76
  valid_y = unpack_BID64 (&sign_y, &exponent_y, &coefficient_y, y);
77
  valid_x = unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x);
78
 
79
  // unpack arguments, check for NaN or Infinity
80
  if (!valid_x) {
81
    // x is Inf. or NaN or 0
82
#ifdef SET_STATUS_FLAGS
83
    if ((y & SNAN_MASK64) == SNAN_MASK64)       // y is sNaN
84
      __set_status_flags (pfpsf, INVALID_EXCEPTION);
85
#endif
86
 
87
    // test if x is NaN
88
    if ((x & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
89
#ifdef SET_STATUS_FLAGS
90
      if (((x & SNAN_MASK64) == SNAN_MASK64))
91
        __set_status_flags (pfpsf, INVALID_EXCEPTION);
92
#endif
93
      res = coefficient_x & QUIET_MASK64;;
94
      BID_RETURN (res);
95
    }
96
    // x is Infinity?
97
    if ((x & 0x7800000000000000ull) == 0x7800000000000000ull) {
98
      if (((y & NAN_MASK64) != NAN_MASK64)) {
99
#ifdef SET_STATUS_FLAGS
100
        __set_status_flags (pfpsf, INVALID_EXCEPTION);
101
#endif
102
        // return NaN
103
        res = 0x7c00000000000000ull;
104
        BID_RETURN (res);
105
      }
106
    }
107
    // x is 0
108
    // return x if y != 0
109
    if (((y & 0x7800000000000000ull) < 0x7800000000000000ull) &&
110
        coefficient_y) {
111
      if ((y & 0x6000000000000000ull) == 0x6000000000000000ull)
112
        exponent_y = (y >> 51) & 0x3ff;
113
      else
114
        exponent_y = (y >> 53) & 0x3ff;
115
 
116
      if (exponent_y < exponent_x)
117
        exponent_x = exponent_y;
118
 
119
      x = exponent_x;
120
      x <<= 53;
121
 
122
      res = x | sign_x;
123
      BID_RETURN (res);
124
    }
125
 
126
  }
127
  if (!valid_y) {
128
    // y is Inf. or NaN
129
 
130
    // test if y is NaN
131
    if ((y & 0x7c00000000000000ull) == 0x7c00000000000000ull) {
132
#ifdef SET_STATUS_FLAGS
133
      if (((y & SNAN_MASK64) == SNAN_MASK64))
134
        __set_status_flags (pfpsf, INVALID_EXCEPTION);
135
#endif
136
      res = coefficient_y & QUIET_MASK64;;
137
      BID_RETURN (res);
138
    }
139
    // y is Infinity?
140
    if ((y & 0x7800000000000000ull) == 0x7800000000000000ull) {
141
      res = very_fast_get_BID64 (sign_x, exponent_x, coefficient_x);
142
      BID_RETURN (res);
143
    }
144
    // y is 0, return NaN
145
    {
146
#ifdef SET_STATUS_FLAGS
147
      __set_status_flags (pfpsf, INVALID_EXCEPTION);
148
#endif
149
      res = 0x7c00000000000000ull;
150
      BID_RETURN (res);
151
    }
152
  }
153
 
154
 
155
  diff_expon = exponent_x - exponent_y;
156
  if (diff_expon <= 0) {
157
    diff_expon = -diff_expon;
158
 
159
    if (diff_expon > 16) {
160
      // |x|<|y| in this case
161
      res = x;
162
      BID_RETURN (res);
163
    }
164
    // set exponent of y to exponent_x, scale coefficient_y
165
    T = power10_table_128[diff_expon].w[0];
166
    __mul_64x64_to_128 (CY, coefficient_y, T);
167
 
168
    if (CY.w[1] || CY.w[0] > (coefficient_x << 1)) {
169
      res = x;
170
      BID_RETURN (res);
171
    }
172
 
173
    Q = coefficient_x / CY.w[0];
174
    R = coefficient_x - Q * CY.w[0];
175
 
176
    R2 = R + R;
177
    if (R2 > CY.w[0] || (R2 == CY.w[0] && (Q & 1))) {
178
      R = CY.w[0] - R;
179
      sign_x ^= 0x8000000000000000ull;
180
    }
181
 
182
    res = very_fast_get_BID64 (sign_x, exponent_x, R);
183
    BID_RETURN (res);
184
  }
185
 
186
 
187
  while (diff_expon > 0) {
188
    // get number of digits in coeff_x
189
    tempx.d = (float) coefficient_x;
190
    bin_expon = ((tempx.i >> 23) & 0xff) - 0x7f;
191
    digits_x = estimate_decimal_digits[bin_expon];
192
    // will not use this test, dividend will have 18 or 19 digits
193
    //if(coefficient_x >= power10_table_128[digits_x].w[0])
194
    //      digits_x++;
195
 
196
    e_scale = 18 - digits_x;
197
    if (diff_expon >= e_scale) {
198
      diff_expon -= e_scale;
199
    } else {
200
      e_scale = diff_expon;
201
      diff_expon = 0;
202
    }
203
 
204
    // scale dividend to 18 or 19 digits
205
    coefficient_x *= power10_table_128[e_scale].w[0];
206
 
207
    // quotient
208
    Q = coefficient_x / coefficient_y;
209
    // remainder
210
    coefficient_x -= Q * coefficient_y;
211
 
212
    // check for remainder == 0
213
    if (!coefficient_x) {
214
      res = very_fast_get_BID64_small_mantissa (sign_x, exponent_y, 0);
215
      BID_RETURN (res);
216
    }
217
  }
218
 
219
  R2 = coefficient_x + coefficient_x;
220
  if (R2 > coefficient_y || (R2 == coefficient_y && (Q & 1))) {
221
    coefficient_x = coefficient_y - coefficient_x;
222
    sign_x ^= 0x8000000000000000ull;
223
  }
224
 
225
  res = very_fast_get_BID64 (sign_x, exponent_y, coefficient_x);
226
  BID_RETURN (res);
227
 
228
}

powered by: WebSVN 2.1.0

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