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 |