1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * MC68881 emulation
5   * Support functions for IEEE 754-compatible host CPUs.
6   * These functions use a GCC extension (type punning through unions) and
7   * should only be compiled with compilers that support this.
8   *
9   * Copyright 1999 Sam Jordan
10   * Copyright 2007 Richard Drummond
11   *
12   * Note: Type punning through unions is no longer a gcc extension.
13   * As long as we are only compiling with strict C99/C11 this method is
14   * perfectly legal *and* portable. It was made explicit with C99/TC3,
15   * which added the following footnote to section 6.5.2.3:
16   *   "If the member used to access the contents of a union object is not
17   *    the same as the member last used to store a value in the object,
18   *    the appropriate part of the object representation of the value is
19   *    reinterpreted as an object representation in the new type as
20   *    described in 6.2.6 (a process sometimes called "type punning").
21   *    This might be a trap representation."
22   * Annex J still lists it as unspecified behavior, which is a known defect
23   * and has been corrected with C11, which changed
24   *   "The value of a union member other than the last one stored into
25   *    [is unspecified]"
26   * to
27   *   "The values of bytes that correspond to union members other than the
28   *    one last stored into [are unspecified]"
29   * It's not that big a deal as the annex is only informative, not normative.
30   *  - Sven
31   */
32 
33 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
to_single(uae_u32 value)34 STATIC_INLINE double to_single (uae_u32 value)
35 {
36     union {
37 	float f;
38 	uae_u32 u;
39     } val;
40 
41     val.u = value;
42     return val.f;
43 }
44 
from_single(double src)45 STATIC_INLINE uae_u32 from_single (double src)
46 {
47     union {
48 	float f;
49 	uae_u32 u;
50     } val;
51 
52     val.f = src;
53     return val.u;
54 }
55 
to_double(uae_u32 wrd1,uae_u32 wrd2)56 STATIC_INLINE double to_double (uae_u32 wrd1, uae_u32 wrd2)
57 {
58     union {
59 	double d;
60 	uae_u32 u[2];
61     } val;
62 
63 #ifdef WORDS_BIGENDIAN
64     val.u[0] = wrd1;
65     val.u[1] = wrd2;
66 #else
67     val.u[1] = wrd1;
68     val.u[0] = wrd2;
69 #endif
70     return val.d;
71 }
72 
from_double(double src,uae_u32 * wrd1,uae_u32 * wrd2)73 STATIC_INLINE void from_double (double src, uae_u32 * wrd1, uae_u32 * wrd2)
74 {
75     union {
76 	double d;
77 	uae_u32 u[2];
78     } val;
79 
80     val.d = src;
81 #ifdef WORDS_BIGENDIAN
82     *wrd1 = val.u[0];
83     *wrd2 = val.u[1];
84 #else
85     *wrd1 = val.u[1];
86     *wrd2 = val.u[0];
87 #endif
88 }
89 
90 #define HAVE_from_double
91 #define HAVE_to_double
92 #define HAVE_from_single
93 #define HAVE_to_single
94 #endif // C99 and newer
95 
96 /* Get the rest of the conversion functions defined.  */
97 #include "fpp-unknown.h"
98