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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [libbid/] [bid_from_int.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
#include "bid_internal.h"
25
 
26
/*****************************************************************************
27
 *  BID64_round_integral_exact
28
 ****************************************************************************/
29
 
30
#if DECIMAL_CALL_BY_REFERENCE
31
void
32
bid64_from_int32 (UINT64 * pres,
33
                  int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
34
  int x = *px;
35
#else
36
UINT64
37
bid64_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
38
#endif
39
  UINT64 res;
40
 
41
  // if integer is negative, put the absolute value
42
  // in the lowest 32bits of the result
43
  if ((x & SIGNMASK32) == SIGNMASK32) {
44
    // negative int32
45
    x = ~x + 1; // 2's complement of x
46
    res = (unsigned int) x | 0xb1c0000000000000ull;
47
    // (exp << 53)) = biased exp. is 0
48
  } else {      // positive int32
49
    res = x | 0x31c0000000000000ull;    // (exp << 53)) = biased exp. is 0
50
  }
51
  BID_RETURN (res);
52
}
53
 
54
#if DECIMAL_CALL_BY_REFERENCE
55
void
56
bid64_from_uint32 (UINT64 * pres, unsigned int *px
57
                   _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
58
  unsigned int x = *px;
59
#else
60
UINT64
61
bid64_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
62
#endif
63
  UINT64 res;
64
 
65
  res = x | 0x31c0000000000000ull;      // (exp << 53)) = biased exp. is 0
66
  BID_RETURN (res);
67
}
68
 
69
#if DECIMAL_CALL_BY_REFERENCE
70
void
71
bid64_from_int64 (UINT64 * pres, SINT64 * px
72
                  _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
73
                  _EXC_INFO_PARAM) {
74
  SINT64 x = *px;
75
#if !DECIMAL_GLOBAL_ROUNDING
76
  unsigned int rnd_mode = *prnd_mode;
77
#endif
78
#else
79
UINT64
80
bid64_from_int64 (SINT64 x
81
                  _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
82
                  _EXC_INFO_PARAM) {
83
#endif
84
 
85
  UINT64 res;
86
  UINT64 x_sign, C;
87
  unsigned int q, ind;
88
  int incr_exp = 0;
89
  int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
90
  int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
91
 
92
  x_sign = x & 0x8000000000000000ull;
93
  // if the integer is negative, use the absolute value
94
  if (x_sign)
95
    C = ~((UINT64) x) + 1;
96
  else
97
    C = x;
98
  if (C <= BID64_SIG_MAX) {     // |C| <= 10^16-1 and the result is exact
99
    if (C < 0x0020000000000000ull) {    // C < 2^53
100
      res = x_sign | 0x31c0000000000000ull | C;
101
    } else {    // C >= 2^53
102
      res =
103
        x_sign | 0x6c70000000000000ull | (C & 0x0007ffffffffffffull);
104
    }
105
  } else {      // |C| >= 10^16 and the result may be inexact 
106
    // the smallest |C| is 10^16 which has 17 decimal digits
107
    // the largest |C| is 0x8000000000000000 = 9223372036854775808 w/ 19 digits
108
    if (C < 0x16345785d8a0000ull) {     // x < 10^17 
109
      q = 17;
110
      ind = 1;  // number of digits to remove for q = 17
111
    } else if (C < 0xde0b6b3a7640000ull) {      // C < 10^18
112
      q = 18;
113
      ind = 2;  // number of digits to remove for q = 18 
114
    } else {    // C < 10^19
115
      q = 19;
116
      ind = 3;  // number of digits to remove for q = 19
117
    }
118
    // overflow and underflow are not possible
119
    // Note: performace can be improved by inlining this call
120
    round64_2_18 (      // will work for 19 digits too if C fits in 64 bits
121
                   q, ind, C, &res, &incr_exp,
122
                   &is_midpoint_lt_even, &is_midpoint_gt_even,
123
                   &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
124
    if (incr_exp)
125
      ind++;
126
    // set the inexact flag
127
    if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
128
        is_midpoint_lt_even || is_midpoint_gt_even)
129
      *pfpsf |= INEXACT_EXCEPTION;
130
    // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
131
    if (rnd_mode != ROUNDING_TO_NEAREST) {
132
      if ((!x_sign
133
           && ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint)
134
               ||
135
               ((rnd_mode == ROUNDING_TIES_AWAY
136
                 || rnd_mode == ROUNDING_UP) && is_midpoint_gt_even)))
137
          || (x_sign
138
              && ((rnd_mode == ROUNDING_DOWN && is_inexact_lt_midpoint)
139
                  ||
140
                  ((rnd_mode == ROUNDING_TIES_AWAY
141
                    || rnd_mode == ROUNDING_DOWN)
142
                   && is_midpoint_gt_even)))) {
143
        res = res + 1;
144
        if (res == 0x002386f26fc10000ull) {     // res = 10^16 => rounding overflow
145
          res = 0x00038d7ea4c68000ull;  // 10^15
146
          ind = ind + 1;
147
        }
148
      } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
149
                 ((x_sign && (rnd_mode == ROUNDING_UP ||
150
                              rnd_mode == ROUNDING_TO_ZERO)) ||
151
                  (!x_sign && (rnd_mode == ROUNDING_DOWN ||
152
                               rnd_mode == ROUNDING_TO_ZERO)))) {
153
        res = res - 1;
154
        // check if we crossed into the lower decade
155
        if (res == 0x00038d7ea4c67fffull) {     // 10^15 - 1
156
          res = 0x002386f26fc0ffffull;  // 10^16 - 1
157
          ind = ind - 1;
158
        }
159
      } else {
160
        ;       // exact, the result is already correct
161
      }
162
    }
163
    if (res < 0x0020000000000000ull) {  // res < 2^53
164
      res = x_sign | (((UINT64) ind + 398) << 53) | res;
165
    } else {    // res >= 2^53 
166
      res =
167
        x_sign | 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
168
        (res & 0x0007ffffffffffffull);
169
    }
170
  }
