Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6515 serge 1
/* Copyright (C) 2007-2015 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
.  */
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
}