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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [fixed-value.c] - Blame information for rev 859

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

Line No. Rev Author Line
1 280 jeremybenn
/* Fixed-point arithmetic support.
2
   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify it under
7
the terms of the GNU General Public License as published by the Free
8
Software Foundation; either version 3, or (at your option) any later
9
version.
10
 
11
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING3.  If not see
18
<http://www.gnu.org/licenses/>.  */
19
 
20
#include "config.h"
21
#include "system.h"
22
#include "coretypes.h"
23
#include "tm.h"
24
#include "tree.h"
25
#include "toplev.h"
26
#include "fixed-value.h"
27
 
28
/* Compare two fixed objects for bitwise identity.  */
29
 
30
bool
31
fixed_identical (const FIXED_VALUE_TYPE *a, const FIXED_VALUE_TYPE *b)
32
{
33
  return (a->mode == b->mode
34
          && a->data.high == b->data.high
35
          && a->data.low == b->data.low);
36
}
37
 
38
/* Calculate a hash value.  */
39
 
40
unsigned int
41
fixed_hash (const FIXED_VALUE_TYPE *f)
42
{
43
  return (unsigned int) (f->data.low ^ f->data.high);
44
}
45
 
46
/* Define the enum code for the range of the fixed-point value.  */
47
enum fixed_value_range_code {
48
  FIXED_OK,             /* The value is within the range.  */
49
  FIXED_UNDERFLOW,      /* The value is less than the minimum.  */
50
  FIXED_GT_MAX_EPS,     /* The value is greater than the maximum, but not equal
51
                           to the maximum plus the epsilon.  */
52
  FIXED_MAX_EPS         /* The value equals the maximum plus the epsilon.  */
53
};
54
 
55
/* Check REAL_VALUE against the range of the fixed-point mode.
56
   Return FIXED_OK, if it is within the range.
57
          FIXED_UNDERFLOW, if it is less than the minimum.
58
          FIXED_GT_MAX_EPS, if it is greater than the maximum, but not equal to
59
            the maximum plus the epsilon.
60
          FIXED_MAX_EPS, if it is equal to the maximum plus the epsilon.  */
61
 
62
static enum fixed_value_range_code
63
check_real_for_fixed_mode (REAL_VALUE_TYPE *real_value, enum machine_mode mode)
64
{
65
  REAL_VALUE_TYPE max_value, min_value, epsilon_value;
66
 
67
  real_2expN (&max_value, GET_MODE_IBIT (mode), mode);
68
  real_2expN (&epsilon_value, -GET_MODE_FBIT (mode), mode);
69
 
70
  if (SIGNED_FIXED_POINT_MODE_P (mode))
71
    min_value = REAL_VALUE_NEGATE (max_value);
72
  else
73
    real_from_string (&min_value, "0.0");
74
 
75
  if (real_compare (LT_EXPR, real_value, &min_value))
76
    return FIXED_UNDERFLOW;
77
  if (real_compare (EQ_EXPR, real_value, &max_value))
78
    return FIXED_MAX_EPS;
79
  real_arithmetic (&max_value, MINUS_EXPR, &max_value, &epsilon_value);
80
  if (real_compare (GT_EXPR, real_value, &max_value))
81
    return FIXED_GT_MAX_EPS;
82
  return FIXED_OK;
83
}
84
 
85
/* Initialize from a decimal or hexadecimal string.  */
86
 
87
void
88
fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
89
{
90
  REAL_VALUE_TYPE real_value, fixed_value, base_value;
91
  unsigned int fbit;
92
  enum fixed_value_range_code temp;
93
 
94
  f->mode = mode;
95
  fbit = GET_MODE_FBIT (mode);
96
 
97
  real_from_string (&real_value, str);
98
  temp = check_real_for_fixed_mode (&real_value, f->mode);
99
  /* We don't want to warn the case when the _Fract value is 1.0.  */
100
  if (temp == FIXED_UNDERFLOW
101
      || temp == FIXED_GT_MAX_EPS
102
      || (temp == FIXED_MAX_EPS && ALL_ACCUM_MODE_P (f->mode)))
103
    warning (OPT_Woverflow,
104
             "large fixed-point constant implicitly truncated to fixed-point type");
105
  real_2expN (&base_value, fbit, mode);
106
  real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
107
  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high,
108
                    &fixed_value);
109
 
110
  if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
111
    {
112
      /* From the spec, we need to evaluate 1 to the maximal value.  */
113
      f->data.low = -1;
114
      f->data.high = -1;
115
      f->data = double_int_ext (f->data,
116
                                GET_MODE_FBIT (f->mode)
117
                                + GET_MODE_IBIT (f->mode), 1);
118
    }
119
  else
120
    f->data = double_int_ext (f->data,
121
                              SIGNED_FIXED_POINT_MODE_P (f->mode)
122
                              + GET_MODE_FBIT (f->mode)
123
                              + GET_MODE_IBIT (f->mode),
124
                              UNSIGNED_FIXED_POINT_MODE_P (f->mode));
125
}
126
 
127
/* Render F as a decimal floating point constant.  */
128
 
129
void
130
fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
131
                  size_t buf_size)
132
{
133
  REAL_VALUE_TYPE real_value, base_value, fixed_value;
134
 
135
  real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode);
136
  real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high,
137
                     UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode));
138
  real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
139
  real_to_decimal (str, &fixed_value, buf_size, 0, 1);
