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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [sim/] [common/] [sim-fpu.h] - Blame information for rev 855

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

Line No. Rev Author Line
1 330 jeremybenn
/* Simulator Floating-point support.
2
 
3
   Copyright 1997, 1998, 2002, 2003, 2007, 2008, 2009, 2010
4
   Free Software Foundation, Inc.
5
 
6
   Contributed by Cygnus Support.
7
 
8
This file is part of GDB, the GNU debugger.
9
 
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 3 of the License, or
13
(at your option) any later version.
14
 
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
GNU General Public License for more details.
19
 
20
You should have received a copy of the GNU General Public License
21
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
 
24
 
25
#ifndef SIM_FPU_H
26
#define SIM_FPU_H
27
 
28
 
29
 
30
/* The FPU intermediate type - this object, passed by reference,
31
   should be treated as opaque.
32
 
33
 
34
   Pragmatics - pass struct by ref:
35
 
36
   The alternatives for this object/interface that were considered
37
   were: a packed 64 bit value; an unpacked structure passed by value;
38
   and an unpacked structure passed by reference.
39
 
40
   The packed 64 bit value was rejected because: it limited the
41
   precision of intermediate values; reasonable performance would only
42
   be achieved when the sim_fpu package was in-lined allowing repeated
43
   unpacking operations to be eliminated.
44
 
45
   For unpacked structures (passed by value and reference), the code
46
   quality of GCC-2.7 (on x86) for each alternative was compared.
47
   Needless to say the results, while better than for a packed 64 bit
48
   object, were still poor (GCC had only limited support for the
49
   optimization of references to structure members).  Regardless, the
50
   struct-by-ref alternative achieved better results when compiled
51
   with (better speed) and without (better code density) in-lining.
52
   Here's looking forward to an improved GCC optimizer.
53
 
54
 
55
   Pragmatics - avoid host FP hardware:
56
 
57
   FP operations can be implemented by either: the host's floating
58
   point hardware; or by emulating the FP operations using integer
59
   only routines.  This is direct tradeoff between speed, portability
60
   and correctness.
61
 
62
   The two principal reasons for selecting portability and correctness
63
   over speed are:
64
 
65
   1 - Correctness.  The assumption that FP correctness wasn't an
66
   issue for code being run on simulators was wrong.  Instead of
67
   running FP tolerant (?) code, simulator users instead typically run
68
   very aggressive FP code sequences.  The sole purpose of those
69
   sequences being to test the target ISA's FP implementation.
70
 
71
   2 - Portability.  The host FP implementation is not predictable.  A
72
   simulator modeling aggressive FP code sequences using the hosts FPU
73
   relies heavily on the correctness of the hosts FP implementation.
74
   It turns out that such trust can be misplaced.  The behavior of
75
   host FP implementations when handling edge conditions such as SNaNs
76
   and exceptions varied widely.
77
 
78
 
79
   */
80
 
81
 
82
typedef enum
83
{
84
  sim_fpu_class_zero,
85
  sim_fpu_class_snan,
86
  sim_fpu_class_qnan,
87
  sim_fpu_class_number,
88
  sim_fpu_class_denorm,
89
  sim_fpu_class_infinity,
90
} sim_fpu_class;
91
 
92
typedef struct _sim_fpu {
93
  sim_fpu_class class;
94
  int sign;
95
  unsigned64 fraction;
96
  int normal_exp;
97
} sim_fpu;
98
 
99
 
100
 
101
/* Rounding options.
102
 
103
   The value zero (sim_fpu_round_default) for ALU operations indicates
104
   that, when possible, rounding should be avoided. */
105
 
106
typedef enum
107
{
108
  sim_fpu_round_default = 0,
109
  sim_fpu_round_near = 1,
110
  sim_fpu_round_zero = 2,
111
  sim_fpu_round_up = 3,
112
  sim_fpu_round_down = 4,
113
} sim_fpu_round;
114
 
115
 
116
/* Options when handling denormalized numbers.  */
117
 
