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 | ... | ... |