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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [common/] [sim-fpu.h] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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