118
typedef enum
119
{
120
  sim_fpu_denorm_default = 0,
121
  sim_fpu_denorm_underflow_inexact = 1,
122
  sim_fpu_denorm_zero = 2,
123
} sim_fpu_denorm;
124
 
125
 
126
 
127
/* Status values returned by FPU operators.
128
 
129
   When checking the result of an FP sequence (ex 32to, add, single,
130
   to32) the caller may either: check the return value of each FP
131
   operator; or form the union (OR) of the returned values and examine
132
   them once at the end.
133
 
134
   FIXME: This facility is still being developed.  The choice of
135
   status values returned and their exact meaning may changed in the
136
   future.  */
137
 
138
typedef enum
139
{
140
  sim_fpu_status_invalid_snan = 1,
141
  sim_fpu_status_invalid_qnan = 2,
142
  sim_fpu_status_invalid_isi = 4, /* (inf - inf) */
143
  sim_fpu_status_invalid_idi = 8, /* (inf / inf) */
144
  sim_fpu_status_invalid_zdz = 16, /* (0 / 0) */
145
  sim_fpu_status_invalid_imz = 32, /* (inf * 0) */
146
  sim_fpu_status_invalid_cvi = 64, /* convert to integer */
147
  sim_fpu_status_invalid_div0 = 128, /* (X / 0) */
148
  sim_fpu_status_invalid_cmp = 256, /* compare */
149
  sim_fpu_status_invalid_sqrt = 512,
150
  sim_fpu_status_rounded = 1024,
151
  sim_fpu_status_inexact = 2048,
152
  sim_fpu_status_overflow = 4096,
153
  sim_fpu_status_underflow = 8192,
154
  sim_fpu_status_denorm = 16384,
155
} sim_fpu_status;
156
 
157
 
158
 
159
 
160
/* Directly map between a 32/64 bit register and the sim_fpu internal
161
   type.
162
 
163
   When converting from the 32/64 bit packed format to the sim_fpu
164
   internal type, the operation is exact.
165
 
166
   When converting from the sim_fpu internal type to 32/64 bit packed
167
   format, the operation may result in a loss of precision. The
168
   configuration macro WITH_FPU_CONVERSION controls this.  By default,
169
   silent round to nearest is performed.  Alternatively, round up,
170
   round down and round to zero can be performed.  In a simulator
171
   emulating exact FPU behavior, sim_fpu_round_{32,64} should be
172
   called before packing the sim_fpu value.  */
173
 
174
INLINE_SIM_FPU (void) sim_fpu_32to (sim_fpu *f, unsigned32 s);
175
INLINE_SIM_FPU (void) sim_fpu_232to (sim_fpu *f, unsigned32 h, unsigned32 l);
176
INLINE_SIM_FPU (void) sim_fpu_64to (sim_fpu *f, unsigned64 d);
177
 
178
INLINE_SIM_FPU (void) sim_fpu_to32 (unsigned32 *s, const sim_fpu *f);
179
INLINE_SIM_FPU (void) sim_fpu_to232 (unsigned32 *h, unsigned32 *l, const sim_fpu *f);
180
INLINE_SIM_FPU (void) sim_fpu_to64 (unsigned64 *d, const sim_fpu *f);
181
 
182
 
183
/* Create a sim_fpu struct using raw information.  (FRACTION & LSMASK
184
   (PRECISION-1, 0)) is assumed to contain the fraction part of the
185
   floating-point number.  The leading bit LSBIT (PRECISION) is always
186
   implied.  The number created can be represented by:
187
 
188
   (SIGN ? "-" : "+") "1." FRACTION{PRECISION-1,0} X 2 ^ NORMAL_EXP>
189
 
190
   You can not specify zero using this function. */
191
 
192
INLINE_SIM_FPU (void) sim_fpu_fractionto (sim_fpu *f, int sign, int normal_exp, unsigned64 fraction, int precision);
193
 
194
/* Reverse operation.  If S is a non-zero number, discards the implied
195
   leading one and returns PRECISION fraction bits.  No rounding is
196
   performed. */
