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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [libbid/] [bid32_to_bid128.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
#define BID_128RES
25
#include "bid_internal.h"
26
 
27
/*
28
 * Takes a BID32 as input and converts it to a BID128 and returns it.
29
 */
30
TYPE0_FUNCTION_ARGTYPE1_NORND (UINT128, bid32_to_bid128, UINT32, x)
31
 
32
     UINT128 new_coeff, res;
33
     UINT32 sign_x;
34
     int exponent_x;
35
     UINT32 coefficient_x;
36
 
37
if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) {
38
if (((x) & 0x78000000) == 0x78000000) {
39
#ifdef SET_STATUS_FLAGS
40
  if (((x) & 0x7e000000) == 0x7e000000) // sNaN
41
    __set_status_flags (pfpsf, INVALID_EXCEPTION);
42
#endif
43
  res.w[0] = (coefficient_x & 0x000fffff);
44
  __mul_64x128_low (res, res.w[0], power10_table_128[27]);
45
  res.w[1] |=
46
    ((((UINT64) coefficient_x) << 32) & 0xfc00000000000000ull);
47
 
48
  BID_RETURN (res);
49
}
50
}
51
 
52
new_coeff.w[0] = coefficient_x;
53
new_coeff.w[1] = 0;
54
get_BID128_very_fast (&res, ((UINT64) sign_x) << 32,
55
                      exponent_x + DECIMAL_EXPONENT_BIAS_128 -
56
                      DECIMAL_EXPONENT_BIAS_32, new_coeff);
57
BID_RETURN (res);
58
}       // convert_bid32_to_bid128
59
 
60
 
61
/*
62
 * Takes a BID128 as input and converts it to a BID32 and returns it.
63
 */
64
#if DECIMAL_CALL_BY_REFERENCE
65
 
66
void
67
bid128_to_bid32 (UINT32 * pres,
68
                 UINT128 *
69
                 px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
70
                 _EXC_INFO_PARAM) {
71
  UINT128 x = *px;
72
#else
73
 
74
UINT32
75
bid128_to_bid32 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
76
                 _EXC_MASKS_PARAM _EXC_INFO_PARAM) {
77
#endif
78
  UINT128 CX, T128, TP128, Qh, Ql, Qh1, Stemp, Tmp, Tmp1, CX1;
79
  UINT64 sign_x, carry, cy;
80
  SINT64 D;
81
  UINT32 res;
82
  int_float f64, fx;
83
  int exponent_x, extra_digits, amount, bin_expon_cx, uf_check = 0;
84
  unsigned rmode, status;
85
 
86
#if DECIMAL_CALL_BY_REFERENCE
87
#if !DECIMAL_GLOBAL_ROUNDING
88
  _IDEC_round rnd_mode = *prnd_mode;
89
#endif
90
#endif
91
 
92
  BID_SWAP128 (x);
93
  // unpack arguments, check for NaN or Infinity or 0
94
  if (!unpack_BID128_value (&sign_x, &exponent_x, &CX, x)) {
95
    if (((x.w[1]) & 0x7800000000000000ull) == 0x7800000000000000ull) {
96
      Tmp.w[1] = (CX.w[1] & 0x00003fffffffffffull);
97
      Tmp.w[0] = CX.w[0];
98
      TP128 = reciprocals10_128[27];
99
      __mul_128x128_full (Qh, Ql, Tmp, TP128);
100
      amount = recip_scale[27] - 64;
101
      res = ((CX.w[1] >> 32) & 0xfc000000) | (Qh.w[1] >> amount);
102
#ifdef SET_STATUS_FLAGS
103
      if ((x.w[1] & SNAN_MASK64) == SNAN_MASK64)        // sNaN
104
        __set_status_flags (pfpsf, INVALID_EXCEPTION);
105
#endif
106
      BID_RETURN_VAL (res);
107
    }
108
    // x is 0
109
    exponent_x =
110
      exponent_x - DECIMAL_EXPONENT_BIAS_128 + DECIMAL_EXPONENT_BIAS_32;
111
    if (exponent_x < 0)
112
      exponent_x = 0;
113
    if (exponent_x > DECIMAL_MAX_EXPON_32)
114
      exponent_x = DECIMAL_MAX_EXPON_32;
115
    res = (sign_x >> 32) | (exponent_x << 23);
116
    BID_RETURN_VAL (res);
117
 
118
  }
119
 
120
  if (CX.w[1] || (CX.w[0] >= 10000000)) {
121
    // find number of digits in coefficient
122
    // 2^64
123
    f64.i = 0x5f800000;
124
    // fx ~ CX
125
    fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
126
    bin_expon_cx = ((fx.i >> 23) & 0xff) - 0x7f;
127
    extra_digits = estimate_decimal_digits[bin_expon_cx] - 7;
128
    // scale = 38-estimate_decimal_digits[bin_expon_cx];
129
    D = CX.w[1] - power10_index_binexp_128[bin_expon_cx].w[1];
130
    if (D > 0
131
        || (!D
132
            && CX.w[0] >= power10_index_binexp_128[bin_expon_cx].w[0]))
133
      extra_digits++;
134
 
135
    exponent_x += extra_digits;
136
 
137
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
138
#ifndef IEEE_ROUND_NEAREST
139
    rmode = rnd_mode;
140
    if (sign_x && (unsigned) (rmode - 1) < 2)
141
      rmode = 3 - rmode;
142
#else
143
    rmode = 0;
144
#endif
145
#else
146
    rmode = 0;
147
#endif
148
    if (exponent_x <
149
        DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS_32) {
150
      uf_check = 1;
151
      if (-extra_digits + exponent_x - DECIMAL_EXPONENT_BIAS_128 +
152
          DECIMAL_EXPONENT_BIAS_32 + 35 >= 0) {
153
        if (exponent_x ==
154
            DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS_32 - 1) {
155
          T128 = round_const_table_128[rmode][extra_digits];
156
          __add_carry_out (CX1.w[0], carry, T128.w[0], CX.w[0]);
157
          CX1.w[1] = CX.w[1] + T128.w[1] + carry;
158
          if (__unsigned_compare_ge_128
159
              (CX1, power10_table_128[extra_digits + 7]))
160
            uf_check = 0;
161
        }
162
        extra_digits =
163
          extra_digits + DECIMAL_EXPONENT_BIAS_128 -
164
          DECIMAL_EXPONENT_BIAS_32 - exponent_x;
165
        exponent_x =
166
          DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS_32;
167
      } else
168
        rmode = ROUNDING_TO_ZERO;
169
    }
170
 
171
    T128 = round_const_table_128[rmode][extra_digits];
172
    __add_carry_out (CX.w[0], carry, T128.w[0], CX.w[0]);
173
    CX.w[1] = CX.w[1] + T128.w[1] + carry;
174
 
175
    TP128 = reciprocals10_128[extra_digits];
176
    __mul_128x128_full (Qh, Ql, CX, TP128);
177
    amount = recip_scale[extra_digits];
178
 
179
    if (amount >= 64) {
180
      CX.w[0] = Qh.w[1] >> (amount - 64);
181
      CX.w[1] = 0;
182
    } else {
183
      __shr_128 (CX, Qh, amount);
184
    }
185
 
186
#ifndef IEEE_ROUND_NEAREST_TIES_AWAY
187
#ifndef IEEE_ROUND_NEAREST
188
    if (!(rnd_mode))
189
#endif
190
      if (CX.w[0] & 1) {
191
        // check whether fractional part of initial_P/10^ed1 is exactly .5
192
 
193
        // get remainder
194
        __shl_128_long (Qh1, Qh, (128 - amount));
195
 
196
        if (!Qh1.w[1] && !Qh1.w[0]
197
            && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
198
                || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
199
                    && Ql.w[0] < reciprocals10_128[extra_digits].w[0]))) {
200
          CX.w[0]--;
201
        }
202
      }
