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 | 20 | #ifndef CPU_ALL_H |
21 | 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 | 57 | /* CPU memory access without any memory or io remapping */ |
24 | 58 | |
25 | 59 | static inline int ldub_raw(void *ptr) |
... | ... | @@ -40,7 +74,7 @@ static inline void stb_raw(void *ptr, int v) |
40 | 74 | /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the |
41 | 75 | kernel handles unaligned load/stores may give better results, but |
42 | 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 | 79 | /* conservative code for little endian unaligned accesses */ |
46 | 80 | static inline int lduw_raw(void *ptr) |
... | ... | @@ -141,55 +175,23 @@ static inline void stfl_raw(void *ptr, float v) |
141 | 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 | 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 | 183 | return u.d; |
157 | 184 | } |
158 | 185 | |
159 | 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 | 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 | 196 | static inline int lduw_raw(void *ptr) |
195 | 197 | { |
... | ... | @@ -235,8 +237,46 @@ static inline void stl_raw(void *ptr, int v) |
235 | 237 | |
236 | 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 | 282 | #else |
... | ... | @@ -330,10 +370,14 @@ static inline void stfq_raw(void *ptr, double v) |
330 | 370 | #define lduw_kernel(p) lduw_raw(p) |
331 | 371 | #define ldsw_kernel(p) ldsw_raw(p) |
332 | 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 | 375 | #define stb_kernel(p, v) stb_raw(p, v) |
334 | 376 | #define stw_kernel(p, v) stw_raw(p, v) |
335 | 377 | #define stl_kernel(p, v) stl_raw(p, v) |
336 | 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 | 382 | #endif /* defined(CONFIG_USER_ONLY) */ |
339 | 383 | ... | ... |