197
INLINE_SIM_FPU (unsigned64) sim_fpu_tofraction (const sim_fpu *s, int precision);
198
 
199
 
200
 
201
/* Rounding operators.
202
 
203
   Force an intermediate result to an exact 32/64 bit
204
   representation. */
205
 
206
INLINE_SIM_FPU (int) sim_fpu_round_32 (sim_fpu *f,
207
                                       sim_fpu_round round,
208
                                       sim_fpu_denorm denorm);
209
INLINE_SIM_FPU (int) sim_fpu_round_64 (sim_fpu *f,
210
                                       sim_fpu_round round,
211
                                       sim_fpu_denorm denorm);
212
 
213
 
214
 
215
/* Arithmetic operators.
216
 
217
   FIXME: In the future, additional arguments ROUNDING and BITSIZE may
218
   be added. */
219
 
220
typedef int (sim_fpu_op1) (sim_fpu *f,
221
                           const sim_fpu *l);
222
typedef int (sim_fpu_op2) (sim_fpu *f,
223
                           const sim_fpu *l,
224
                           const sim_fpu *r);
225
 
226
INLINE_SIM_FPU (int) sim_fpu_add (sim_fpu *f,
227
                                  const sim_fpu *l, const sim_fpu *r);
228
INLINE_SIM_FPU (int) sim_fpu_sub (sim_fpu *f,
229
                                  const sim_fpu *l, const sim_fpu *r);
230
INLINE_SIM_FPU (int) sim_fpu_mul (sim_fpu *f,
231
                                  const sim_fpu *l, const sim_fpu *r);
232
INLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
233
                                  const sim_fpu *l, const sim_fpu *r);
234
INLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f,
235
                                  const sim_fpu *l, const sim_fpu *r);
236
INLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
237
                                  const sim_fpu *l, const sim_fpu *r);
238
INLINE_SIM_FPU (int) sim_fpu_neg (sim_fpu *f,
239
                                  const sim_fpu *a);
240
INLINE_SIM_FPU (int) sim_fpu_abs (sim_fpu *f,
241
                                  const sim_fpu *a);
242
INLINE_SIM_FPU (int) sim_fpu_inv (sim_fpu *f,
243
                                  const sim_fpu *a);
244
INLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f,
245
                                   const sim_fpu *sqr);
246
 
247
 
248
 
249
/* Conversion of integer <-> floating point. */
250
 
251
INLINE_SIM_FPU (int) sim_fpu_i32to (sim_fpu *f, signed32 i,
252
                                    sim_fpu_round round);
253
INLINE_SIM_FPU (int) sim_fpu_u32to (sim_fpu *f, unsigned32 u,
254
                                    sim_fpu_round round);
255
INLINE_SIM_FPU (int) sim_fpu_i64to (sim_fpu *f, signed64 i,
256
                                    sim_fpu_round round);
257
INLINE_SIM_FPU (int) sim_fpu_u64to (sim_fpu *f, unsigned64 u,
258
                                    sim_fpu_round round);
259
#if 0
260
INLINE_SIM_FPU (int) sim_fpu_i232to (sim_fpu *f, signed32 h, signed32 l,
261
                                     sim_fpu_round round);
262
#endif
263
#if 0
264
INLINE_SIM_FPU (int) sim_fpu_u232to (sim_fpu *f, unsigned32 h, unsigned32 l,
265
                                     sim_fpu_round round);
266
#endif
267
 
268
INLINE_SIM_FPU (int) sim_fpu_to32i (signed32 *i, const sim_fpu *f,
269
                                    sim_fpu_round round);
270
INLINE_SIM_FPU (int) sim_fpu_to32u (unsigned32 *u, const sim_fpu *f,
271
                                    sim_fpu_round round);
272
INLINE_SIM_FPU (int) sim_fpu_to64i (signed64 *i, const sim_fpu *f,
273
                                    sim_fpu_round round);
