~ubuntu-branches/debian/jessie/gdb/jessie

« back to all changes in this revision

Viewing changes to sim/rx/fpu.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Jacobowitz
  • Date: 2010-03-20 01:21:29 UTC
  • mfrom: (1.3.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20100320012129-t7h25y8zgr8c2369
Tags: 7.1-1
* New upstream release, including:
  - PIE support (Closes: #346409).
  - C++ improvements, including static_cast<> et al, namespace imports,
    and bug fixes in printing virtual base classes.
  - Multi-program debugging.  One GDB can now debug multiple programs
    at the same time.
  - Python scripting improvements, including gdb.parse_and_eval.
  - Updated MIPS Linux signal frame layout (Closes: #570875).
  - No internal error stepping over _dl_debug_state (Closes: #569551).
* Update to Standards-Version: 3.8.4 (no changes required).
* Include more relevant (and smaller) docs in the gdbserver package
  (Closes: #571132).
* Do not duplicate documentation in gdb64, gdb-source, and libgdb-dev.
* Fix crash when switching into TUI mode (Closes: #568489).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* fpu.c --- FPU emulator for stand-alone RX simulator.
 
2
 
 
3
Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
4
Contributed by Red Hat, Inc.
 
5
 
 
6
This file is part of the GNU simulators.
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 3 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
 
 
24
#include "cpu.h"
 
25
#include "fpu.h"
 
26
 
 
27
/* FPU encodings are as follows:
 
28
 
 
29
   S EXPONENT MANTISSA
 
30
   1 12345678 12345678901234567890123
 
31
 
 
32
   0 00000000 00000000000000000000000   +0
 
33
   1 00000000 00000000000000000000000   -0
 
34
 
 
35
   X 00000000 00000000000000000000001   Denormals
 
36
   X 00000000 11111111111111111111111
 
37
 
 
38
   X 00000001 XXXXXXXXXXXXXXXXXXXXXXX   Normals
 
39
   X 11111110 XXXXXXXXXXXXXXXXXXXXXXX
 
40
 
 
41
   0 11111111 00000000000000000000000   +Inf
 
42
   1 11111111 00000000000000000000000   -Inf
 
43
 
 
44
   X 11111111 0XXXXXXXXXXXXXXXXXXXXXX   SNaN (X != 0)
 
45
   X 11111111 1XXXXXXXXXXXXXXXXXXXXXX   QNaN (X != 0)
 
46
 
 
47
*/
 
48
 
 
49
#define trace 0
 
50
#define tprintf if (trace) printf
 
51
 
 
52
/* Some magic numbers.  */
 
53
#define PLUS_MAX   0x7f7fffffUL
 
54
#define MINUS_MAX  0xff7fffffUL
 
55
#define PLUS_INF   0x7f800000UL
 
56
#define MINUS_INF  0xff800000UL
 
57
#define PLUS_ZERO  0x00000000UL
 
58
#define MINUS_ZERO 0x80000000UL
 
59
 
 
60
#define FP_RAISE(e) fp_raise(FPSWBITS_C##e)
 
61
static void
 
62
fp_raise (int mask)
 
63
{
 
64
  regs.r_fpsw |= mask;
 
65
  if (mask != FPSWBITS_CE)
 
66
    {
 
67
      if (regs.r_fpsw & (mask << FPSW_CESH))
 
68
        regs.r_fpsw |= (mask << FPSW_CFSH);
 
69
      if (regs.r_fpsw & FPSWBITS_FMASK)
 
70
        regs.r_fpsw |= FPSWBITS_FSUM;
 
71
      else
 
72
        regs.r_fpsw &= ~FPSWBITS_FSUM;
 
73
    }
 
74
}
 
75
 
 
76
/* We classify all numbers as one of these.  They correspond to the
 
77
   rows/colums in the exception tables.  */
 
78
typedef enum {
 
79
  FP_NORMAL,
 
80
  FP_PZERO,
 
81
  FP_NZERO,
 
82
  FP_PINFINITY,
 
83
  FP_NINFINITY,
 
84
  FP_DENORMAL,
 
85
  FP_QNAN,
 
86
  FP_SNAN
 
87
} FP_Type;
 
88
 
 
89
#if defined DEBUG0
 
90
static const char *fpt_names[] = {
 
91
  "Normal", "+0", "-0", "+Inf", "-Inf", "Denormal", "QNaN", "SNaN"
 
92
};
 
93
#endif
 
94
 
 
95
#define EXP_BIAS  127
 
96
#define EXP_ZERO -127
 
97
#define EXP_INF   128
 
98
 
 
99
#define MANT_BIAS 0x00080000UL
 
100
 
 
101
typedef struct {
 
102
  int exp;
 
103
  unsigned int mant; /* 24 bits */
 
104
  char type;
 
105
  char sign;
 
106
  fp_t orig_value;
 
107
} FP_Parts;
 
108
 
 
109
static void
 
110
fp_explode (fp_t f, FP_Parts *p)
 
111
{
 
112
  int exp, mant, sign;
 
113
 
 
114
  exp = ((f & 0x7f800000UL) >> 23);
 
115
  mant = f & 0x007fffffUL;
 
116
  sign = f & 0x80000000UL;
 
117
  /*printf("explode: %08x %x %2x %6x\n", f, sign, exp, mant);*/
 
118
 
 
119
  p->sign = sign ? -1 : 1;
 
120
  p->exp = exp - EXP_BIAS;
 
121
  p->orig_value = f;
 
122
  p->mant = mant | 0x00800000UL;
 
123
 
 
124
  if (p->exp == EXP_ZERO)
 
125
    {
 
126
      if (regs.r_fpsw & FPSWBITS_DN)
 
127
        mant = 0;
 
128
      if (mant)
 
129
        p->type = FP_DENORMAL;
 
130
      else
 
131
        {
 
132
          p->mant = 0;
 
133
          p->type = sign ? FP_NZERO : FP_PZERO;
 
134
        }
 
135
    }
 
136
  else if (p->exp == EXP_INF)
 
137
    {
 
138
      if (mant == 0)
 
139
        p->type = sign ? FP_NINFINITY : FP_PINFINITY;
 
140
      else if (mant & 0x00400000UL)
 
141
        p->type = FP_QNAN;
 
142
      else
 
143
        p->type = FP_SNAN;
 
144
    }
 
145
  else
 
146
    p->type = FP_NORMAL;
 
147
}
 
148
 
 
149
static fp_t
 
150
fp_implode (FP_Parts *p)
 
151
{
 
152
  int exp, mant;
 
153
 
 
154
  exp = p->exp + EXP_BIAS;
 
155
  mant = p->mant;
 
156
  /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/
 
157
  if (p->type == FP_NORMAL)
 
158
    {
 
159
      while (mant
 
160
             && exp > 0
 
161
             && mant < 0x00800000UL)
 
162
        {
 
163
          mant <<= 1;
 
164
          exp --;
 
165
        }
 
166
      while (mant > 0x00ffffffUL)
 
167
        {
 
168
          mant >>= 1;
 
169
          exp ++;
 
170
        }
 
171
      if (exp < 0)
 
172
        {
 
173
          /* underflow */
 
174
          exp = 0;
 
175
          mant = 0;
 
176
          FP_RAISE (E);
 
177
        }
 
178
      if (exp >= 255)
 
179
        {
 
180
          /* overflow */
 
181
          exp = 255;
 
182
          mant = 0;
 
183
          FP_RAISE (O);
 
184
        }
 
185
    }
 
186
  mant &= 0x007fffffUL;
 
187
  exp &= 0xff;
 
188
  mant |= exp << 23;
 
189
  if (p->sign < 0)
 
190
    mant |= 0x80000000UL;
 
191
 
 
192
  return mant;
 
193
}
 
194
 
 
195
typedef union {
 
196
  unsigned long long ll;
 
197
  double d;
 
198
} U_d_ll;
 
199
 
 
200
static int checked_format = 0;
 
201
 
 
202
/* We assume a double format like this:
 
203
   S[1] E[11] M[52]
 
204
*/
 
205
 
 
206
static double
 
207
fp_to_double (FP_Parts *p)
 
208
{
 
209
  U_d_ll u;
 
210
 
 
211
  if (!checked_format)
 
212
    {
 
213
      u.d = 1.5;
 
214
      if (u.ll != 0x3ff8000000000000ULL)
 
215
        abort ();
 
216
      u.d = -225;
 
217
      if (u.ll != 0xc06c200000000000ULL)
 
218
        abort ();
 
219
      u.d = 10.1;
 
220
      if (u.ll != 0x4024333333333333ULL)
 
221
        abort ();
 
222
      checked_format = 1;
 
223
    }
 
224
 
 
225
  u.ll = 0;
 
226
  if (p->sign < 0)
 
227
    u.ll |= (1ULL << 63);
 
228
  /* Make sure a zero encoding stays a zero.  */
 
229
  if (p->exp != -EXP_BIAS)
 
230
    u.ll |= ((unsigned long long)p->exp + 1023ULL) << 52;
 
231
  u.ll |= (unsigned long long) (p->mant & 0x007fffffUL) << (52 - 23);
 
232
  return u.d;
 
233
}
 
234
 
 
235
static void
 
236
double_to_fp (double d, FP_Parts *p)
 
237
{
 
238
  int exp;
 
239
  U_d_ll u;
 
240
  int sign;
 
241
 
 
242
  u.d = d;
 
243
 
 
244
  sign = (u.ll & 0x8000000000000000ULL) ? 1 : 0;
 
245
  exp = u.ll >> 52;
 
246
  exp = (exp & 0x7ff);
 
247
 
 
248
  if (exp == 0)
 
249
    {
 
250
      /* A generated denormal should show up as an underflow, not
 
251
         here.  */
 
252
      if (sign)
 
253
        fp_explode (MINUS_ZERO, p);
 
254
      else
 
255
        fp_explode (PLUS_ZERO, p);
 
256
      return;
 
257
    }
 
258
 
 
259
  exp = exp - 1023;
 
260
  if ((exp + EXP_BIAS) > 254)
 
261
    {
 
262
      FP_RAISE (O);
 
263
      switch (regs.r_fpsw & FPSWBITS_RM)
 
264
        {
 
265
        case FPRM_NEAREST:
 
266
          if (sign)
 
267
            fp_explode (MINUS_INF, p);
 
268
          else
 
269
            fp_explode (PLUS_INF, p);
 
270
          break;
 
271
        case FPRM_ZERO:
 
272
          if (sign)
 
273
            fp_explode (MINUS_MAX, p);
 
274
          else
 
275
            fp_explode (PLUS_MAX, p);
 
276
          break;
 
277
        case FPRM_PINF:
 
278
          if (sign)
 
279
            fp_explode (MINUS_MAX, p);
 
280
          else
 
281
            fp_explode (PLUS_INF, p);
 
282
          break;
 
283
        case FPRM_NINF:
 
284
          if (sign)
 
285
            fp_explode (MINUS_INF, p);
 
286
          else
 
287
            fp_explode (PLUS_MAX, p);
 
288
          break;
 
289
        }
 
290
      return;
 
291
    }
 
292
  if ((exp + EXP_BIAS) < 1)
 
293
    {
 
294
      if (sign)
 
295
        fp_explode (MINUS_ZERO, p);
 
296
      else
 
297
        fp_explode (PLUS_ZERO, p);
 
298
      FP_RAISE (U);
 
299
    }
 
300
 
 
301
  p->sign = sign ? -1 : 1;
 
302
  p->exp = exp;
 
303
  p->mant = u.ll >> (52-23) & 0x007fffffUL;
 
304
  p->mant |= 0x00800000UL;
 
305
  p->type = FP_NORMAL;
 
306
 
 
307
  if (u.ll & 0x1fffffffULL)
 
308
    {
 
309
      switch (regs.r_fpsw & FPSWBITS_RM)
 
310
        {
 
311
        case FPRM_NEAREST:
 
312
          if (u.ll & 0x10000000ULL)
 
313
            p->mant ++;
 
314
          break;
 
315
        case FPRM_ZERO:
 
316
          break;
 
317
        case FPRM_PINF:
 
318
          if (sign == 1)
 
319
            p->mant ++;
 
320
          break;
 
321
        case FPRM_NINF:
 
322
          if (sign == -1)
 
323
            p->mant ++;
 
324
          break;
 
325
        }
 
326
      FP_RAISE (X);
 
327
    }
 
328
 
 
329
}
 
330
 
 
331
typedef enum {
 
332
  eNR,          /* Use the normal result.  */
 
333
  ePZ, eNZ,     /* +- zero */
 
334
  eSZ,          /* signed zero - XOR signs of ops together.  */
 
335
  eRZ,          /* +- zero depending on rounding mode.  */
 
336
  ePI, eNI,     /* +- Infinity */
 
337
  eSI,          /* signed infinity - XOR signs of ops together.  */
 
338
  eQN, eSN,     /* Quiet/Signalling NANs */
 
339
  eIn,          /* Invalid.  */
 
340
  eUn,          /* Unimplemented.  */
 
341
  eDZ,          /* Divide-by-zero.  */
 
342
  eLT,          /* less than */
 
343
  eGT,          /* greater than */
 
344
  eEQ,          /* equal to */
 
345
} FP_ExceptionCases;
 
346
 
 
347
#if defined DEBUG0
 
348
static const char *ex_names[] = {
 
349
  "NR", "PZ", "NZ", "SZ", "RZ", "PI", "NI", "SI", "QN", "SN", "IN", "Un", "DZ", "LT", "GT", "EQ"
 
350
};
 
351
#endif
 
352
 
 
353
/* This checks for all exceptional cases (not all FP exceptions) and
 
354
   returns TRUE if it is providing the result in *c.  If it returns
 
355
   FALSE, the caller should do the "normal" operation.  */
 
356
int
 
357
check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c,
 
358
                  FP_ExceptionCases ex_tab[5][5], 
 
359
                  FP_ExceptionCases *case_ret)
 
360
{
 
361
  FP_ExceptionCases fpec;
 
362
 
 
363
  if (a->type == FP_SNAN
 
364
      || b->type == FP_SNAN)
 
365
    fpec = eIn;
 
366
  else if (a->type == FP_QNAN
 
367
           || b->type == FP_QNAN)
 
368
    fpec = eQN;
 
369
  else if (a->type == FP_DENORMAL
 
370
           || b->type == FP_DENORMAL)
 
371
    fpec = eUn;
 
372
  else
 
373
    fpec = ex_tab[(int)(a->type)][(int)(b->type)];
 
374
 
 
375
  /*printf("%s %s -> %s\n", fpt_names[(int)(a->type)], fpt_names[(int)(b->type)], ex_names[(int)(fpec)]);*/
 
376
 
 
377
  if (case_ret)
 
378
    *case_ret = fpec;
 
379
 
 
380
  switch (fpec)
 
381
    {
 
382
    case eNR:   /* Use the normal result.  */
 
383
      return 0;
 
384
 
 
385
    case ePZ:   /* + zero */
 
386
      *c = 0x00000000;
 
387
      return 1;
 
388
 
 
389
    case eNZ:   /* - zero */
 
390
      *c = 0x80000000;
 
391
      return 1;
 
392
 
 
393
    case eSZ:   /* signed zero */
 
394
      *c = (a->sign == b->sign) ? PLUS_ZERO : MINUS_ZERO;
 
395
      return 1;
 
396
 
 
397
    case eRZ:   /* +- zero depending on rounding mode.  */
 
398
      if ((regs.r_fpsw & FPSWBITS_RM) == FPRM_NINF)
 
399
        *c = 0x80000000;
 
400
      else
 
401
        *c = 0x00000000;
 
402
      return 1;
 
403
 
 
404
    case ePI:   /* + Infinity */
 
405
      *c = 0x7F800000;
 
406
      return 1;
 
407
 
 
408
    case eNI:   /* - Infinity */
 
409
      *c = 0xFF800000;
 
410
      return 1;
 
411
 
 
412
    case eSI:   /* sign Infinity */
 
413
      *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
 
414
      return 1;
 
415
 
 
416
    case eQN:   /* Quiet NANs */
 
417
      if (a->type == FP_QNAN)
 
418
        *c = a->orig_value;
 
419
      else
 
420
        *c = b->orig_value;
 
421
      return 1;
 
422
 
 
423
    case eSN:   /* Signalling NANs */
 
424
      if (a->type == FP_SNAN)
 
425
        *c = a->orig_value;
 
426
      else
 
427
        *c = b->orig_value;
 
428
      FP_RAISE (V);
 
429
      return 1;
 
430
 
 
431
    case eIn:   /* Invalid.  */
 
432
      FP_RAISE (V);
 
433
      if (a->type == FP_SNAN)
 
434
        *c = a->orig_value | 0x00400000;
 
435
      else if  (a->type == FP_SNAN)
 
436
        *c = b->orig_value | 0x00400000;
 
437
      else
 
438
        *c = 0x7fc00000;
 
439
      return 1;
 
440
 
 
441
    case eUn:   /* Unimplemented.  */
 
442
      FP_RAISE (E);
 
443
      return 1;
 
444
 
 
445
    case eDZ:   /* Division-by-zero.  */
 
446
      *c = (a->sign == b->sign) ? PLUS_INF : MINUS_INF;
 
447
      FP_RAISE (Z);
 
448
      return 1;
 
449
 
 
450
    default:
 
451
      return 0;
 
452
    }
 
453
}
 
454
 
 
455
#define CHECK_EXCEPTIONS(FPPa, FPPb, fpc, ex_tab) \
 
456
  if (check_exceptions (&FPPa, &FPPb, &fpc, ex_tab, 0)) \
 
457
    return fpc;
 
458
 
 
459
/* For each operation, we have two tables of how nonnormal cases are
 
460
   handled.  The DN=0 case is first, followed by the DN=1 case, with
 
461
   each table using the following layout: */
 
462
 
 
463
static FP_ExceptionCases ex_add_tab[5][5] = {
 
464
  /* N   +0   -0   +In  -In */
 
465
  { eNR, eNR, eNR, ePI, eNI }, /* Normal */
 
466
  { eNR, ePZ, eRZ, ePI, eNI }, /* +0   */
 
467
  { eNR, eRZ, eNZ, ePI, eNI }, /* -0   */
 
468
  { ePI, ePI, ePI, ePI, eIn }, /* +Inf */
 
469
  { eNI, eNI, eNI, eIn, eNI }, /* -Inf */
 
470
};
 
471
 
 
472
fp_t
 
473
rxfp_add (fp_t fa, fp_t fb)
 
474
{
 
475
  FP_Parts a, b, c;
 
476
  fp_t rv;
 
477
  double da, db;
 
478
 
 
479
  fp_explode (fa, &a);
 
480
  fp_explode (fb, &b);
 
481
  CHECK_EXCEPTIONS (a, b, rv, ex_add_tab);
 
482
 
 
483
  da = fp_to_double (&a);
 
484
  db = fp_to_double (&b);
 
485
  tprintf("%g + %g = %g\n", da, db, da+db);
 
486
 
 
487
  double_to_fp (da+db, &c);
 
488
  rv = fp_implode (&c);
 
489
  return rv;
 
490
}
 
491
 
 
492
static FP_ExceptionCases ex_sub_tab[5][5] = {
 
493
  /* N   +0   -0   +In  -In */
 
494
  { eNR, eNR, eNR, eNI, ePI }, /* Normal */
 
495
  { eNR, eRZ, ePZ, eNI, ePI }, /* +0   */
 
496
  { eNR, eNZ, eRZ, eNI, ePI }, /* -0   */
 
497
  { ePI, ePI, ePI, eIn, ePI }, /* +Inf */
 
498
  { eNI, eNI, eNI, eNI, eIn }, /* -Inf */
 
499
};
 
500
 
 
501
fp_t
 
502
rxfp_sub (fp_t fa, fp_t fb)
 
503
{
 
504
  FP_Parts a, b, c;
 
505
  fp_t rv;
 
506
  double da, db;
 
507
 
 
508
  fp_explode (fa, &a);
 
509
  fp_explode (fb, &b);
 
510
  CHECK_EXCEPTIONS (a, b, rv, ex_sub_tab);
 
511
 
 
512
  da = fp_to_double (&a);
 
513
  db = fp_to_double (&b);
 
514
  tprintf("%g - %g = %g\n", da, db, da-db);
 
515
 
 
516
  double_to_fp (da-db, &c);
 
517
  rv = fp_implode (&c);
 
518
 
 
519
  return rv;
 
520
}
 
521
 
 
522
static FP_ExceptionCases ex_mul_tab[5][5] = {
 
523
  /* N   +0   -0   +In  -In */
 
524
  { eNR, eNR, eNR, eSI, eSI }, /* Normal */
 
525
  { eNR, ePZ, eNZ, eIn, eIn }, /* +0   */
 
526
  { eNR, eNZ, ePZ, eIn, eIn }, /* -0   */
 
527
  { eSI, eIn, eIn, ePI, eNI }, /* +Inf */
 
528
  { eSI, eIn, eIn, eNI, ePI }, /* -Inf */
 
529
};
 
530
 
 
531
fp_t
 
532
rxfp_mul (fp_t fa, fp_t fb)
 
533
{
 
534
  FP_Parts a, b, c;
 
535
  fp_t rv;
 
536
  double da, db;
 
537
 
 
538
  fp_explode (fa, &a);
 
539
  fp_explode (fb, &b);
 
540
  CHECK_EXCEPTIONS (a, b, rv, ex_mul_tab);
 
541
 
 
542
  da = fp_to_double (&a);
 
543
  db = fp_to_double (&b);
 
544
  tprintf("%g x %g = %g\n", da, db, da*db);
 
545
 
 
546
  double_to_fp (da*db, &c);
 
547
  rv = fp_implode (&c);
 
548
 
 
549
  return rv;
 
550
}
 
551
 
 
552
static FP_ExceptionCases ex_div_tab[5][5] = {
 
553
  /* N   +0   -0   +In  -In */
 
554
  { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */
 
555
  { eSZ, eIn, eIn, ePZ, eNZ }, /* +0   */
 
556
  { eSZ, eIn, eIn, eNZ, ePZ }, /* -0   */
 
557
  { eSI, ePI, eNI, eIn, eIn }, /* +Inf */
 
558
  { eSI, eNI, ePI, eIn, eIn }, /* -Inf */
 
559
};
 
560
 
 
561
fp_t
 
562
rxfp_div (fp_t fa, fp_t fb)
 
563
{
 
564
  FP_Parts a, b, c;
 
565
  fp_t rv;
 
566
  double da, db;
 
567
 
 
568
  fp_explode (fa, &a);
 
569
  fp_explode (fb, &b);
 
570
  CHECK_EXCEPTIONS (a, b, rv, ex_div_tab);
 
571
 
 
572
  da = fp_to_double (&a);
 
573
  db = fp_to_double (&b);
 
574
  tprintf("%g / %g = %g\n", da, db, da/db);
 
575
 
 
576
  double_to_fp (da/db, &c);
 
577
  rv = fp_implode (&c);
 
578
 
 
579
  return rv;
 
580
}
 
581
 
 
582
static FP_ExceptionCases ex_cmp_tab[5][5] = {
 
583
  /* N   +0   -0   +In  -In */
 
584
  { eNR, eNR, eNR, eLT, eGT }, /* Normal */
 
585
  { eNR, eEQ, eEQ, eLT, eGT }, /* +0   */
 
586
  { eNR, eEQ, eEQ, eLT, eGT }, /* -0   */
 
587
  { eGT, eGT, eGT, eEQ, eGT }, /* +Inf */
 
588
  { eLT, eLT, eLT, eLT, eEQ }, /* -Inf */
 
589
};
 
590
 
 
591
void
 
592
rxfp_cmp (fp_t fa, fp_t fb)
 
593
{
 
594
  FP_Parts a, b;
 
595
  fp_t c;
 
596
  FP_ExceptionCases reason;
 
597
  int flags = 0;
 
598
  double da, db;
 
599
 
 
600
  fp_explode (fa, &a);
 
601
  fp_explode (fb, &b);
 
602
 
 
603
  if (check_exceptions (&a, &b, &c, ex_cmp_tab, &reason))
 
604
    {
 
605
      if (reason == eQN)
 
606
        {
 
607
          /* Special case - incomparable.  */
 
608
          set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, FLAGBIT_O);
 
609
          return;
 
610
        }
 
611
      return;
 
612
    }
 
613
 
 
614
  switch (reason)
 
615
    {
 
616
    case eEQ:
 
617
      flags = FLAGBIT_Z;
 
618
      break;
 
619
    case eLT:
 
620
      flags = FLAGBIT_S;
 
621
      break;
 
622
    case eGT:
 
623
      flags = 0;
 
624
      break;
 
625
    case eNR:
 
626
      da = fp_to_double (&a);
 
627
      db = fp_to_double (&b);
 
628
      tprintf("fcmp: %g cmp %g\n", da, db);
 
629
      if (da < db)
 
630
        flags = FLAGBIT_S;
 
631
      else if (da == db)
 
632
        flags = FLAGBIT_Z;
 
633
      else
 
634
        flags = 0;
 
635
      break;
 
636
    default:
 
637
      abort();
 
638
    }
 
639
 
 
640
  set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, flags);
 
641
}
 
642
 
 
643
long
 
644
rxfp_ftoi (fp_t fa, int round_mode)
 
645
{
 
646
  FP_Parts a;
 
647
  fp_t rv;
 
648
  int sign;
 
649
  int whole_bits, frac_bits;
 
650
 
 
651
  fp_explode (fa, &a);
 
652
  sign = fa & 0x80000000UL;
 
653
 
 
654
  switch (a.type)
 
655
    {
 
656
    case FP_NORMAL:
 
657
      break;
 
658
    case FP_PZERO:
 
659
    case FP_NZERO:
 
660
      return 0;
 
661
    case FP_PINFINITY:
 
662
      FP_RAISE (V);
 
663
      return 0x7fffffffL;
 
664
    case FP_NINFINITY:
 
665
      FP_RAISE (V);
 
666
      return 0x80000000L;
 
667
    case FP_DENORMAL:
 
668
      FP_RAISE (E);
 
669
      return 0;
 
670
    case FP_QNAN:
 
671
    case FP_SNAN:
 
672
      FP_RAISE (V);
 
673
      return sign ? 0x80000000U : 0x7fffffff;
 
674
    }
 
675
 
 
676
  if (a.exp >= 31)
 
677
    {
 
678
      FP_RAISE (V);
 
679
      return sign ? 0x80000000U : 0x7fffffff;
 
680
    }
 
681
 
 
682
  a.exp -= 23;
 
683
 
 
684
  if (a.exp <= -25)
 
685
    {
 
686
      /* Less than 0.49999 */
 
687
      frac_bits = a.mant;
 
688
      whole_bits = 0;
 
689
    }
 
690
  else if (a.exp < 0)
 
691
    {
 
692
      frac_bits = a.mant << (32 + a.exp);
 
693
      whole_bits = a.mant >> (-a.exp);
 
694
    }
 
695
  else
 
696
    {
 
697
      frac_bits = 0;
 
698
      whole_bits = a.mant << a.exp;
 
699
    }
 
700
 
 
701
  if (frac_bits)
 
702
    {
 
703
      switch (round_mode & 3)
 
704
        {
 
705
        case FPRM_NEAREST:
 
706
          if (frac_bits & 0x80000000UL)
 
707
            whole_bits ++;
 
708
          break;
 
709
        case FPRM_ZERO:
 
710
          break;
 
711
        case FPRM_PINF:
 
712
          if (!sign)
 
713
            whole_bits ++;
 
714
          break;
 
715
        case FPRM_NINF:
 
716
          if (sign)
 
717
            whole_bits ++;
 
718
          break;
 
719
        }
 
720
    }
 
721
 
 
722
  rv = sign ? -whole_bits : whole_bits;
 
723
  
 
724
  return rv;
 
725
}
 
726
 
 
727
fp_t
 
728
rxfp_itof (long fa, int round_mode)
 
729
{
 
730
  fp_t rv;
 
731
  int sign = 0;
 
732
  unsigned int frac_bits;
 
733
  volatile unsigned int whole_bits;
 
734
  FP_Parts a;
 
735
 
 
736
  if (fa == 0)
 
737
    return PLUS_ZERO;
 
738
 
 
739
  if (fa < 0)
 
740
    {
 
741
      fa = -fa;
 
742
      sign = 1;
 
743
      a.sign = -1;
 
744
    }
 
745
  else
 
746
    a.sign = 1;
 
747
 
 
748
  whole_bits = fa;
 
749
  a.exp = 31;
 
750
 
 
751
  while (! (whole_bits & 0x80000000UL))
 
752
    {
 
753
      a.exp --;
 
754
      whole_bits <<= 1;
 
755
    }
 
756
  frac_bits = whole_bits & 0xff;
 
757
  whole_bits = whole_bits >> 8;
 
758
 
 
759
  if (frac_bits)
 
760
    {
 
761
      /* We must round */
 
762
      switch (round_mode & 3)
 
763
        {
 
764
        case FPRM_NEAREST:
 
765
          if (frac_bits & 0x80)
 
766
            whole_bits ++;
 
767
          break;
 
768
        case FPRM_ZERO:
 
769
          break;
 
770
        case FPRM_PINF:
 
771
          if (!sign)
 
772
            whole_bits ++;
 
773
          break;
 
774
        case FPRM_NINF:
 
775
          if (sign)
 
776
            whole_bits ++;
 
777
          break;
 
778
        }
 
779
    }
 
780
 
 
781
  a.mant = whole_bits;
 
782
  if (whole_bits & 0xff000000UL)
 
783
    {
 
784
      a.mant >>= 1;
 
785
      a.exp ++;
 
786
    }
 
787
 
 
788
  rv = fp_implode (&a);
 
789
  return rv;
 
790
}
 
791