203
#endif
204
 
205
 
206
    {
207
      status = INEXACT_EXCEPTION;
208
      // get remainder
209
      __shl_128_long (Qh1, Qh, (128 - amount));
210
 
211
      switch (rmode) {
212
      case ROUNDING_TO_NEAREST:
213
      case ROUNDING_TIES_AWAY:
214
        // test whether fractional part is 0
215
        if (Qh1.w[1] == 0x8000000000000000ull && (!Qh1.w[0])
216
            && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
217
                || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
218
                    && Ql.w[0] < reciprocals10_128[extra_digits].w[0])))
219
          status = EXACT_STATUS;
220
        break;
221
      case ROUNDING_DOWN:
222
      case ROUNDING_TO_ZERO:
223
        if ((!Qh1.w[1]) && (!Qh1.w[0])
224
            && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
225
                || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
226
                    && Ql.w[0] < reciprocals10_128[extra_digits].w[0])))
227
          status = EXACT_STATUS;
228
        break;
229
      default:
230
        // round up
231
        __add_carry_out (Stemp.w[0], cy, Ql.w[0],
232
                         reciprocals10_128[extra_digits].w[0]);
233
        __add_carry_in_out (Stemp.w[1], carry, Ql.w[1],
234
                            reciprocals10_128[extra_digits].w[1], cy);
235
        __shr_128_long (Qh, Qh1, (128 - amount));
236
        Tmp.w[0] = 1;
237
        Tmp.w[1] = 0;
238
        __shl_128_long (Tmp1, Tmp, amount);
239
        Qh.w[0] += carry;
240
        if (Qh.w[0] < carry)
241
          Qh.w[1]++;
242
        if (__unsigned_compare_ge_128 (Qh, Tmp1))
243
          status = EXACT_STATUS;
244
      }
245
 
246
      if (status != EXACT_STATUS) {
247
        if (uf_check) {
248
          status |= UNDERFLOW_EXCEPTION;
249
        }
250
#ifdef SET_STATUS_FLAGS
251
        __set_status_flags (pfpsf, status);
252
#endif
253
      }
254
    }
255
 
256
  }
257
 
258
  res =
259
    get_BID32 ((UINT32) (sign_x >> 32),
260
               exponent_x - DECIMAL_EXPONENT_BIAS_128 +
261
               DECIMAL_EXPONENT_BIAS_32, CX.w[0], rnd_mode, pfpsf);
262
  BID_RETURN_VAL (res);
263
 
264
}

powered by: WebSVN 2.1.0

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