1193323Sed/* Simulator Floating-point support.
2193323Sed
3193323Sed   Copyright 1997-2023 Free Software Foundation, Inc.
4193323Sed
5193323Sed   Contributed by Cygnus Support.
6193323Sed
7193323SedThis file is part of GDB, the GNU debugger.
8193323Sed
9193323SedThis program is free software; you can redistribute it and/or modify
10193323Sedit under the terms of the GNU General Public License as published by
11193323Sedthe Free Software Foundation; either version 3 of the License, or
12193323Sed(at your option) any later version.
13193323Sed
14193323SedThis program is distributed in the hope that it will be useful,
15193323Sedbut WITHOUT ANY WARRANTY; without even the implied warranty of
16193323SedMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17193323SedGNU General Public License for more details.
18193323Sed
19193323SedYou should have received a copy of the GNU General Public License
20193323Sedalong with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21239462Sdim
22239462Sdim
23239462Sdim
24193323Sed#ifndef SIM_FPU_H
25193323Sed#define SIM_FPU_H
26193323Sed
27204961Srdivacky
28193323Sed#include <stdbool.h>
29193323Sed
30193323Sed
31193323Sed/* The FPU intermediate type - this object, passed by reference,
32193323Sed   should be treated as opaque.
33193323Sed
34193323Sed
35193323Sed   Pragmatics - pass struct by ref:
36193323Sed
37193323Sed   The alternatives for this object/interface that were considered
38193323Sed   were: a packed 64 bit value; an unpacked structure passed by value;
39193323Sed   and an unpacked structure passed by reference.
40198090Srdivacky
41198090Srdivacky   The packed 64 bit value was rejected because: it limited the
42198090Srdivacky   precision of intermediate values; reasonable performance would only
43198090Srdivacky   be achieved when the sim_fpu package was in-lined allowing repeated
44210299Sed   unpacking operations to be eliminated.
45210299Sed
46210299Sed   For unpacked structures (passed by value and reference), the code
47210299Sed   quality of GCC-2.7 (on x86) for each alternative was compared.
48210299Sed   Needless to say the results, while better than for a packed 64 bit
49210299Sed   object, were still poor (GCC had only limited support for the
50212904Sdim   optimization of references to structure members).  Regardless, the
51212904Sdim   struct-by-ref alternative achieved better results when compiled
52212904Sdim   with (better speed) and without (better code density) in-lining.
53212904Sdim   Here's looking forward to an improved GCC optimizer.
54193323Sed
55193323Sed
56193323Sed   Pragmatics - avoid host FP hardware:
57193323Sed
58193323Sed   FP operations can be implemented by either: the host's floating
59193323Sed   point hardware; or by emulating the FP operations using integer
60203954Srdivacky   only routines.  This is direct tradeoff between speed, portability
61203954Srdivacky   and correctness.
62208599Srdivacky
63193323Sed   The two principal reasons for selecting portability and correctness
64218893Sdim   over speed are:
65218893Sdim
66224145Sdim   1 - Correctness.  The assumption that FP correctness wasn't an
67224145Sdim   issue for code being run on simulators was wrong.  Instead of
68224145Sdim   running FP tolerant (?) code, simulator users instead typically run
69210299Sed   very aggressive FP code sequences.  The sole purpose of those
70210299Sed   sequences being to test the target ISA's FP implementation.
71212904Sdim
72212904Sdim   2 - Portability.  The host FP implementation is not predictable.  A
73212904Sdim   simulator modeling aggressive FP code sequences using the hosts FPU
74226633Sdim   relies heavily on the correctness of the hosts FP implementation.
75226633Sdim   It turns out that such trust can be misplaced.  The behavior of
76226633Sdim   host FP implementations when handling edge conditions such as SNaNs
77226633Sdim   and exceptions varied widely.
78226633Sdim
79226633Sdim
80226633Sdim   */
81226633Sdim
82226633Sdim
83226633Sdimtypedef enum
84226633Sdim{
85226633Sdim  sim_fpu_class_zero,
86243830Sdim  sim_fpu_class_snan,
87243830Sdim  sim_fpu_class_qnan,
88243830Sdim  sim_fpu_class_number,
89243830Sdim  sim_fpu_class_denorm,
90243830Sdim  sim_fpu_class_infinity,
91243830Sdim} sim_fpu_class;
92243830Sdim
93193323Sedtypedef struct _sim_fpu {
94193323Sed  sim_fpu_class class;
95218893Sdim  int sign;
96218893Sdim  uint64_t fraction;
97193323Sed  int normal_exp;
98193323Sed} sim_fpu;
99193323Sed
100243830Sdim
101193323Sed
102243830Sdim/* Rounding options.
103243830Sdim
104239462Sdim   The value zero (sim_fpu_round_default) for ALU operations indicates
105239462Sdim   that, when possible, rounding should be avoided. */
106239462Sdim
107239462Sdimtypedef enum
108193323Sed{
109193323Sed  sim_fpu_round_default = 0,
110218893Sdim  sim_fpu_round_near = 1,
111205407Srdivacky  sim_fpu_round_zero = 2,
112193323Sed  sim_fpu_round_up = 3,
113218893Sdim  sim_fpu_round_down = 4,
114205407Srdivacky} sim_fpu_round;
115193323Sed
116218893Sdim
117205407Srdivacky/* Options when handling denormalized numbers.  */
118193323Sed
119193323Sedtypedef enum
120249423Sdim{
121193323Sed  sim_fpu_denorm_default = 0,
122193323Sed  sim_fpu_denorm_underflow_inexact = 1,
123218893Sdim  sim_fpu_denorm_zero = 2,
124193323Sed} sim_fpu_denorm;
125193323Sed
126218893Sdim
127193323Sed
128193323Sed/* Status values returned by FPU operators.
129193323Sed
130198090Srdivacky   When checking the result of an FP sequence (ex 32to, add, single,
131198090Srdivacky   to32) the caller may either: check the return value of each FP
132193323Sed   operator; or form the union (OR) of the returned values and examine
133210299Sed   them once at the end.
134210299Sed
135210299Sed   FIXME: This facility is still being developed.  The choice of
136193323Sed   status values returned and their exact meaning may changed in the
137218893Sdim   future.  */
138193323Sed
139239462Sdimtypedef enum
140239462Sdim{
141239462Sdim  sim_fpu_status_invalid_snan = 1,
142195340Sed  sim_fpu_status_invalid_qnan = 2,
143218893Sdim  sim_fpu_status_invalid_isi = 4, /* (inf - inf) */
144193323Sed  sim_fpu_status_invalid_idi = 8, /* (inf / inf) */
145193323Sed  sim_fpu_status_invalid_zdz = 16, /* (0 / 0) */
146193323Sed  sim_fpu_status_invalid_imz = 32, /* (inf * 0) */
147218893Sdim  sim_fpu_status_invalid_cvi = 64, /* convert to integer */
148218893Sdim  sim_fpu_status_invalid_div0 = 128, /* (X / 0) */
149218893Sdim  sim_fpu_status_invalid_cmp = 256, /* compare */
150193323Sed  sim_fpu_status_invalid_sqrt = 512,
151226633Sdim  sim_fpu_status_invalid_irx = 1024, /* (inf % X) */
152226633Sdim  sim_fpu_status_rounded = 2048,
153226633Sdim  sim_fpu_status_inexact = 4096,
154226633Sdim  sim_fpu_status_overflow = 8192,
155226633Sdim  sim_fpu_status_underflow = 16384,
156226633Sdim  sim_fpu_status_denorm = 32768,
157193323Sed} sim_fpu_status;
158208599Srdivacky
159243830Sdim
160243830Sdim
161208599Srdivacky
162243830Sdim/* State used by the FPU.
163243830Sdim
164193323Sed   FIXME: This state is global, but should be moved to SIM_CPU.  */
165212904Sdim
166243830Sdimtypedef enum
167218893Sdim{
168243830Sdim  sim_fpu_ieee754_1985,
169224145Sdim  sim_fpu_ieee754_2008,
170218893Sdim} sim_fpu_mode;
171200581Srdivacky
172202878Srdivackytypedef struct _sim_fpu_state {
173202878Srdivacky  bool quiet_nan_inverted; /* Toggle quiet NaN semantics.  */
174218893Sdim  sim_fpu_mode current_mode;
175218893Sdim} sim_fpu_state;
176210299Sed
177212904Sdim
178212904Sdim
179212904Sdim
180193323Sed/* Directly map between a 32/64 bit register and the sim_fpu internal
181193323Sed   type.
182193323Sed
183224145Sdim   When converting from the 32/64 bit packed format to the sim_fpu
184239462Sdim   internal type, the operation is exact.
185212904Sdim
186212904Sdim   When converting from the sim_fpu internal type to 32/64 bit packed
187224145Sdim   format, the operation may result in a loss of precision. The
188239462Sdim   configuration macro WITH_FPU_CONVERSION controls this.  By default,
189224145Sdim   silent round to nearest is performed.  Alternatively, round up,
190239462Sdim   round down and round to zero can be performed.  In a simulator
191218893Sdim   emulating exact FPU behavior, sim_fpu_round_{32,64} should be
192224145Sdim   called before packing the sim_fpu value.  */
193239462Sdim
194212904SdimINLINE_SIM_FPU (void) sim_fpu_32to (sim_fpu *f, uint32_t s);
195224145SdimINLINE_SIM_FPU (void) sim_fpu_232to (sim_fpu *f, uint32_t h, uint32_t l);
196239462SdimINLINE_SIM_FPU (void) sim_fpu_64to (sim_fpu *f, uint64_t d);
197212904Sdim
198224145SdimINLINE_SIM_FPU (void) sim_fpu_to32 (uint32_t *s, const sim_fpu *f);
199239462SdimINLINE_SIM_FPU (void) sim_fpu_to232 (uint32_t *h, uint32_t *l, const sim_fpu *f);
200224145SdimINLINE_SIM_FPU (void) sim_fpu_to64 (uint64_t *d, const sim_fpu *f);
201239462Sdim
202234353Sdim
203239462Sdim/* Create a sim_fpu struct using raw information.  (FRACTION & LSMASK
204224145Sdim   (PRECISION-1, 0)) is assumed to contain the fraction part of the
205239462Sdim   floating-point number.  The leading bit LSBIT (PRECISION) is always
206224145Sdim   implied.  The number created can be represented by:
207239462Sdim
208224145Sdim   (SIGN ? "-" : "+") "1." FRACTION{PRECISION-1,0} X 2 ^ NORMAL_EXP>
209239462Sdim
210243830Sdim   You can not specify zero using this function. */
211243830Sdim
212218893SdimINLINE_SIM_FPU (void) sim_fpu_fractionto (sim_fpu *f, int sign, int normal_exp, uint64_t fraction, int precision);
213239462Sdim
214239462Sdim/* Reverse operation.  If S is a non-zero number, discards the implied
215224145Sdim   leading one and returns PRECISION fraction bits.  No rounding is
216239462Sdim   performed. */
217239462SdimINLINE_SIM_FPU (uint64_t) sim_fpu_tofraction (const sim_fpu *s, int precision);
218218893Sdim
219239462Sdim
220239462Sdim
221218893Sdim/* Rounding operators.
222239462Sdim
223239462Sdim   Force an intermediate result to an exact 32/64 bit
224251662Sdim   representation. */
225251662Sdim
226251662SdimINLINE_SIM_FPU (int) sim_fpu_round_32 (sim_fpu *f,
227212904Sdim				       sim_fpu_round round,
228198090Srdivacky				       sim_fpu_denorm denorm);
229224145SdimINLINE_SIM_FPU (int) sim_fpu_round_64 (sim_fpu *f,
230239462Sdim				       sim_fpu_round round,
231212904Sdim				       sim_fpu_denorm denorm);
232224145Sdim
233239462Sdim
234239462Sdim
235226633Sdim/* Arithmetic operators.
236239462Sdim
237226633Sdim   FIXME: In the future, additional arguments ROUNDING and BITSIZE may
238239462Sdim   be added. */
239239462Sdim
240224145Sdimtypedef int (sim_fpu_op1) (sim_fpu *f,
241239462Sdim			   const sim_fpu *l);
242234353Sdimtypedef int (sim_fpu_op2) (sim_fpu *f,
243234353Sdim			   const sim_fpu *l,
244234353Sdim			   const sim_fpu *r);
245249423Sdim
246249423SdimINLINE_SIM_FPU (int) sim_fpu_add (sim_fpu *f,
247249423Sdim				  const sim_fpu *l, const sim_fpu *r);
248193323SedINLINE_SIM_FPU (int) sim_fpu_sub (sim_fpu *f,
249199989Srdivacky				  const sim_fpu *l, const sim_fpu *r);
250212904SdimINLINE_SIM_FPU (int) sim_fpu_mul (sim_fpu *f,
251212904Sdim				  const sim_fpu *l, const sim_fpu *r);
252218893SdimINLINE_SIM_FPU (int) sim_fpu_div (sim_fpu *f,
253243830Sdim				  const sim_fpu *l, const sim_fpu *r);
254199989SrdivackyINLINE_SIM_FPU (int) sim_fpu_rem (sim_fpu *f,
255234353Sdim				  const sim_fpu *l, const sim_fpu *r);
256234353SdimINLINE_SIM_FPU (int) sim_fpu_max (sim_fpu *f,
257234982Sdim				  const sim_fpu *l, const sim_fpu *r);
258239462SdimINLINE_SIM_FPU (int) sim_fpu_min (sim_fpu *f,
259239462Sdim				  const sim_fpu *l, const sim_fpu *r);
260234982SdimINLINE_SIM_FPU (int) sim_fpu_neg (sim_fpu *f,
261234982Sdim				  const sim_fpu *a);
262234982SdimINLINE_SIM_FPU (int) sim_fpu_abs (sim_fpu *f,
263234353Sdim				  const sim_fpu *a);
264243830SdimINLINE_SIM_FPU (int) sim_fpu_inv (sim_fpu *f,
265243830Sdim				  const sim_fpu *a);
266243830SdimINLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f,
267243830Sdim				   const sim_fpu *sqr);
268243830Sdim
269243830Sdim
270243830Sdim
271243830Sdim/* NaN handling.
272243830Sdim
273243830Sdim   Assuming that at least one of the inputs is NAN choose the correct
274243830Sdim   NAN result for the binary operation.  */
275243830Sdim
276243830SdimINLINE_SIM_FPU (int) sim_fpu_op_nan (sim_fpu *f,
277243830Sdim				     const sim_fpu *l, const sim_fpu *r);
278239462SdimINLINE_SIM_FPU (int) sim_fpu_minmax_nan (sim_fpu *f,
279239462Sdim					 const sim_fpu *l, const sim_fpu *r);
280239462Sdim
281193323Sed
282193323Sed
283193323Sed/* Conversion of integer <-> floating point. */
284193323Sed
285193323SedINLINE_SIM_FPU (int) sim_fpu_i32to (sim_fpu *f, int32_t i,
286193323Sed				    sim_fpu_round round);
287193323SedINLINE_SIM_FPU (int) sim_fpu_u32to (sim_fpu *f, uint32_t u,
288193323Sed				    sim_fpu_round round);
289193323SedINLINE_SIM_FPU (int) sim_fpu_i64to (sim_fpu *f, int64_t i,
290193323Sed				    sim_fpu_round round);
291193323SedINLINE_SIM_FPU (int) sim_fpu_u64to (sim_fpu *f, uint64_t u,
292243830Sdim				    sim_fpu_round round);
293239462Sdim#if 0
294198090SrdivackyINLINE_SIM_FPU (int) sim_fpu_i232to (sim_fpu *f, int32_t h, int32_t l,
295193323Sed				     sim_fpu_round round);
296193323Sed#endif
297243830Sdim#if 0
298243830SdimINLINE_SIM_FPU (int) sim_fpu_u232to (sim_fpu *f, uint32_t h, uint32_t l,
299198090Srdivacky				     sim_fpu_round round);
300193323Sed#endif
301193323Sed
302193323SedINLINE_SIM_FPU (int) sim_fpu_to32i (int32_t *i, const sim_fpu *f,
303221345Sdim				    sim_fpu_round round);
304221345SdimINLINE_SIM_FPU (int) sim_fpu_to32u (uint32_t *u, const sim_fpu *f,
305193323Sed				    sim_fpu_round round);
306193323SedINLINE_SIM_FPU (int) sim_fpu_to64i (int64_t *i, const sim_fpu *f,
307234353Sdim				    sim_fpu_round round);
308234353SdimINLINE_SIM_FPU (int) sim_fpu_to64u (uint64_t *u, const sim_fpu *f,
309243830Sdim				    sim_fpu_round round);
310234353Sdim#if 0
311239462SdimINLINE_SIM_FPU (int) sim_fpu_to232i (int64_t *h, int64_t *l, const sim_fpu *f,
312234353Sdim				     sim_fpu_round round);
313234353Sdim#endif
314193323Sed#if 0
315234353SdimINLINE_SIM_FPU (int) sim_fpu_to232u (uint64_t *h, uint64_t *l, const sim_fpu *f,
316234353Sdim				     sim_fpu_round round);
317234353Sdim#endif
318234353Sdim
319234353Sdim
320218893Sdim/* Conversion of internal sim_fpu type to host double format.
321243830Sdim
322234353Sdim   For debugging/tracing only.  A SNaN is never returned. */
323234353Sdim
324193323Sed/* INLINE_SIM_FPU (float) sim_fpu_2f (const sim_fpu *f); */
325193323SedINLINE_SIM_FPU (double) sim_fpu_2d (const sim_fpu *d);
326193323Sed
327193323Sed/* INLINE_SIM_FPU (void) sim_fpu_f2 (sim_fpu *f, float s); */
328193323SedINLINE_SIM_FPU (void) sim_fpu_d2 (sim_fpu *f, double d);
329193323Sed
330198090Srdivacky/* IEEE754-2008 classifiction function.  */
331198090SrdivackyINLINE_SIM_FPU (int) sim_fpu_classify (const sim_fpu *f);
332198090Srdivacky
333198090Srdivacky/* Specific number classes.
334198090Srdivacky
335198090Srdivacky   NB: When either, a 32/64 bit floating points is converted to
336198090Srdivacky   internal format, or an internal format number is rounded to 32/64
337198090Srdivacky   bit precision, a special marker is retained that indicates that the
338199989Srdivacky   value was normalized.  For such numbers both is_number and
339198090Srdivacky   is_denorm return true. */
340226633Sdim
341226633SdimINLINE_SIM_FPU (int) sim_fpu_is_nan (const sim_fpu *s); /* 1 => SNaN or QNaN */
342193323SedINLINE_SIM_FPU (int) sim_fpu_is_snan (const sim_fpu *s); /* 1 => SNaN */
343193323SedINLINE_SIM_FPU (int) sim_fpu_is_qnan (const sim_fpu *s); /* 1 => QNaN */
344193323Sed
345218893SdimINLINE_SIM_FPU (int) sim_fpu_is_zero (const sim_fpu *s);
346218893SdimINLINE_SIM_FPU (int) sim_fpu_is_infinity (const sim_fpu *s);
347218893SdimINLINE_SIM_FPU (int) sim_fpu_is_number (const sim_fpu *s); /* !zero */
348218893SdimINLINE_SIM_FPU (int) sim_fpu_is_denorm (const sim_fpu *s); /* !zero */
349218893Sdim
350218893Sdim
351218893Sdim
352218893Sdim/* Floating point fields */
353218893Sdim
354218893SdimINLINE_SIM_FPU (int) sim_fpu_sign (const sim_fpu *s);
355218893SdimINLINE_SIM_FPU (int) sim_fpu_exp (const sim_fpu *s);
356218893SdimINLINE_SIM_FPU (uint64_t) sim_fpu_fraction (const sim_fpu *s);
357218893SdimINLINE_SIM_FPU (uint64_t) sim_fpu_guard (const sim_fpu *s, int is_double);
358218893Sdim
359218893Sdim
360218893Sdim
361218893Sdim/* Specific comparison operators
362218893Sdim
363218893Sdim   For NaNs et al., the comparison operators will set IS to zero and
364218893Sdim   return a nonzero result. */
365218893Sdim
366218893SdimINLINE_SIM_FPU (int) sim_fpu_lt (int *is, const sim_fpu *l, const sim_fpu *r);
367218893SdimINLINE_SIM_FPU (int) sim_fpu_le (int *is, const sim_fpu *l, const sim_fpu *r);
368218893SdimINLINE_SIM_FPU (int) sim_fpu_eq (int *is, const sim_fpu *l, const sim_fpu *r);
369218893SdimINLINE_SIM_FPU (int) sim_fpu_ne (int *is, const sim_fpu *l, const sim_fpu *r);
370193323SedINLINE_SIM_FPU (int) sim_fpu_ge (int *is, const sim_fpu *l, const sim_fpu *r);
371193323SedINLINE_SIM_FPU (int) sim_fpu_gt (int *is, const sim_fpu *l, const sim_fpu *r);
372193323Sed
373193323SedINLINE_SIM_FPU (int) sim_fpu_is_lt (const sim_fpu *l, const sim_fpu *r);
374234353SdimINLINE_SIM_FPU (int) sim_fpu_is_le (const sim_fpu *l, const sim_fpu *r);
375234353SdimINLINE_SIM_FPU (int) sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r);
376234353SdimINLINE_SIM_FPU (int) sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r);
377193323SedINLINE_SIM_FPU (int) sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r);
378218893SdimINLINE_SIM_FPU (int) sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r);
379218893Sdim
380218893Sdim/* Unordered/ordered comparison operators.  */
381224145Sdim
382226633SdimINLINE_SIM_FPU (int) sim_fpu_un (int *is, const sim_fpu *l, const sim_fpu *r);
383218893SdimINLINE_SIM_FPU (int) sim_fpu_or (int *is, const sim_fpu *l, const sim_fpu *r);
384193323Sed
385218893SdimINLINE_SIM_FPU (int) sim_fpu_is_un (const sim_fpu *l, const sim_fpu *r);
386218893SdimINLINE_SIM_FPU (int) sim_fpu_is_or (const sim_fpu *l, const sim_fpu *r);
387218893Sdim
388224145Sdim/* Changes the behaviour of the library to IEEE754-2008 or IEEE754-1985.
389218893Sdim   The default for the library is IEEE754-1985.  */
390218893Sdim
391218893SdimINLINE_SIM_FPU (bool) sim_fpu_is_ieee754_1985 (void);
392218893SdimINLINE_SIM_FPU (bool) sim_fpu_is_ieee754_2008 (void);
393218893SdimINLINE_SIM_FPU (void) sim_fpu_set_mode (const sim_fpu_mode m);
394224145Sdim
395218893Sdim/* General number class and comparison operators.
396218893Sdim
397218893Sdim   The result of the comparison is indicated by returning one of the
398218893Sdim   values below.  Efficient emulation of a target FP compare
399218893Sdim   instruction can be achieved by redefining the values below to match
400218893Sdim   corresponding target FP status bits.
401218893Sdim
402224145Sdim   For instance.  SIM_FPU_QNAN may be redefined to be the bit
403218893Sdim   `INVALID' while SIM_FPU_NINF might be redefined as the bits
404218893Sdim   `NEGATIVE | INFINITY | VALID'. */
405218893Sdim
406218893Sdim#ifndef SIM_FPU_IS_SNAN
407218893Sdimenum {
408234353Sdim  SIM_FPU_IS_SNAN = 1, /* Noisy not-a-number */
409224145Sdim  SIM_FPU_IS_QNAN = 2, /* Quiet not-a-number */
410218893Sdim  SIM_FPU_IS_NINF = 3, /* -infinity */
411218893Sdim  SIM_FPU_IS_PINF = 4, /* +infinity */
412226633Sdim  SIM_FPU_IS_NNUMBER = 5, /* -number - [ -MAX .. -MIN ] */
413226633Sdim  SIM_FPU_IS_PNUMBER = 6, /* +number - [ +MIN .. +MAX ] */
414226633Sdim  SIM_FPU_IS_NDENORM = 7, /* -denorm - ( MIN .. 0 ) */
415226633Sdim  SIM_FPU_IS_PDENORM = 8, /* +denorm - ( 0 .. MIN ) */
416218893Sdim  SIM_FPU_IS_NZERO = 9, /* -0 */
417193323Sed  SIM_FPU_IS_PZERO = 10, /* +0 */
418226633Sdim};
419193323Sed#endif
420218893Sdim
421218893SdimINLINE_SIM_FPU (int) sim_fpu_is (const sim_fpu *l);
422193323SedINLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r);
423226633Sdim
424193323Sed/* Global FPU state.  */
425193323Sed
426249423Sdimextern sim_fpu_state _sim_fpu;
427249423Sdim
428226633Sdim
429218893Sdim/* IEEE 754-1985 specifies the top bit of the mantissa as an indicator
430218893Sdim   of signalling vs. quiet NaN, but does not specify the semantics.
431218893Sdim   Most architectures treat this bit as quiet NaN, but legacy (pre-R6)
432218893Sdim   MIPS goes the other way and treats it as signalling.  This variable
433226633Sdim   tracks the current semantics of the NaN bit and allows differentiation
434218893Sdim   between pre-R6 and R6 MIPS cores.  */
435218893Sdim
436226633Sdim#define sim_fpu_quiet_nan_inverted _sim_fpu.quiet_nan_inverted
437218893Sdim#define sim_fpu_current_mode _sim_fpu.current_mode
438218893Sdim
439218893Sdim/* A number of useful constants.  */
440218893Sdim
441226633Sdimextern const sim_fpu sim_fpu_zero;
442218893Sdimextern const sim_fpu sim_fpu_one;
443218893Sdimextern const sim_fpu sim_fpu_two;
444193323Sedextern const sim_fpu sim_fpu_qnan;
445193323Sedextern const sim_fpu sim_fpu_max32;
446193323Sedextern const sim_fpu sim_fpu_max64;
447193323Sed
448193323Sed
449193323Sed/* Select the applicable functions for the fp_word type */
450193323Sed
451193323Sed#if WITH_TARGET_FLOATING_POINT_BITSIZE == 32
452193323Sed#define sim_fpu_tofp sim_fpu_to32
453193323Sed#define sim_fpu_fpto sim_fpu_32to
454218893Sdim#define sim_fpu_round_fp sim_fpu_round_32
455239462Sdim#define sim_fpu_maxfp sim_fpu_max32
456218893Sdim#endif
457218893Sdim#if WITH_TARGET_FLOATING_POINT_BITSIZE == 64
458239462Sdim#define sim_fpu_tofp sim_fpu_to64
459239462Sdim#define sim_fpu_fpto sim_fpu_64to
460218893Sdim#define sim_fpu_round_fp sim_fpu_round_64
461218893Sdim#define sim_fpu_maxfp sim_fpu_max64
462218893Sdim#endif
463218893Sdim
464226633Sdim
465218893Sdim
466218893Sdim/* For debugging */
467218893Sdim
468226633Sdimtypedef void sim_fpu_print_func (void *, const char *, ...);
469226633Sdim
470226633Sdim/* Print a sim_fpu with full precision.  */
471226633SdimINLINE_SIM_FPU (void) sim_fpu_print_fpu (const sim_fpu *f,
472226633Sdim					 sim_fpu_print_func *print,
473226633Sdim					 void *arg);
474226633Sdim
475226633Sdim/* Print a sim_fpu with `n' trailing digits.  */
476226633SdimINLINE_SIM_FPU (void) sim_fpu_printn_fpu (const sim_fpu *f,
477226633Sdim					  sim_fpu_print_func *print,
478226633Sdim					  int digits,
479226633Sdim					  void *arg);
480218893Sdim
481226633SdimINLINE_SIM_FPU (void) sim_fpu_print_status (int status,
482226633Sdim					    sim_fpu_print_func *print,
483226633Sdim					    void *arg);
484226633Sdim
485226633Sdim#if H_REVEALS_MODULE_P (SIM_FPU_INLINE)
486226633Sdim#include "sim-fpu.c"
487221345Sdim#endif
488221345Sdim
489212904Sdim#endif
490226633Sdim