274
INLINE_SIM_FPU (int) sim_fpu_to64u (unsigned64 *u, const sim_fpu *f,
275
                                    sim_fpu_round round);
276
#if 0
277
INLINE_SIM_FPU (int) sim_fpu_to232i (signed64 *h, signed64 *l, const sim_fpu *f,
278
                                     sim_fpu_round round);
279
#endif
280
#if 0
281
INLINE_SIM_FPU (int) sim_fpu_to232u (unsigned64 *h, unsigned64 *l, const sim_fpu *f,
282
                                     sim_fpu_round round);
283
#endif
284
 
285
 
286
/* Conversion of internal sim_fpu type to host double format.
287
 
288
   For debugging/tracing only.  A SNaN is never returned. */
289
 
290
/* INLINE_SIM_FPU (float) sim_fpu_2f (const sim_fpu *f); */
291
INLINE_SIM_FPU (double) sim_fpu_2d (const sim_fpu *d);
292
 
293
/* INLINE_SIM_FPU (void) sim_fpu_f2 (sim_fpu *f, float s); */
294
INLINE_SIM_FPU (void) sim_fpu_d2 (sim_fpu *f, double d);
295
 
296
 
297
 
298
/* Specific number classes.
299
 
300
   NB: When either, a 32/64 bit floating points is converted to
301
   internal format, or an internal format number is rounded to 32/64
302
   bit precision, a special marker is retained that indicates that the
303
   value was normalized.  For such numbers both is_number and
304
   is_denorm return true. */
305
 
306
INLINE_SIM_FPU (int) sim_fpu_is_nan (const sim_fpu *s); /* 1 => SNaN or QNaN */
307
INLINE_SIM_FPU (int) sim_fpu_is_snan (const sim_fpu *s); /* 1 => SNaN */
308
INLINE_SIM_FPU (int) sim_fpu_is_qnan (const sim_fpu *s); /* 1 => QNaN */
309
 
310
INLINE_SIM_FPU (int) sim_fpu_is_zero (const sim_fpu *s);
311
INLINE_SIM_FPU (int) sim_fpu_is_infinity (const sim_fpu *s);
312
INLINE_SIM_FPU (int) sim_fpu_is_number (const sim_fpu *s); /* !zero */
313
INLINE_SIM_FPU (int) sim_fpu_is_denorm (const sim_fpu *s); /* !zero */
314
 
315
 
316
 
317
/* Floating point fields */
318
 
319
INLINE_SIM_FPU (int) sim_fpu_sign (const sim_fpu *s);
320
INLINE_SIM_FPU (int) sim_fpu_exp (const sim_fpu *s);
321
INLINE_SIM_FPU (unsigned64) sim_fpu_fraction (const sim_fpu *s);
322
INLINE_SIM_FPU (unsigned64) sim_fpu_guard (const sim_fpu *s, int is_double);
323
 
324
 
325
 
326
/* Specific comparison operators
327
 
328
   For NaNs et al., the comparison operators will set IS to zero and
329
   return a nonzero result. */
330
 
331
INLINE_SIM_FPU (int) sim_fpu_lt (int *is, const sim_fpu *l, const sim_fpu *r);
332
INLINE_SIM_FPU (int) sim_fpu_le (int *is, const sim_fpu *l, const sim_fpu *r);
333
INLINE_SIM_FPU (int) sim_fpu_eq (int *is, const sim_fpu *l, const sim_fpu *r);
334
INLINE_SIM_FPU (int) sim_fpu_ne (int *is, const sim_fpu *l, const sim_fpu *r);
335
INLINE_SIM_FPU (int) sim_fpu_ge (int *is, const sim_fpu *l, const sim_fpu *r);
336
INLINE_SIM_FPU (int) sim_fpu_gt (int *is, const sim_fpu *l, const sim_fpu *r);
337
 
338
INLINE_SIM_FPU (int) sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r);
339
INLINE_SIM_FPU (int) sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r);
340
INLINE_SIM_FPU (int) sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r);
341
INLINE_SIM_FPU (int) sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r);
342
INLINE_SIM_FPU (int) sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r);
343
INLINE_SIM_FPU (int) sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r);
344
 