140
}
141
 
142
/* If SAT_P, saturate A to the maximum or the minimum, and save to *F based on
143
   the machine mode MODE.
144
   Do not modify *F otherwise.
145
   This function assumes the width of double_int is greater than the width
146
   of the fixed-point value (the sum of a possible sign bit, possible ibits,
147
   and fbits).
148
   Return true, if !SAT_P and overflow.  */
149
 
150
static bool
151
fixed_saturate1 (enum machine_mode mode, double_int a, double_int *f,
152
                 bool sat_p)
153
{
154
  bool overflow_p = false;
155
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
156
  int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
157
 
158
  if (unsigned_p) /* Unsigned type.  */
159
    {
160
      double_int max;
161
      max.low = -1;
162
      max.high = -1;
163
      max = double_int_ext (max, i_f_bits, 1);
164
      if (double_int_cmp (a, max, 1) == 1)
165
        {
166
          if (sat_p)
167
            *f = max;
168
          else
169
            overflow_p = true;
170
        }
171
    }
172
  else /* Signed type.  */
173
    {
174
      double_int max, min;
175
      max.high = -1;
176
      max.low = -1;
177
      max = double_int_ext (max, i_f_bits, 1);
178
      min.high = 0;
179
      min.low = 1;
180
      lshift_double (min.low, min.high, i_f_bits,
181
                     2 * HOST_BITS_PER_WIDE_INT,
182
                     &min.low, &min.high, 1);
183
      min = double_int_ext (min, 1 + i_f_bits, 0);
184
      if (double_int_cmp (a, max, 0) == 1)
185
        {
186
          if (sat_p)
187
            *f = max;
188
          else
189
            overflow_p = true;
190
        }
191
      else if (double_int_cmp (a, min, 0) == -1)
192
        {
193
          if (sat_p)
194
            *f = min;
195
          else
196
            overflow_p = true;
197
        }
198
    }
199
  return overflow_p;
200
}
201
 
202
/* If SAT_P, saturate {A_HIGH, A_LOW} to the maximum or the minimum, and
203
   save to *F based on the machine mode MODE.
204
   Do not modify *F otherwise.
205
   This function assumes the width of two double_int is greater than the width
206
   of the fixed-point value (the sum of a possible sign bit, possible ibits,
207
   and fbits).
208
   Return true, if !SAT_P and overflow.  */
209
 
210
static bool
211
fixed_saturate2 (enum machine_mode mode, double_int a_high, double_int a_low,
212
                 double_int *f, bool sat_p)
213
{
214
  bool overflow_p = false;
215
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
216
  int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
217
 
218
  if (unsigned_p) /* Unsigned type.  */
219
    {
220
      double_int max_r, max_s;
221
      max_r.high = 0;
222
      max_r.low = 0;
223
      max_s.high = -1;
224
      max_s.low = -1;
225
      max_s = double_int_ext (max_s, i_f_bits, 1);
226
      if (double_int_cmp (a_high, max_r, 1) == 1
227
          || (double_int_equal_p (a_high, max_r) &&
228
              double_int_cmp (a_low, max_s, 1) == 1))
229
        {
230
          if (sat_p)
231
            *f = max_s;
232
          else
233
            overflow_p = true;
234
        }
235
    }
236
  else /* Signed type.  */
237
    {
238
      double_int max_r, max_s, min_r, min_s;
239
      max_r.high = 0;
240
      max_r.low = 0;
241
      max_s.high = -1;
242
      max_s.low = -1;
243
      max_s = double_int_ext (max_s, i_f_bits, 1);
244
      min_r.high = -1;
245
      min_r.low = -1;
246
      min_s.high = 0;
247
      min_s.low = 1;
248
      lshift_double (min_s.low, min_s.high, i_f_bits,
249
                     2 * HOST_BITS_PER_WIDE_INT,
250
                     &min_s.low, &min_s.high, 1);
251
      min_s = double_int_ext (min_s, 1 + i_f_bits, 0);
252
      if (double_int_cmp (a_high, max_r, 0) == 1
253
          || (double_int_equal_p (a_high, max_r) &&
254
              double_int_cmp (a_low, max_s, 1) == 1))
255
        {
256
          if (sat_p)
257
            *f = max_s;
258
          else
259
            overflow_p = true;
260
        }
261
      else if (double_int_cmp (a_high, min_r, 0) == -1
262
               || (double_int_equal_p (a_high, min_r) &&
263
                   double_int_cmp (a_low, min_s, 1) == -1))
264
        {
265
          if (sat_p)
266
            *f = min_s;
267
          else
268
            overflow_p = true;
269
        }
270
    }
271
  return overflow_p;
272
}
273
 
274
/* Return the sign bit based on I_F_BITS.  */
275
 
276
static inline int
277
get_fixed_sign_bit (double_int a, int i_f_bits)
278
{
279
  if (i_f_bits < HOST_BITS_PER_WIDE_INT)
280
    return (a.low >> i_f_bits) & 1;
281
  else
282
    return (a.high >> (i_f_bits - HOST_BITS_PER_WIDE_INT)) & 1;
283
}
284
 
285
/* Calculate F = A + (SUBTRACT_P ? -B : B).
286
   If SAT_P, saturate the result to the max or the min.
287
   Return true, if !SAT_P and overflow.  */
288
 
