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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [common/] [sim-fpu.h] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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