cc68a136 |
1 | /* |
2 | * ==================================================== |
3 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. |
4 | * |
5 | * Developed at SunPro, a Sun Microsystems, Inc. business. |
6 | * Permission to use, copy, modify, and distribute this |
7 | * software is freely granted, provided that this notice |
8 | * is preserved. |
9 | * ==================================================== |
10 | */ |
11 | |
12 | /* |
13 | * from: @(#)fdlibm.h 5.1 93/09/24 |
14 | * $Id: math_private.h,v 1.3 2004/02/09 07:10:38 andersen Exp $ |
15 | */ |
16 | |
17 | #ifndef _MATH_PRIVATE_H_ |
18 | #define _MATH_PRIVATE_H_ |
19 | |
20 | #include <endian.h> |
21 | #include <sys/types.h> |
22 | |
23 | /* The original fdlibm code used statements like: |
24 | n0 = ((*(int*)&one)>>29)^1; * index of high word * |
25 | ix0 = *(n0+(int*)&x); * high word of x * |
26 | ix1 = *((1-n0)+(int*)&x); * low word of x * |
27 | to dig two 32 bit words out of the 64 bit IEEE floating point |
28 | value. That is non-ANSI, and, moreover, the gcc instruction |
29 | scheduler gets it wrong. We instead use the following macros. |
30 | Unlike the original code, we determine the endianness at compile |
31 | time, not at run time; I don't see much benefit to selecting |
32 | endianness at run time. */ |
33 | |
34 | /* A union which permits us to convert between a double and two 32 bit |
35 | ints. */ |
36 | |
37 | /* |
38 | * Math on arm is special: |
39 | * For FPA, float words are always big-endian. |
40 | * For VFP, floats words follow the memory system mode. |
41 | */ |
42 | |
43 | #if (__BYTE_ORDER == __BIG_ENDIAN) || \ |
44 | (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__))) |
45 | |
46 | typedef union |
47 | { |
48 | double value; |
49 | struct |
50 | { |
51 | u_int32_t msw; |
52 | u_int32_t lsw; |
53 | } parts; |
54 | } ieee_double_shape_type; |
55 | |
56 | #else |
57 | |
58 | typedef union |
59 | { |
60 | double value; |
61 | struct |
62 | { |
63 | u_int32_t lsw; |
64 | u_int32_t msw; |
65 | } parts; |
66 | } ieee_double_shape_type; |
67 | |
68 | #endif |
69 | |
70 | /* Get two 32 bit ints from a double. */ |
71 | |
72 | #define EXTRACT_WORDS(ix0,ix1,d) \ |
73 | do { \ |
74 | ieee_double_shape_type ew_u; \ |
75 | ew_u.value = (d); \ |
76 | (ix0) = ew_u.parts.msw; \ |
77 | (ix1) = ew_u.parts.lsw; \ |
78 | } while (0) |
79 | |
80 | /* Get the more significant 32 bit int from a double. */ |
81 | |
82 | #define GET_HIGH_WORD(i,d) \ |
83 | do { \ |
84 | ieee_double_shape_type gh_u; \ |
85 | gh_u.value = (d); \ |
86 | (i) = gh_u.parts.msw; \ |
87 | } while (0) |
88 | |
89 | /* Get the less significant 32 bit int from a double. */ |
90 | |
91 | #define GET_LOW_WORD(i,d) \ |
92 | do { \ |
93 | ieee_double_shape_type gl_u; \ |
94 | gl_u.value = (d); \ |
95 | (i) = gl_u.parts.lsw; \ |
96 | } while (0) |
97 | |
98 | /* Set a double from two 32 bit ints. */ |
99 | |
100 | #define INSERT_WORDS(d,ix0,ix1) \ |
101 | do { \ |
102 | ieee_double_shape_type iw_u; \ |
103 | iw_u.parts.msw = (ix0); \ |
104 | iw_u.parts.lsw = (ix1); \ |
105 | (d) = iw_u.value; \ |
106 | } while (0) |
107 | |
108 | /* Set the more significant 32 bits of a double from an int. */ |
109 | |
110 | #define SET_HIGH_WORD(d,v) \ |
111 | do { \ |
112 | ieee_double_shape_type sh_u; \ |
113 | sh_u.value = (d); \ |
114 | sh_u.parts.msw = (v); \ |
115 | (d) = sh_u.value; \ |
116 | } while (0) |
117 | |
118 | /* Set the less significant 32 bits of a double from an int. */ |
119 | |
120 | #define SET_LOW_WORD(d,v) \ |
121 | do { \ |
122 | ieee_double_shape_type sl_u; \ |
123 | sl_u.value = (d); \ |
124 | sl_u.parts.lsw = (v); \ |
125 | (d) = sl_u.value; \ |
126 | } while (0) |
127 | |
128 | |
129 | #endif /* _MATH_PRIVATE_H_ */ |