289
static bool
290
do_fixed_add (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
291
              const FIXED_VALUE_TYPE *b, bool subtract_p, bool sat_p)
292
{
293
  bool overflow_p = false;
294
  bool unsigned_p;
295
  double_int temp;
296
  int i_f_bits;
297
 
298
  /* This was a conditional expression but it triggered a bug in
299
     Sun C 5.5.  */
300
  if (subtract_p)
301
    temp = double_int_neg (b->data);
302
  else
303
    temp = b->data;
304
 
305
  unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
306
  i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
307
  f->mode = a->mode;
308
  f->data = double_int_add (a->data, temp);
309
  if (unsigned_p) /* Unsigned type.  */
310
    {
311
      if (subtract_p) /* Unsigned subtraction.  */
312
        {
313
          if (double_int_cmp (a->data, b->data, 1) == -1)
314
            {
315
              if (sat_p)
316
                {
317
                  f->data.high = 0;
318
                  f->data.low = 0;
319
                 }
320
              else
321
                overflow_p = true;
322
            }
323
        }
324
      else /* Unsigned addition.  */
325
        {
326
          f->data = double_int_ext (f->data, i_f_bits, 1);
327
          if (double_int_cmp (f->data, a->data, 1) == -1
328
              || double_int_cmp (f->data, b->data, 1) == -1)
329
            {
330
              if (sat_p)
331
                {
332
                  f->data.high = -1;
333
                  f->data.low = -1;
334
                }
335
              else
336
                overflow_p = true;
337
            }
338
        }
339
    }
340
  else /* Signed type.  */
341
    {
342
      if ((!subtract_p
343
           && (get_fixed_sign_bit (a->data, i_f_bits)
344
               == get_fixed_sign_bit (b->data, i_f_bits))
345
           && (get_fixed_sign_bit (a->data, i_f_bits)
346
               != get_fixed_sign_bit (f->data, i_f_bits)))
347
          || (subtract_p
348
              && (get_fixed_sign_bit (a->data, i_f_bits)
349
                  != get_fixed_sign_bit (b->data, i_f_bits))
350
              && (get_fixed_sign_bit (a->data, i_f_bits)
351
                  != get_fixed_sign_bit (f->data, i_f_bits))))
352
        {
353
          if (sat_p)
354
            {
355
              f->data.low = 1;
356
              f->data.high = 0;
357
              lshift_double (f->data.low, f->data.high, i_f_bits,
358
                             2 * HOST_BITS_PER_WIDE_INT,
359
                             &f->data.low, &f->data.high, 1);
360
              if (get_fixed_sign_bit (a->data, i_f_bits) == 0)
361
                {
362
                  double_int one;
363
                  one.low = 1;
364
                  one.high = 0;
365
                  f->data = double_int_add (f->data, double_int_neg (one));
366
                }
367
            }
368
          else
369
            overflow_p = true;
370
        }
371
    }
372
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
373
  return overflow_p;
374
}
375
 
376
/* Calculate F = A * B.
377
   If SAT_P, saturate the result to the max or the min.
378
   Return true, if !SAT_P and overflow.  */
379
 
380
static bool
381
do_fixed_multiply (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
382
                   const FIXED_VALUE_TYPE *b, bool sat_p)
