Commit 0ac4bd56a8baf235c136c84b338616d47ce01689
1 parent
3811a291
float access fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@489 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
86 additions
and
42 deletions
cpu-all.h
@@ -20,6 +20,40 @@ | @@ -20,6 +20,40 @@ | ||
20 | #ifndef CPU_ALL_H | 20 | #ifndef CPU_ALL_H |
21 | #define CPU_ALL_H | 21 | #define CPU_ALL_H |
22 | 22 | ||
23 | +#if defined(__arm__) || defined(__sparc__) | ||
24 | +#define WORDS_ALIGNED | ||
25 | +#endif | ||
26 | + | ||
27 | +/* some important defines: | ||
28 | + * | ||
29 | + * WORDS_ALIGNED : if defined, the host cpu can only make word aligned | ||
30 | + * memory accesses. | ||
31 | + * | ||
32 | + * WORDS_BIGENDIAN : if defined, the host cpu is big endian and | ||
33 | + * otherwise little endian. | ||
34 | + * | ||
35 | + * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet)) | ||
36 | + * | ||
37 | + * TARGET_WORDS_BIGENDIAN : same for target cpu | ||
38 | + */ | ||
39 | + | ||
40 | +/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ | ||
41 | +typedef union { | ||
42 | + double d; | ||
43 | +#if !defined(WORDS_BIGENDIAN) && !defined(__arm__) | ||
44 | + struct { | ||
45 | + uint32_t lower; | ||
46 | + uint32_t upper; | ||
47 | + } l; | ||
48 | +#else | ||
49 | + struct { | ||
50 | + uint32_t upper; | ||
51 | + uint32_t lower; | ||
52 | + } l; | ||
53 | +#endif | ||
54 | + uint64_t ll; | ||
55 | +} CPU_DoubleU; | ||
56 | + | ||
23 | /* CPU memory access without any memory or io remapping */ | 57 | /* CPU memory access without any memory or io remapping */ |
24 | 58 | ||
25 | static inline int ldub_raw(void *ptr) | 59 | static inline int ldub_raw(void *ptr) |
@@ -40,7 +74,7 @@ static inline void stb_raw(void *ptr, int v) | @@ -40,7 +74,7 @@ static inline void stb_raw(void *ptr, int v) | ||
40 | /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the | 74 | /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the |
41 | kernel handles unaligned load/stores may give better results, but | 75 | kernel handles unaligned load/stores may give better results, but |
42 | it is a system wide setting : bad */ | 76 | it is a system wide setting : bad */ |
43 | -#if defined(WORDS_BIGENDIAN) || defined(__arm__) | 77 | +#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)) |
44 | 78 | ||
45 | /* conservative code for little endian unaligned accesses */ | 79 | /* conservative code for little endian unaligned accesses */ |
46 | static inline int lduw_raw(void *ptr) | 80 | static inline int lduw_raw(void *ptr) |
@@ -141,55 +175,23 @@ static inline void stfl_raw(void *ptr, float v) | @@ -141,55 +175,23 @@ static inline void stfl_raw(void *ptr, float v) | ||
141 | stl_raw(ptr, u.i); | 175 | stl_raw(ptr, u.i); |
142 | } | 176 | } |
143 | 177 | ||
144 | - | ||
145 | -#if defined(__arm__) && !defined(WORDS_BIGENDIAN) | ||
146 | - | ||
147 | -/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ | ||
148 | static inline double ldfq_raw(void *ptr) | 178 | static inline double ldfq_raw(void *ptr) |
149 | { | 179 | { |
150 | - union { | ||
151 | - double d; | ||
152 | - uint32_t tab[2]; | ||
153 | - } u; | ||
154 | - u.tab[1] = ldl_raw(ptr); | ||
155 | - u.tab[0] = ldl_raw(ptr + 4); | 180 | + CPU_DoubleU u; |
181 | + u.l.lower = ldl_raw(ptr); | ||
182 | + u.l.upper = ldl_raw(ptr + 4); | ||
156 | return u.d; | 183 | return u.d; |
157 | } | 184 | } |
158 | 185 | ||
159 | static inline void stfq_raw(void *ptr, double v) | 186 | static inline void stfq_raw(void *ptr, double v) |
160 | { | 187 | { |
161 | - union { | ||
162 | - double d; | ||
163 | - uint32_t tab[2]; | ||
164 | - } u; | 188 | + CPU_DoubleU u; |
165 | u.d = v; | 189 | u.d = v; |
166 | - stl_raw(ptr, u.tab[1]); | ||
167 | - stl_raw(ptr + 4, u.tab[0]); | 190 | + stl_raw(ptr, u.l.lower); |
191 | + stl_raw(ptr + 4, u.l.upper); | ||
168 | } | 192 | } |
169 | 193 | ||
170 | -#else | ||
171 | -static inline double ldfq_raw(void *ptr) | ||
172 | -{ | ||
173 | - union { | ||
174 | - double d; | ||
175 | - uint64_t i; | ||
176 | - } u; | ||
177 | - u.i = ldq_raw(ptr); | ||
178 | - return u.d; | ||
179 | -} | ||
180 | - | ||
181 | -static inline void stfq_raw(void *ptr, double v) | ||
182 | -{ | ||
183 | - union { | ||
184 | - double d; | ||
185 | - uint64_t i; | ||
186 | - } u; | ||
187 | - u.d = v; | ||
188 | - stq_raw(ptr, u.i); | ||
189 | -} | ||
190 | -#endif | ||
191 | - | ||
192 | -#elif defined(TARGET_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN) | 194 | +#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)) |
193 | 195 | ||
194 | static inline int lduw_raw(void *ptr) | 196 | static inline int lduw_raw(void *ptr) |
195 | { | 197 | { |
@@ -235,8 +237,46 @@ static inline void stl_raw(void *ptr, int v) | @@ -235,8 +237,46 @@ static inline void stl_raw(void *ptr, int v) | ||
235 | 237 | ||
236 | static inline void stq_raw(void *ptr, uint64_t v) | 238 | static inline void stq_raw(void *ptr, uint64_t v) |
237 | { | 239 | { |
238 | - stl_raw(ptr, v); | ||
239 | - stl_raw(ptr+4, v >> 32); | 240 | + stl_raw(ptr, v >> 32); |
241 | + stl_raw(ptr + 4, v); | ||
242 | +} | ||
243 | + | ||
244 | +/* float access */ | ||
245 | + | ||
246 | +static inline float ldfl_raw(void *ptr) | ||
247 | +{ | ||
248 | + union { | ||
249 | + float f; | ||
250 | + uint32_t i; | ||
251 | + } u; | ||
252 | + u.i = ldl_raw(ptr); | ||
253 | + return u.f; | ||
254 | +} | ||
255 | + | ||
256 | +static inline void stfl_raw(void *ptr, float v) | ||
257 | +{ | ||
258 | + union { | ||
259 | + float f; | ||
260 | + uint32_t i; | ||
261 | + } u; | ||
262 | + u.f = v; | ||
263 | + stl_raw(ptr, u.i); | ||
264 | +} | ||
265 | + | ||
266 | +static inline double ldfq_raw(void *ptr) | ||
267 | +{ | ||
268 | + CPU_DoubleU u; | ||
269 | + u.l.upper = ldl_raw(ptr); | ||
270 | + u.l.lower = ldl_raw(ptr + 4); | ||
271 | + return u.d; | ||
272 | +} | ||
273 | + | ||
274 | +static inline void stfq_raw(void *ptr, double v) | ||
275 | +{ | ||
276 | + CPU_DoubleU u; | ||
277 | + u.d = v; | ||
278 | + stl_raw(ptr, u.l.upper); | ||
279 | + stl_raw(ptr + 4, u.l.lower); | ||
240 | } | 280 | } |
241 | 281 | ||
242 | #else | 282 | #else |
@@ -330,10 +370,14 @@ static inline void stfq_raw(void *ptr, double v) | @@ -330,10 +370,14 @@ static inline void stfq_raw(void *ptr, double v) | ||
330 | #define lduw_kernel(p) lduw_raw(p) | 370 | #define lduw_kernel(p) lduw_raw(p) |
331 | #define ldsw_kernel(p) ldsw_raw(p) | 371 | #define ldsw_kernel(p) ldsw_raw(p) |
332 | #define ldl_kernel(p) ldl_raw(p) | 372 | #define ldl_kernel(p) ldl_raw(p) |
373 | +#define ldfl_kernel(p) ldfl_raw(p) | ||
374 | +#define ldfq_kernel(p) ldfq_raw(p) | ||
333 | #define stb_kernel(p, v) stb_raw(p, v) | 375 | #define stb_kernel(p, v) stb_raw(p, v) |
334 | #define stw_kernel(p, v) stw_raw(p, v) | 376 | #define stw_kernel(p, v) stw_raw(p, v) |
335 | #define stl_kernel(p, v) stl_raw(p, v) | 377 | #define stl_kernel(p, v) stl_raw(p, v) |
336 | #define stq_kernel(p, v) stq_raw(p, v) | 378 | #define stq_kernel(p, v) stq_raw(p, v) |
379 | +#define stfl_kernel(p, v) stfl_raw(p, v) | ||
380 | +#define stfq_kernel(p, vt) stfq_raw(p, v) | ||
337 | 381 | ||
338 | #endif /* defined(CONFIG_USER_ONLY) */ | 382 | #endif /* defined(CONFIG_USER_ONLY) */ |
339 | 383 |