345
 
346
 
347
/* General number class and comparison operators.
348
 
349
   The result of the comparison is indicated by returning one of the
350
   values below.  Efficient emulation of a target FP compare
351
   instruction can be achieved by redefining the values below to match
352
   corresponding target FP status bits.
353
 
354
   For instance.  SIM_FPU_QNAN may be redefined to be the bit
355
   `INVALID' while SIM_FPU_NINF might be redefined as the bits
356
   `NEGATIVE | INFINITY | VALID'. */
357
 
358
#ifndef SIM_FPU_IS_SNAN
359
enum {
360
  SIM_FPU_IS_SNAN = 1, /* Noisy not-a-number */
361
  SIM_FPU_IS_QNAN = 2, /* Quiet not-a-number */
362
  SIM_FPU_IS_NINF = 3, /* -infinity */
363
  SIM_FPU_IS_PINF = 4, /* +infinity */
364
  SIM_FPU_IS_NNUMBER = 5, /* -number - [ -MAX .. -MIN ] */
365
  SIM_FPU_IS_PNUMBER = 6, /* +number - [ +MIN .. +MAX ] */
366
  SIM_FPU_IS_NDENORM = 7, /* -denorm - ( MIN .. 0 ) */
367
  SIM_FPU_IS_PDENORM = 8, /* +denorm - ( 0 .. MIN ) */
368
  SIM_FPU_IS_NZERO = 9, /* -0 */
369
  SIM_FPU_IS_PZERO = 10, /* +0 */
370
};
371
#endif
372
 
373
INLINE_SIM_FPU (int) sim_fpu_is (const sim_fpu *l);
374
INLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r);
375
 
376
 
377
 
378
/* A number of useful constants.  */
379
 
380
extern const sim_fpu sim_fpu_zero;
381
extern const sim_fpu sim_fpu_one;
382
extern const sim_fpu sim_fpu_two;
383
extern const sim_fpu sim_fpu_qnan;
384
extern const sim_fpu sim_fpu_max32;
385
extern const sim_fpu sim_fpu_max64;
386
 
387
 
388
/* Select the applicable functions for the fp_word type */
389
 
390
#if WITH_TARGET_FLOATING_POINT_BITSIZE == 32
391
#define sim_fpu_tofp sim_fpu_to32
392
#define sim_fpu_fpto sim_fpu_32to
393
#define sim_fpu_round_fp sim_fpu_round_32
394
#define sim_fpu_maxfp sim_fpu_max32
395
#endif
396
#if WITH_TARGET_FLOATING_POINT_BITSIZE == 64
397
#define sim_fpu_tofp sim_fpu_to64
398
#define sim_fpu_fpto sim_fpu_64to
399
#define sim_fpu_round_fp sim_fpu_round_64
400
#define sim_fpu_maxfp sim_fpu_max64
401
#endif
402
 
403
 
404
 
405
/* For debugging */
406
 
407
typedef void sim_fpu_print_func (void *, const char *, ...);
408
 
409
/* Print a sim_fpu with full precision.  */
410
INLINE_SIM_FPU (void) sim_fpu_print_fpu (const sim_fpu *f,
411
                                         sim_fpu_print_func *print,
412
                                         void *arg);
413
 
414
/* Print a sim_fpu with `n' trailing digits.  */
415
INLINE_SIM_FPU (void) sim_fpu_printn_fpu (const sim_fpu *f,
416
                                          sim_fpu_print_func *print,
417
                                          int digits,
418
                                          void *arg);
419
 
420
INLINE_SIM_FPU (void) sim_fpu_print_status (int status,
421
                                            sim_fpu_print_func *print,
422
                                            void *arg);
423
 
424
#if H_REVEALS_MODULE_P (SIM_FPU_INLINE)
425
#include "sim-fpu.c"
426
#endif
427
 
428
#endif

powered by: WebSVN 2.1.0

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