383
{
384
  bool overflow_p = false;
385
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
386
  int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
387
  f->mode = a->mode;
388
  if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
389
    {
390
      f->data = double_int_mul (a->data, b->data);
391
      lshift_double (f->data.low, f->data.high,
392
                     (-GET_MODE_FBIT (f->mode)),
393
                     2 * HOST_BITS_PER_WIDE_INT,
394
                     &f->data.low, &f->data.high, !unsigned_p);
395
      overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
396
    }
397
  else
398
    {
399
      /* The result of multiplication expands to two double_int.  */
400
      double_int a_high, a_low, b_high, b_low;
401
      double_int high_high, high_low, low_high, low_low;
402
      double_int r, s, temp1, temp2;
403
      int carry = 0;
404
 
405
      /* Decompose a and b to four double_int.  */
406
      a_high.low = a->data.high;
407
      a_high.high = 0;
408
      a_low.low = a->data.low;
409
      a_low.high = 0;
410
      b_high.low = b->data.high;
411
      b_high.high = 0;
412
      b_low.low = b->data.low;
413
      b_low.high = 0;
414
 
415
      /* Perform four multiplications.  */
416
      low_low = double_int_mul (a_low, b_low);
417
      low_high = double_int_mul (a_low, b_high);
418
      high_low = double_int_mul (a_high, b_low);
419
      high_high = double_int_mul (a_high, b_high);
420
 
421
      /* Accumulate four results to {r, s}.  */
422
      temp1.high = high_low.low;
423
      temp1.low = 0;
424
      s = double_int_add (low_low, temp1);
425
      if (double_int_cmp (s, low_low, 1) == -1
426
          || double_int_cmp (s, temp1, 1) == -1)
427
        carry ++; /* Carry */
428
      temp1.high = s.high;
429
      temp1.low = s.low;
430
      temp2.high = low_high.low;
431
      temp2.low = 0;
432
      s = double_int_add (temp1, temp2);
433
      if (double_int_cmp (s, temp1, 1) == -1
434
          || double_int_cmp (s, temp2, 1) == -1)
435
        carry ++; /* Carry */
436
 
437
      temp1.low = high_low.high;
438
      temp1.high = 0;
439
      r = double_int_add (high_high, temp1);
440
      temp1.low = low_high.high;
441
      temp1.high = 0;
442
      r = double_int_add (r, temp1);
443
      temp1.low = carry;
444
      temp1.high = 0;
445
      r = double_int_add (r, temp1);
446
 
447
      /* We need to add neg(b) to r, if a < 0.  */
448
      if (!unsigned_p && a->data.high < 0)
449
        r = double_int_add (r, double_int_neg (b->data));
450
      /* We need to add neg(a) to r, if b < 0.  */
451
      if (!unsigned_p && b->data.high < 0)
452
        r = double_int_add (r, double_int_neg (a->data));
453
 
454
      /* Shift right the result by FBIT.  */
455
      if (GET_MODE_FBIT (f->mode) == 2 * HOST_BITS_PER_WIDE_INT)
456
        {
457
          s.low = r.low;
458
          s.high = r.high;
459
          if (unsigned_p)
460
            {
461
              r.low = 0;
462
              r.high = 0;
463
            }
464
          else
465
            {
466
              r.low = -1;
467
              r.high = -1;
468
            }
469
          f->data.low = s.low;
470
          f->data.high = s.high;
471
        }
472
      else
473
        {
474
          lshift_double (s.low, s.high,
475
                         (-GET_MODE_FBIT (f->mode)),
476
                         2 * HOST_BITS_PER_WIDE_INT,
477
                         &s.low, &s.high, 0);
478
          lshift_double (r.low, r.high,
479
                         (2 * HOST_BITS_PER_WIDE_INT
480
                          - GET_MODE_FBIT (f->mode)),
481
                         2 * HOST_BITS_PER_WIDE_INT,
482
                         &f->data.low, &f->data.high, 0);
483
          f->data.low = f->data.low | s.low;
484
          f->data.high = f->data.high | s.high;
485
          s.low = f->data.low;
486
          s.high = f->data.high;
487
          lshift_double (r.low, r.high,
488
                         (-GET_MODE_FBIT (f->mode)),
489
                         2 * HOST_BITS_PER_WIDE_INT,
490
                         &r.low, &r.high, !unsigned_p);
491
        }
492
 
493
      overflow_p = fixed_saturate2 (f->mode, r, s, &f->data, sat_p);
494
    }
495
 
496
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
497
  return overflow_p;
498
}
499
 
500
/* Calculate F = A / B.
501
   If SAT_P, saturate the result to the max or the min.
502
   Return true, if !SAT_P and overflow.  */
503
 
504
static bool
505
do_fixed_divide (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
506
                 const FIXED_VALUE_TYPE *b, bool sat_p)
507
{
508
  bool overflow_p = false;
509
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
510
  int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
511
  f->mode = a->mode;
512
  if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT)
513
    {
514
      lshift_double (a->data.low, a->data.high,
515
                     GET_MODE_FBIT (f->mode),
516
                     2 * HOST_BITS_PER_WIDE_INT,
517
                     &f->data.low, &f->data.high, !unsigned_p);
518
      f->data = double_int_div (f->data, b->data, unsigned_p, TRUNC_DIV_EXPR);
519
      overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
520
    }
521
  else
522
    {
523
      double_int pos_a, pos_b, r, s;
524
      double_int quo_r, quo_s, mod, temp;
525
      int num_of_neg = 0;
526
      int i;
527
 
528
      /* If a < 0, negate a.  */
529
      if (!unsigned_p && a->data.high < 0)
530
        {
531
          pos_a = double_int_neg (a->data);
532
          num_of_neg ++;
533
        }
534
      else
535
        pos_a = a->data;
536
 
537
      /* If b < 0, negate b.  */
538
      if (!unsigned_p && b->data.high < 0)
539
        {
540
          pos_b = double_int_neg (b->data);
541
          num_of_neg ++;
542
        }
543
      else
544
        pos_b = b->data;
545
 
546
      /* Left shift pos_a to {r, s} by FBIT.  */
547
      if (GET_MODE_FBIT (f->mode) == 2 * HOST_BITS_PER_WIDE_INT)
548
        {
549
          r = pos_a;
550
          s.high = 0;
551
          s.low = 0;
552
        }
553
      else
554
        {
555
          lshift_double (pos_a.low, pos_a.high,
556
                         GET_MODE_FBIT (f->mode),
557
                         2 * HOST_BITS_PER_WIDE_INT,
558
                         &s.low, &s.high, 0);
559
          lshift_double (pos_a.low, pos_a.high,
560
                         - (2 * HOST_BITS_PER_WIDE_INT
561
                            - GET_MODE_FBIT (f->mode)),
562
                         2 * HOST_BITS_PER_WIDE_INT,
563
                         &r.low, &r.high, 0);
564
        }
565
 
566
      /* Divide r by pos_b to quo_r.  The remainder is in mod.  */
567
      div_and_round_double (TRUNC_DIV_EXPR, 1, r.low, r.high, pos_b.low,
568
                            pos_b.high, &quo_r.low, &quo_r.high, &mod.low,
569
                            &mod.high);
570
 
571
      quo_s.high = 0;
572
      quo_s.low = 0;
573
 
574
      for (i = 0; i < 2 * HOST_BITS_PER_WIDE_INT; i++)
575
        {
576
          /* Record the leftmost bit of mod.  */
577
          int leftmost_mod = (mod.high < 0);
578
 
579
          /* Shift left mod by 1 bit.  */
580
          lshift_double (mod.low, mod.high, 1, 2 * HOST_BITS_PER_WIDE_INT,
581
                         &mod.low, &mod.high, 0);
582
 
583
          /* Test the leftmost bit of s to add to mod.  */
584
          if (s.high < 0)
585
            mod.low += 1;
586
 
587
          /* Shift left quo_s by 1 bit.  */
588
          lshift_double (quo_s.low, quo_s.high, 1, 2 * HOST_BITS_PER_WIDE_INT,
589
                         &quo_s.low, &quo_s.high, 0);
590
 
591
          /* Try to calculate (mod - pos_b).  */
592
          temp = double_int_add (mod, double_int_neg (pos_b));
593
 
594
          if (leftmost_mod == 1 || double_int_cmp (mod, pos_b, 1) != -1)
595
            {
596
              quo_s.low += 1;
597
              mod = temp;
598
            }
599
 
600
          /* Shift left s by 1 bit.  */
601
          lshift_double (s.low, s.high, 1, 2 * HOST_BITS_PER_WIDE_INT,
602
                         &s.low, &s.high, 0);
603
 
604
        }
605
 
606
      if (num_of_neg == 1)
607
        {
608
          quo_s = double_int_neg (quo_s);
609
          if (quo_s.high == 0 && quo_s.low == 0)
610
            quo_r = double_int_neg (quo_r);
611
          else
612
            {
613
              quo_r.low = ~quo_r.low;
614
              quo_r.high = ~quo_r.high;
615
            }
616
        }
617
 
618
      f->data = quo_s;
619
      overflow_p = fixed_saturate2 (f->mode, quo_r, quo_s, &f->data, sat_p);
620
    }