171
  BID_RETURN (res);
172
}
173
 
174
#if DECIMAL_CALL_BY_REFERENCE
175
void
176
bid64_from_uint64 (UINT64 * pres, UINT64 * px
177
                   _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
178
                   _EXC_INFO_PARAM) {
179
  UINT64 x = *px;
180
#if !DECIMAL_GLOBAL_ROUNDING
181
  unsigned int rnd_mode = *prnd_mode;
182
#endif
183
#else
184
UINT64
185
bid64_from_uint64 (UINT64 x
186
                   _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
187
                   _EXC_INFO_PARAM) {
188
#endif
189
 
190
  UINT64 res;
191
  UINT128 x128, res128;
192
  unsigned int q, ind;
193
  int incr_exp = 0;
194
  int is_midpoint_lt_even = 0, is_midpoint_gt_even = 0;
195
  int is_inexact_lt_midpoint = 0, is_inexact_gt_midpoint = 0;
196
 
197
  if (x <= BID64_SIG_MAX) {     // x <= 10^16-1 and the result is exact
198
    if (x < 0x0020000000000000ull) {    // x < 2^53
199
      res = 0x31c0000000000000ull | x;
200
    } else {    // x >= 2^53
201
      res = 0x6c70000000000000ull | (x & 0x0007ffffffffffffull);
202
    }
203
  } else {      // x >= 10^16 and the result may be inexact 
204
    // the smallest x is 10^16 which has 17 decimal digits
205
    // the largest x is 0xffffffffffffffff = 18446744073709551615 w/ 20 digits
206
    if (x < 0x16345785d8a0000ull) {     // x < 10^17 
207
      q = 17;
208
      ind = 1;  // number of digits to remove for q = 17
209
    } else if (x < 0xde0b6b3a7640000ull) {      // x < 10^18
210
      q = 18;
211
      ind = 2;  // number of digits to remove for q = 18 
212
    } else if (x < 0x8ac7230489e80000ull) {     // x < 10^19
213
      q = 19;
214
      ind = 3;  // number of digits to remove for q = 19
215
    } else {    // x < 10^20
216
      q = 20;
217
      ind = 4;  // number of digits to remove for q = 20
218
    }
219
    // overflow and underflow are not possible
220
    // Note: performace can be improved by inlining this call
221
    if (q <= 19) {
222
      round64_2_18 (    // will work for 20 digits too if x fits in 64 bits
223
                     q, ind, x, &res, &incr_exp,
224
                     &is_midpoint_lt_even, &is_midpoint_gt_even,
225
                     &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
226
    } else {    // q = 20
227
      x128.w[1] = 0x0;
228
      x128.w[0] = x;
229
      round128_19_38 (q, ind, x128, &res128, &incr_exp,
230
                      &is_midpoint_lt_even, &is_midpoint_gt_even,
231
                      &is_inexact_lt_midpoint, &is_inexact_gt_midpoint);
232
      res = res128.w[0]; // res.w[1] is 0
233
    }
234
    if (incr_exp)
235
      ind++;
236
    // set the inexact flag
237
    if (is_inexact_lt_midpoint || is_inexact_gt_midpoint ||
238
        is_midpoint_lt_even || is_midpoint_gt_even)
239
      *pfpsf |= INEXACT_EXCEPTION;
240
    // general correction from RN to RA, RM, RP, RZ; result uses ind for exp
241
    if (rnd_mode != ROUNDING_TO_NEAREST) {
242
      if ((rnd_mode == ROUNDING_UP && is_inexact_lt_midpoint) ||
243
          ((rnd_mode == ROUNDING_TIES_AWAY || rnd_mode == ROUNDING_UP)
244
           && is_midpoint_gt_even)) {
245
        res = res + 1;
246
        if (res == 0x002386f26fc10000ull) {     // res = 10^16 => rounding overflow
247
          res = 0x00038d7ea4c68000ull;  // 10^15
248
          ind = ind + 1;
249
        }
250
      } else if ((is_midpoint_lt_even || is_inexact_gt_midpoint) &&
251
                 (rnd_mode == ROUNDING_DOWN ||
252
                  rnd_mode == ROUNDING_TO_ZERO)) {
253
        res = res - 1;
254
        // check if we crossed into the lower decade
255
        if (res == 0x00038d7ea4c67fffull) {     // 10^15 - 1
256
          res = 0x002386f26fc0ffffull;  // 10^16 - 1
257
          ind = ind - 1;
258
        }
259
      } else {
260
        ;       // exact, the result is already correct
261
      }
262
    }
263
    if (res < 0x0020000000000000ull) {  // res < 2^53
264
      res = (((UINT64) ind + 398) << 53) | res;
265
    } else {    // res >= 2^53 
266
      res = 0x6000000000000000ull | (((UINT64) ind + 398) << 51) |
267
        (res & 0x0007ffffffffffffull);
268
    }
269
  }
270
  BID_RETURN (res);
271
}
272
 
273
#if DECIMAL_CALL_BY_REFERENCE
274
void
275
bid128_from_int32 (UINT128 * pres,
276
                   int *px _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
277
  int x = *px;
278
#else
279
UINT128
280
bid128_from_int32 (int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
281
#endif
282
  UINT128 res;
283
 
284
  // if integer is negative, use the absolute value
285
  if ((x & SIGNMASK32) == SIGNMASK32) {
286
    res.w[HIGH_128W] = 0xb040000000000000ull;
287
    res.w[LOW_128W] = ~((unsigned int) x) + 1;  // 2's complement of x
288
  } else {
289
    res.w[HIGH_128W] = 0x3040000000000000ull;
290
    res.w[LOW_128W] = (unsigned int) x;
291
  }
292
  BID_RETURN (res);
293
}
294
 
295
#if DECIMAL_CALL_BY_REFERENCE
296
void
297
bid128_from_uint32 (UINT128 * pres, unsigned int *px
298
                    _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
299
  unsigned int x = *px;
300
#else
301
UINT128
302
bid128_from_uint32 (unsigned int x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
303
#endif
304
  UINT128 res;
305
 
306
  res.w[HIGH_128W] = 0x3040000000000000ull;
307
  res.w[LOW_128W] = x;
308
  BID_RETURN (res);
309
}
310
 
311
#if DECIMAL_CALL_BY_REFERENCE
312
void
313
bid128_from_int64 (UINT128 * pres, SINT64 * px
314
                   _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
315
  SINT64 x = *px;
316
#else
317
UINT128
318
bid128_from_int64 (SINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
319
#endif
320
 
321
  UINT128 res;
322
 
323
  // if integer is negative, use the absolute value
324
  if ((x & SIGNMASK64) == SIGNMASK64) {
325
    res.w[HIGH_128W] = 0xb040000000000000ull;
326
    res.w[LOW_128W] = ~x + 1;   // 2's complement of x
327
  } else {
328
    res.w[HIGH_128W] = 0x3040000000000000ull;
329
    res.w[LOW_128W] = x;
330
  }
331
  BID_RETURN (res);
332
}
333
 
334
#if DECIMAL_CALL_BY_REFERENCE
335
void
336
bid128_from_uint64 (UINT128 * pres, UINT64 * px
337
                    _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
338
  UINT64 x = *px;
339
#else
340
UINT128
341
bid128_from_uint64 (UINT64 x _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
342
#endif
343
 
344
  UINT128 res;
345
 
346
  res.w[HIGH_128W] = 0x3040000000000000ull;
347
  res.w[LOW_128W] = x;
348
  BID_RETURN (res);
349
}

powered by: WebSVN 2.1.0

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