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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [libdecnumber/] [decUtility.c] - Blame information for rev 280

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

Line No. Rev Author Line
1 38 julius
/* Utility functions for decimal floating point support via decNumber.
2
   Copyright (C) 2005 Free Software Foundation, Inc.
3
   Contributed by IBM Corporation.  Author Mike Cowlishaw.
4
 
5
   This file is part of GCC.
6
 
7
   GCC is free software; you can redistribute it and/or modify it under
8
   the terms of the GNU General Public License as published by the Free
9
   Software Foundation; either version 2, or (at your option) any later
10
   version.
11
 
12
   In addition to the permissions in the GNU General Public License,
13
   the Free Software Foundation gives you unlimited permission to link
14
   the compiled version of this file into combinations with other
15
   programs, and to distribute those combinations without any
16
   restriction coming from the use of this file.  (The General Public
17
   License restrictions do apply in other respects; for example, they
18
   cover modification of the file, and distribution when not linked
19
   into a combine executable.)
20
 
21
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
23
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
   for more details.
25
 
26
   You should have received a copy of the GNU General Public License
27
   along with GCC; see the file COPYING.  If not, write to the Free
28
   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29
   02110-1301, USA.  */
30
 
31
#include "config.h"
32
#include "decNumber.h"          /* base number library */
33
#include "decNumberLocal.h"     /* decNumber local types, etc. */
34
#include "decUtility.h"         /* utility routines */
35
 
36
/* ================================================================== */
37
/* Shared utility routines                                            */
38
/* ================================================================== */
39
 
40
/* define and include the conversion tables to use */
41
#define DEC_BIN2DPD 1           /* used for all sizes */
42
#if DECDPUN==3
43
#define DEC_DPD2BIN 1
44
#else
45
#define DEC_DPD2BCD 1
46
#endif
47
#include "decDPD.h"             /* lookup tables */
48
 
49
/* The maximum number of decNumberUnits we need for a working copy of */
50
/* the units array is the ceiling of digits/DECDPUN, where digits is */
51
/* the maximum number of digits in any of the formats for which this */
52
/* is used.  We do not want to include decimal128.h, so, as a very */
53
/* special case, that number is defined here. */
54
#define DECMAX754   34
55
#define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
56
 