621
 
622
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
623
  return overflow_p;
624
}
625
 
626
/* Calculate F = A << B if LEFT_P.  Otherwise, F = A >> B.
627
   If SAT_P, saturate the result to the max or the min.
628
   Return true, if !SAT_P and overflow.  */
629
 
630
static bool
631
do_fixed_shift (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a,
632
              const FIXED_VALUE_TYPE *b, bool left_p, bool sat_p)
633
{
634
  bool overflow_p = false;
635
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
636
  int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
637
  f->mode = a->mode;
638
 
639
  if (b->data.low == 0)
640
    {
641
      f->data = a->data;
642
      return overflow_p;
643
    }
644
 
645
  if (GET_MODE_PRECISION (f->mode) <= HOST_BITS_PER_WIDE_INT || (!left_p))
646
    {
647
      lshift_double (a->data.low, a->data.high,
648
                     left_p ? b->data.low : (-b->data.low),
649
                     2 * HOST_BITS_PER_WIDE_INT,
650
                     &f->data.low, &f->data.high, !unsigned_p);
651
      if (left_p) /* Only left shift saturates.  */
652
        overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
653
    }
654
  else /* We need two double_int to store the left-shift result.  */
655
    {
656
      double_int temp_high, temp_low;
657
      if (b->data.low == 2 * HOST_BITS_PER_WIDE_INT)
658
        {
659
          temp_high = a->data;
660
          temp_low.high = 0;
661
          temp_low.low = 0;
662
        }
663
      else
664
        {
665
          lshift_double (a->data.low, a->data.high,
666
                         b->data.low,
667
                         2 * HOST_BITS_PER_WIDE_INT,
668
                         &temp_low.low, &temp_low.high, !unsigned_p);
669
          /* Logical shift right to temp_high.  */
670
          lshift_double (a->data.low, a->data.high,
671
                         b->data.low - 2 * HOST_BITS_PER_WIDE_INT,
672
                         2 * HOST_BITS_PER_WIDE_INT,
673
                         &temp_high.low, &temp_high.high, 0);
674
        }
675
      if (!unsigned_p && a->data.high < 0) /* Signed-extend temp_high.  */
676
        temp_high = double_int_ext (temp_high, b->data.low, unsigned_p);
677
      f->data = temp_low;
678
      overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
679
                                    sat_p);
680
    }
681
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
682
  return overflow_p;
683
}
684
 
685
/* Calculate F = -A.
686
   If SAT_P, saturate the result to the max or the min.
687
   Return true, if !SAT_P and overflow.  */
688
 
689
static bool
690
do_fixed_neg (FIXED_VALUE_TYPE *f, const FIXED_VALUE_TYPE *a, bool sat_p)
691
{
692
  bool overflow_p = false;
693
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (a->mode);
694
  int i_f_bits = GET_MODE_IBIT (a->mode) + GET_MODE_FBIT (a->mode);
695
  f->mode = a->mode;
696
  f->data = double_int_neg (a->data);
697
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
698
 
699
  if (unsigned_p) /* Unsigned type.  */
700
    {
701
      if (f->data.low != 0 || f->data.high != 0)
702
        {
703
          if (sat_p)
704
            {
705
              f->data.low = 0;
706
              f->data.high = 0;
707
            }
708
          else
709
            overflow_p = true;
710
        }
711
    }
712
  else /* Signed type.  */
713
    {
714
      if (!(f->data.high == 0 && f->data.low == 0)
715
          && f->data.high == a->data.high && f->data.low == a->data.low )
716
        {
717
          if (sat_p)
718
            {
719
              /* Saturate to the maximum by subtracting f->data by one.  */
720
              f->data.low = -1;
721
              f->data.high = -1;
722
              f->data = double_int_ext (f->data, i_f_bits, 1);
723
            }
724
          else
725
            overflow_p = true;
726
        }
727
    }
728
  return overflow_p;
729
}
730
 
731
/* Perform the binary or unary operation described by CODE.
732
   Note that OP0 and OP1 must have the same mode for binary operators.
733
   For a unary operation, leave OP1 NULL.
734
   Return true, if !SAT_P and overflow.  */
735
 
736
bool
737
fixed_arithmetic (FIXED_VALUE_TYPE *f, int icode, const FIXED_VALUE_TYPE *op0,
738
                  const FIXED_VALUE_TYPE *op1, bool sat_p)
739
{
740
  switch (icode)
741
    {
742
    case NEGATE_EXPR:
743
      return do_fixed_neg (f, op0, sat_p);
744
      break;
745
 
746
    case PLUS_EXPR:
747
      gcc_assert (op0->mode == op1->mode);
748
      return do_fixed_add (f, op0, op1, false, sat_p);
749
      break;
750
 
751
    case MINUS_EXPR:
752
      gcc_assert (op0->mode == op1->mode);
753
      return do_fixed_add (f, op0, op1, true, sat_p);
754
      break;
755
 
756
    case MULT_EXPR:
757
      gcc_assert (op0->mode == op1->mode);
758
      return do_fixed_multiply (f, op0, op1, sat_p);
759
      break;
760
 
761
    case TRUNC_DIV_EXPR:
762
      gcc_assert (op0->mode == op1->mode);
763
      return do_fixed_divide (f, op0, op1, sat_p);
764
      break;
765
 
766
    case LSHIFT_EXPR:
767
      return do_fixed_shift (f, op0, op1, true, sat_p);
768
      break;
769
 
770
    case RSHIFT_EXPR:
771
      return do_fixed_shift (f, op0, op1, false, sat_p);
772
      break;
773
 
774
    default:
775
      gcc_unreachable ();
776
    }
777
  return false;
778
}
779
 
780
/* Compare fixed-point values by tree_code.
781
   Note that OP0 and OP1 must have the same mode.  */
782
 
783
bool
784
fixed_compare (int icode, const FIXED_VALUE_TYPE *op0,
785
               const FIXED_VALUE_TYPE *op1)
786
{
787
  enum tree_code code = (enum tree_code) icode;
788
  gcc_assert (op0->mode == op1->mode);
789
 
790
  switch (code)
791
    {
792
    case NE_EXPR:
793
      return !double_int_equal_p (op0->data, op1->data);
794
 
795
    case EQ_EXPR:
796
      return double_int_equal_p (op0->data, op1->data);
797
 
798
    case LT_EXPR:
799
      return double_int_cmp (op0->data, op1->data,
800
                             UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == -1;
801
 
802
    case LE_EXPR:
803
      return double_int_cmp (op0->data, op1->data,
804
                             UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != 1;
805
 
806
    case GT_EXPR:
807
      return double_int_cmp (op0->data, op1->data,
808
                             UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) == 1;
809
 
810
    case GE_EXPR:
811
      return double_int_cmp (op0->data, op1->data,
812
                             UNSIGNED_FIXED_POINT_MODE_P (op0->mode)) != -1;
813
 
814
    default:
815
      gcc_unreachable ();
816
    }
817
}
818
 
819
/* Extend or truncate to a new mode.
820
   If SAT_P, saturate the result to the max or the min.
821
   Return true, if !SAT_P and overflow.  */
822
 
823
bool
824
fixed_convert (FIXED_VALUE_TYPE *f, enum machine_mode mode,
825
               const FIXED_VALUE_TYPE *a, bool sat_p)
826
{
827
  bool overflow_p = false;
828
  if (mode == a->mode)
829
    {
830
      *f = *a;
831
      return overflow_p;
832
    }
833
 
834
  if (GET_MODE_FBIT (mode) > GET_MODE_FBIT (a->mode))
835
    {
836
      /* Left shift a to temp_high, temp_low based on a->mode.  */
837
      double_int temp_high, temp_low;
838
      int amount = GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode);
839
      lshift_double (a->data.low, a->data.high,
840
                     amount,
841
                     2 * HOST_BITS_PER_WIDE_INT,
842
                     &temp_low.low, &temp_low.high,
843
                     SIGNED_FIXED_POINT_MODE_P (a->mode));
844
      /* Logical shift right to temp_high.  */
845
      lshift_double (a->data.low, a->data.high,
846
                     amount - 2 * HOST_BITS_PER_WIDE_INT,
847
                     2 * HOST_BITS_PER_WIDE_INT,
848
                     &temp_high.low, &temp_high.high, 0);
849
      if (SIGNED_FIXED_POINT_MODE_P (a->mode)
850
          && a->data.high < 0) /* Signed-extend temp_high.  */
851
        temp_high = double_int_ext (temp_high, amount, 0);
852
      f->mode = mode;
853
      f->data = temp_low;
854
      if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
855
          SIGNED_FIXED_POINT_MODE_P (f->mode))
856
        overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
857
                                      sat_p);
858
      else
859
        {
860
          /* Take care of the cases when converting between signed and
861
             unsigned.  */
862
          if (SIGNED_FIXED_POINT_MODE_P (a->mode))
863
            {
864
              /* Signed -> Unsigned.  */
865
              if (a->data.high < 0)
866
                {
867
                  if (sat_p)
868
                    {
869
                      f->data.low = 0;  /* Set to zero.  */
870
                      f->data.high = 0;  /* Set to zero.  */
871
                    }
872
                  else
873
                    overflow_p = true;
874
                }
875
              else
876
                overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
877
                                              &f->data, sat_p);
878
            }
879
          else
880
            {
881
              /* Unsigned -> Signed.  */
882
              if (temp_high.high < 0)
883
                {
884
                  if (sat_p)
885
                    {
886
                      /* Set to maximum.  */
887
                      f->data.low = -1;  /* Set to all ones.  */
888
                      f->data.high = -1;  /* Set to all ones.  */
889
                      f->data = double_int_ext (f->data,
890
                                                GET_MODE_FBIT (f->mode)
891
                                                + GET_MODE_IBIT (f->mode),
892
                                                1); /* Clear the sign.  */
893
                    }
894
                  else
895
                    overflow_p = true;
896
                }
897
              else
898
                overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
899
                                              &f->data, sat_p);
900
            }