57
/* ------------------------------------------------------------------ */
58
/* decDensePackCoeff -- densely pack coefficient into DPD form        */
59
/*                                                                    */
60
/*   dn is the source number (assumed valid, max DECMAX754 digits)    */
61
/*   bytes is the target's byte array                                 */
62
/*   len is length of target format's byte array                      */
63
/*   shift is the number of 0 digits to add on the right (normally 0) */
64
/*                                                                    */
65
/* The coefficient must be known small enough to fit, and is filled   */
66
/* in from the right (least significant first).  Note that the full   */
67
/* coefficient is copied, including the leading 'odd' digit.  This    */
68
/* digit is retrieved and packed into the combination field by the    */
69
/* caller.                                                            */
70
/*                                                                    */
71
/* shift is used for 'fold-down' padding.                             */
72
/*                                                                    */
73
/* No error is possible.                                              */
74
/* ------------------------------------------------------------------ */
75
void
76
decDensePackCoeff (const decNumber * dn, uByte * bytes, Int len, Int shift)
77
{
78
  Int cut;                      /* work */
79
  Int n;                        /* output bunch counter */
80
  Int digits = dn->digits;      /* digit countdown */
81
  uInt dpd;                     /* densely packed decimal value */
82
  uInt bin;                     /* binary value 0-999 */
83
  uByte *bout;                  /* -> current output byte */
84
  const Unit *inu = dn->lsu;    /* -> current input unit */
85
  Unit uar[DECMAXUNITS];        /* working copy of units, iff shifted */
86
#if DECDPUN!=3                  /* not fast path */
87
  Unit in;                      /* current input unit */
88
#endif
89
 
90
  if (shift != 0)
91
    {                           /* shift towards most significant required */
92
      /* shift the units array to the left by pad digits and copy */
93
      /* [this code is a special case of decShiftToMost, which could */
94
      /* be used instead if exposed and the array were copied first] */
95
      Unit *target, *first;     /* work */
96
      const Unit *source;       /* work */
97
      uInt next = 0;             /* work */
98
 
99
      source = dn->lsu + D2U (digits) - 1;      /* where msu comes from */
100
      first = uar + D2U (digits + shift) - 1;   /* where msu will end up */
101
      target = uar + D2U (digits) - 1 + D2U (shift);    /* where upper part of first cut goes */
102
 
103
      cut = (DECDPUN - shift % DECDPUN) % DECDPUN;
104
      for (; source >= dn->lsu; source--, target--)
105
        {
106
          /* split the source Unit and accumulate remainder for next */
107
          uInt rem = *source % powers[cut];
108
          next += *source / powers[cut];
109
          if (target <= first)
110
            *target = (Unit) next;      /* write to target iff valid */
111
          next = rem * powers[DECDPUN - cut];   /* save remainder for next Unit */
112
        }
113
      /* propagate remainder to one below and clear the rest */
114
      for (; target >= uar; target--)
115
        {
116
          *target = (Unit) next;
117
          next = 0;
118
        }
119
      digits += shift;          /* add count (shift) of zeros added */
120
      inu = uar;                /* use units in working array */
121
    }
122
 
123
  /* densely pack the coefficient into the byte array, starting from
124
     the right (optionally padded) */
125
  bout = &bytes[len - 1];       /* rightmost result byte for phase */
126
 
127
#if DECDPUN!=3                  /* not fast path */
128
  in = *inu;                    /* prime */
129
  cut = 0;                       /* at lowest digit */
130
  bin = 0;                       /* [keep compiler quiet] */
131
#endif
132
 
133
  for (n = 0; digits > 0; n++)
134
    {                           /* each output bunch */
135
#if DECDPUN==3                  /* fast path, 3-at-a-time */
136
      bin = *inu;               /* 3 ready for convert */
137
      digits -= 3;              /* [may go negative] */
138
      inu++;                    /* may need another */
139
 
140
#else /* must collect digit-by-digit */
141
      Unit dig;                 /* current digit */
142
      Int j;                    /* digit-in-bunch count */
143
      for (j = 0; j < 3; j++)
144
        {
145
#if DECDPUN<=4
146
          Unit temp = (Unit) ((uInt) (in * 6554) >> 16);
147
          dig = (Unit) (in - X10 (temp));
148
          in = temp;
149
#else
150
          dig = in % 10;
151
          in = in / 10;
152
#endif
153
 
154
          if (j == 0)
155
            bin = dig;
156
          else if (j == 1)
157
            bin += X10 (dig);
158
          else                  /* j==2 */
159
            bin += X100 (dig);
160
 
161
          digits--;
162
          if (digits == 0)
163
            break;              /* [also protects *inu below] */
164
          cut++;
165
          if (cut == DECDPUN)
166
            {
167
              inu++;
168
              in = *inu;
169
              cut = 0;
170
            }
171
        }
172
#endif
173
      /* here we have 3 digits in bin, or have used all input digits */
174
 
175
      dpd = BIN2DPD[bin];
176
 
177
      /* write bunch (bcd) to byte array */
178
      switch (n & 0x03)
179
        {                       /* phase 0-3 */
180
        case 0:
181
          *bout = (uByte) dpd;  /* [top 2 bits truncated] */
182
          bout--;
183
          *bout = (uByte) (dpd >> 8);
184
          break;
185
        case 1:
186
          *bout |= (uByte) (dpd << 2);
187
          bout--;
188
          *bout = (uByte) (dpd >> 6);
189
          break;
190
        case 2:
191
          *bout |= (uByte) (dpd << 4);
192
          bout--;
193
          *bout = (uByte) (dpd >> 4);
194
          break;
195
        case 3:
196
          *bout |= (uByte) (dpd << 6);
197
          bout--;
198
          *bout = (uByte) (dpd >> 2);
199
          bout--;
200
          break;
201
        }                       /* switch */
202
    }                           /* n bunches */
203
  return;
204
}
205
 
206
/* ------------------------------------------------------------------ */
207
/* decDenseUnpackCoeff -- unpack a format's coefficient               */
208
/*                                                                    */
209
/*   byte is the source's byte array                                  */
210
/*   len is length of the source's byte array                         */
211
/*   dn is the target number, with 7, 16, or 34-digit space.          */
212
/*   bunches is the count of DPD groups in the decNumber (2, 5, or 11)*/
213
/*   odd is 1 if there is a non-zero leading 10-bit group containing  */
214
/*     a single digit, 0 otherwise                                    */
215
/*                                                                    */
216
/* (This routine works on a copy of the number, if necessary, where   */
217
/* an extra 10-bit group is prefixed to the coefficient continuation  */
218
/* to hold the most significant digit if the latter is non-0.)        */
219
/*                                                                    */
220
/* dn->digits is set, but not the sign or exponent.                   */
221
/* No error is possible [the redundant 888 codes are allowed].        */
222
/* ------------------------------------------------------------------ */
223
void
224
decDenseUnpackCoeff (const uByte * bytes, Int len, decNumber * dn,
225
                     Int bunches, Int odd)