901
        }
902
    }
903
  else
904
    {
905
      /* Right shift a to temp based on a->mode.  */
906
      double_int temp;
907
      lshift_double (a->data.low, a->data.high,
908
                     GET_MODE_FBIT (mode) - GET_MODE_FBIT (a->mode),
909
                     2 * HOST_BITS_PER_WIDE_INT,
910
                     &temp.low, &temp.high,
911
                     SIGNED_FIXED_POINT_MODE_P (a->mode));
912
      f->mode = mode;
913
      f->data = temp;
914
      if (SIGNED_FIXED_POINT_MODE_P (a->mode) ==
915
          SIGNED_FIXED_POINT_MODE_P (f->mode))
916
        overflow_p = fixed_saturate1 (f->mode, f->data, &f->data, sat_p);
917
      else
918
        {
919
          /* Take care of the cases when converting between signed and
920
             unsigned.  */
921
          if (SIGNED_FIXED_POINT_MODE_P (a->mode))
922
            {
923
              /* Signed -> Unsigned.  */
924
              if (a->data.high < 0)
925
                {
926
                  if (sat_p)
927
                    {
928
                      f->data.low = 0;  /* Set to zero.  */
929
                      f->data.high = 0;  /* Set to zero.  */
930
                    }
931
                  else
932
                    overflow_p = true;
933
                }
934
              else
935
                overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
936
                                              sat_p);
937
            }
938
          else
939
            {
940
              /* Unsigned -> Signed.  */
941
              if (temp.high < 0)
942
                {
943
                  if (sat_p)
944
                    {
945
                      /* Set to maximum.  */
946
                      f->data.low = -1;  /* Set to all ones.  */
947
                      f->data.high = -1;  /* Set to all ones.  */
948
                      f->data = double_int_ext (f->data,
949
                                                GET_MODE_FBIT (f->mode)
950
                                                + GET_MODE_IBIT (f->mode),
951
                                                1); /* Clear the sign.  */
952
                    }
953
                  else
954
                    overflow_p = true;
955
                }
956
              else
957
                overflow_p = fixed_saturate1 (f->mode, f->data, &f->data,
958
                                              sat_p);
959
            }
960
        }
961
    }
962
 
963
  f->data = double_int_ext (f->data,
964
                            SIGNED_FIXED_POINT_MODE_P (f->mode)
965
                            + GET_MODE_FBIT (f->mode)
966
                            + GET_MODE_IBIT (f->mode),
967
                            UNSIGNED_FIXED_POINT_MODE_P (f->mode));
968
  return overflow_p;
969
}
970
 
971
/* Convert to a new fixed-point mode from an integer.
972
   If UNSIGNED_P, this integer is unsigned.
973
   If SAT_P, saturate the result to the max or the min.
974
   Return true, if !SAT_P and overflow.  */
975
 
976
bool
977
fixed_convert_from_int (FIXED_VALUE_TYPE *f, enum machine_mode mode,
978
                        double_int a, bool unsigned_p, bool sat_p)
979
{
980
  bool overflow_p = false;
981
  /* Left shift a to temp_high, temp_low.  */
982
  double_int temp_high, temp_low;
983
  int amount = GET_MODE_FBIT (mode);
984
  if (amount == 2 * HOST_BITS_PER_WIDE_INT)
985
    {
986
       temp_high = a;
987
       temp_low.low = 0;
988
       temp_low.high = 0;
989
    }
990
  else
991
    {
992
      lshift_double (a.low, a.high,
993
                     amount,
994
                     2 * HOST_BITS_PER_WIDE_INT,
995
                     &temp_low.low, &temp_low.high, 0);
996
 
997
      /* Logical shift right to temp_high.  */
998
      lshift_double (a.low, a.high,
999
                     amount - 2 * HOST_BITS_PER_WIDE_INT,
1000
                     2 * HOST_BITS_PER_WIDE_INT,
1001
                     &temp_high.low, &temp_high.high, 0);
1002
    }
1003
  if (!unsigned_p && a.high < 0) /* Signed-extend temp_high.  */
1004
    temp_high = double_int_ext (temp_high, amount, 0);
1005
 
1006
  f->mode = mode;
1007
  f->data = temp_low;
1008
 
1009
  if (unsigned_p == UNSIGNED_FIXED_POINT_MODE_P (f->mode))
1010
    overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low, &f->data,
1011
                                  sat_p);