226
{
227
  uInt dpd = 0;                  /* collector for 10 bits */
228
  Int n;                        /* counter */
229
  const uByte *bin;             /* -> current input byte */
230
  Unit *uout = dn->lsu;         /* -> current output unit */
231
  Unit out = 0;                  /* accumulator */
232
  Int cut = 0;                   /* power of ten in current unit */
233
  Unit *last = uout;            /* will be unit containing msd */
234
#if DECDPUN!=3
235
  uInt bcd;                     /* BCD result */
236
  uInt nibble;                  /* work */
237
#endif
238
 
239
  /* Expand the densely-packed integer, right to left */
240
  bin = &bytes[len - 1];        /* next input byte to use */
241
  for (n = 0; n < bunches + odd; n++)
242
    {                           /* N bunches of 10 bits */
243
      /* assemble the 10 bits */
244
      switch (n & 0x03)
245
        {                       /* phase 0-3 */
246
        case 0:
247
          dpd = *bin;
248
          bin--;
249
          dpd |= (*bin & 0x03) << 8;
250
          break;
251
        case 1:
252
          dpd = (unsigned) *bin >> 2;
253
          bin--;
254
          dpd |= (*bin & 0x0F) << 6;
255
          break;
256
        case 2:
257
          dpd = (unsigned) *bin >> 4;
258
          bin--;
259
          dpd |= (*bin & 0x3F) << 4;
260
          break;
261
        case 3:
262
          dpd = (unsigned) *bin >> 6;
263
          bin--;
264
          dpd |= (*bin) << 2;
265
          bin--;
266
          break;
267
        }                       /*switch */
268
 
269
#if DECDPUN==3
270
      if (dpd == 0)
271
        *uout = 0;
272
      else
273
        {
274
          *uout = DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */
275
          last = uout;          /* record most significant unit */
276
        }
277
      uout++;
278
 
279
#else /* DECDPUN!=3 */
280
      if (dpd == 0)
281
        {                       /* fastpath [e.g., leading zeros] */
282
          cut += 3;
283
          for (; cut >= DECDPUN;)
284
            {
285
              cut -= DECDPUN;
286
              *uout = out;
287
              uout++;
288
              out = 0;
289
            }
290
          continue;
291
        }
292
      bcd = DPD2BCD[dpd];       /* convert 10 bits to 12 bits BCD */
293
      /* now split the 3 BCD nibbles into bytes, and accumulate into units */
294
      /* If this is the last bunch and it is an odd one, we only have one */
295
      /* nibble to handle [extras could overflow a Unit] */
296
      nibble = bcd & 0x000f;
297
      if (nibble)
298
        {
299
          last = uout;
300
          out = (Unit) (out + nibble * powers[cut]);
301
        }
302
      cut++;
303
      if (cut == DECDPUN)
304
        {
305
          *uout = out;
306
          uout++;
307
          cut = 0;
308
          out = 0;
309
        }
310
      if (n < bunches)
311
        {
312
          nibble = bcd & 0x00f0;
313
          if (nibble)
314
            {
315
              nibble >>= 4;
316
              last = uout;
317
              out = (Unit) (out + nibble * powers[cut]);
318
            }
319
          cut++;
320
          if (cut == DECDPUN)
321
            {
322
              *uout = out;
323
              uout++;
324
              cut = 0;
325
              out = 0;
326
            }
327
          nibble = bcd & 0x0f00;
328
          if (nibble)
329
            {
330
              nibble >>= 8;
331
              last = uout;
332
              out = (Unit) (out + nibble * powers[cut]);
333
            }
334
          cut++;
335
          if (cut == DECDPUN)
336
            {
337
              *uout = out;
338
              uout++;
339
              cut = 0;
340
              out = 0;
341
            }
342
        }
343
#endif
344
    }                           /* n */
345
  if (cut != 0)
346
    *uout = out;                /* write out final unit */
347
 
348
  /* here, last points to the most significant unit with digits */
349
  /* we need to inspect it to get final digits count */
350
  dn->digits = (last - dn->lsu) * DECDPUN;      /* floor of digits */
351
  for (cut = 0; cut < DECDPUN; cut++)
352
    {
353
      if (*last < powers[cut])
354
        break;
355
      dn->digits++;
356
    }
357
  if (dn->digits == 0)
358
    dn->digits++;               /* zero has one digit */
359
  return;
360
}

powered by: WebSVN 2.1.0

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