1012
  else
1013
    {
1014
      /* Take care of the cases when converting between signed and unsigned.  */
1015
      if (!unsigned_p)
1016
        {
1017
          /* Signed -> Unsigned.  */
1018
          if (a.high < 0)
1019
            {
1020
              if (sat_p)
1021
                {
1022
                  f->data.low = 0;  /* Set to zero.  */
1023
                  f->data.high = 0;  /* Set to zero.  */
1024
                }
1025
              else
1026
                overflow_p = true;
1027
            }
1028
          else
1029
            overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
1030
                                          &f->data, sat_p);
1031
        }
1032
      else
1033
        {
1034
          /* Unsigned -> Signed.  */
1035
          if (temp_high.high < 0)
1036
            {
1037
              if (sat_p)
1038
                {
1039
                  /* Set to maximum.  */
1040
                  f->data.low = -1;  /* Set to all ones.  */
1041
                  f->data.high = -1;  /* Set to all ones.  */
1042
                  f->data = double_int_ext (f->data,
1043
                                            GET_MODE_FBIT (f->mode)
1044
                                            + GET_MODE_IBIT (f->mode),
1045
                                            1); /* Clear the sign.  */
1046
                }
1047
              else
1048
                overflow_p = true;
1049
            }
1050
          else
1051
            overflow_p = fixed_saturate2 (f->mode, temp_high, temp_low,
1052
                                          &f->data, sat_p);
1053
        }
1054
    }
1055
  f->data = double_int_ext (f->data,
1056
                            SIGNED_FIXED_POINT_MODE_P (f->mode)
1057
                            + GET_MODE_FBIT (f->mode)
1058
                            + GET_MODE_IBIT (f->mode),
1059
                            UNSIGNED_FIXED_POINT_MODE_P (f->mode));
1060
  return overflow_p;
1061
}
1062
 
1063
/* Convert to a new fixed-point mode from a real.
1064
   If SAT_P, saturate the result to the max or the min.
1065
   Return true, if !SAT_P and overflow.  */
1066
 
1067
bool
1068
fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
1069
                         const REAL_VALUE_TYPE *a, bool sat_p)
1070
{
1071
  bool overflow_p = false;
1072
  REAL_VALUE_TYPE real_value, fixed_value, base_value;
1073
  bool unsigned_p = UNSIGNED_FIXED_POINT_MODE_P (mode);
1074
  int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
1075
  unsigned int fbit = GET_MODE_FBIT (mode);
1076
  enum fixed_value_range_code temp;
1077
 
1078
  real_value = *a;
1079
  f->mode = mode;
1080
  real_2expN (&base_value, fbit, mode);
1081
  real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
1082
  real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value);
1083
  temp = check_real_for_fixed_mode (&real_value, mode);
1084
  if (temp == FIXED_UNDERFLOW) /* Minimum.  */
1085
    {
1086
      if (sat_p)
1087
        {
1088
          if (unsigned_p)
1089
            {
1090
              f->data.low = 0;
1091
              f->data.high = 0;
1092
            }
1093
          else
1094
            {
1095
              f->data.low = 1;
1096
              f->data.high = 0;
1097
              lshift_double (f->data.low, f->data.high, i_f_bits,
1098
                             2 * HOST_BITS_PER_WIDE_INT,
1099
                             &f->data.low, &f->data.high, 1);
1100
              f->data = double_int_ext (f->data, 1 + i_f_bits, 0);
1101
            }
1102
        }
1103
      else
1104
        overflow_p = true;
1105
    }
1106
  else if (temp == FIXED_GT_MAX_EPS || temp == FIXED_MAX_EPS) /* Maximum.  */
1107
    {
1108
      if (sat_p)
1109
        {
1110
          f->data.low = -1;
1111
          f->data.high = -1;
1112
          f->data = double_int_ext (f->data, i_f_bits, 1);
1113
        }
1114
      else
1115
        overflow_p = true;
1116
    }
1117
  f->data = double_int_ext (f->data, (!unsigned_p) + i_f_bits, unsigned_p);
1118
  return overflow_p;
1119
}
1120
 
1121
/* Convert to a new real mode from a fixed-point.  */
1122
 
1123
void
1124
real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode,
1125
                         const FIXED_VALUE_TYPE *f)
1126
{
1127
  REAL_VALUE_TYPE base_value, fixed_value, real_value;
1128
 
1129
  real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode);
1130
  real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high,
1131
                     UNSIGNED_FIXED_POINT_MODE_P (f->mode));
1132
  real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
1133
  real_convert (r, mode, &real_value);
1134
}
1135
 
1136
/* Determine whether a fixed-point value F is negative.  */
1137
 
1138
bool
1139
fixed_isneg (const FIXED_VALUE_TYPE *f)
1140
{
1141
  if (SIGNED_FIXED_POINT_MODE_P (f->mode))
1142
    {
1143
      int i_f_bits = GET_MODE_IBIT (f->mode) + GET_MODE_FBIT (f->mode);
1144
      int sign_bit = get_fixed_sign_bit (f->data, i_f_bits);
1145
      if (sign_bit == 1)
1146
        return true;
1147
    }
1148
 
1149
  return false;
1150
}

powered by: WebSVN 2.1.0

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