Commit 4373f3ceeb419263d63109408b86f398564c9536
1 parent
b0109805
ARM TCG conversion 10/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4147 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
678 additions
and
685 deletions
target-arm/cpu.h
| @@ -168,9 +168,6 @@ typedef struct CPUARMState { | @@ -168,9 +168,6 @@ typedef struct CPUARMState { | ||
| 168 | int vec_len; | 168 | int vec_len; |
| 169 | int vec_stride; | 169 | int vec_stride; |
| 170 | 170 | ||
| 171 | - /* Temporary variables if we don't have spare fp regs. */ | ||
| 172 | - float32 tmp0s, tmp1s; | ||
| 173 | - float64 tmp0d, tmp1d; | ||
| 174 | /* scratch space when Tn are not sufficient. */ | 171 | /* scratch space when Tn are not sufficient. */ |
| 175 | uint32_t scratch[8]; | 172 | uint32_t scratch[8]; |
| 176 | 173 |
target-arm/exec.h
| @@ -25,13 +25,6 @@ register uint32_t T0 asm(AREG1); | @@ -25,13 +25,6 @@ register uint32_t T0 asm(AREG1); | ||
| 25 | register uint32_t T1 asm(AREG2); | 25 | register uint32_t T1 asm(AREG2); |
| 26 | register uint32_t T2 asm(AREG3); | 26 | register uint32_t T2 asm(AREG3); |
| 27 | 27 | ||
| 28 | -/* TODO: Put these in FP regs on targets that have such things. */ | ||
| 29 | -/* It is ok for FT0s and FT0d to overlap. Likewise FT1s and FT1d. */ | ||
| 30 | -#define FT0s env->vfp.tmp0s | ||
| 31 | -#define FT1s env->vfp.tmp1s | ||
| 32 | -#define FT0d env->vfp.tmp0d | ||
| 33 | -#define FT1d env->vfp.tmp1d | ||
| 34 | - | ||
| 35 | #define M0 env->iwmmxt.val | 28 | #define M0 env->iwmmxt.val |
| 36 | 29 | ||
| 37 | #include "cpu.h" | 30 | #include "cpu.h" |
| @@ -83,23 +76,5 @@ void cpu_loop_exit(void); | @@ -83,23 +76,5 @@ void cpu_loop_exit(void); | ||
| 83 | 76 | ||
| 84 | void raise_exception(int); | 77 | void raise_exception(int); |
| 85 | 78 | ||
| 86 | -void do_vfp_abss(void); | ||
| 87 | -void do_vfp_absd(void); | ||
| 88 | -void do_vfp_negs(void); | ||
| 89 | -void do_vfp_negd(void); | ||
| 90 | -void do_vfp_sqrts(void); | ||
| 91 | -void do_vfp_sqrtd(void); | ||
| 92 | -void do_vfp_cmps(void); | ||
| 93 | -void do_vfp_cmpd(void); | ||
| 94 | -void do_vfp_cmpes(void); | ||
| 95 | -void do_vfp_cmped(void); | ||
| 96 | -void do_vfp_set_fpscr(void); | ||
| 97 | -void do_vfp_get_fpscr(void); | ||
| 98 | -float32 helper_recps_f32(float32, float32); | ||
| 99 | -float32 helper_rsqrts_f32(float32, float32); | ||
| 100 | -uint32_t helper_recpe_u32(uint32_t); | ||
| 101 | -uint32_t helper_rsqrte_u32(uint32_t); | ||
| 102 | -float32 helper_recpe_f32(float32); | ||
| 103 | -float32 helper_rsqrte_f32(float32); | ||
| 104 | void helper_neon_tbl(int rn, int maxindex); | 79 | void helper_neon_tbl(int rn, int maxindex); |
| 105 | uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2); | 80 | uint32_t helper_neon_mul_p8(uint32_t op1, uint32_t op2); |
target-arm/helper.c
| @@ -2167,3 +2167,366 @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b) | @@ -2167,3 +2167,366 @@ uint32_t HELPER(sel_flags)(uint32_t flags, uint32_t a, uint32_t b) | ||
| 2167 | return (a & mask) | (b & ~mask); | 2167 | return (a & mask) | (b & ~mask); |
| 2168 | } | 2168 | } |
| 2169 | 2169 | ||
| 2170 | + | ||
| 2171 | +/* VFP support. We follow the convention used for VFP instrunctions: | ||
| 2172 | + Single precition routines have a "s" suffix, double precision a | ||
| 2173 | + "d" suffix. */ | ||
| 2174 | + | ||
| 2175 | +/* Convert host exception flags to vfp form. */ | ||
| 2176 | +static inline int vfp_exceptbits_from_host(int host_bits) | ||
| 2177 | +{ | ||
| 2178 | + int target_bits = 0; | ||
| 2179 | + | ||
| 2180 | + if (host_bits & float_flag_invalid) | ||
| 2181 | + target_bits |= 1; | ||
| 2182 | + if (host_bits & float_flag_divbyzero) | ||
| 2183 | + target_bits |= 2; | ||
| 2184 | + if (host_bits & float_flag_overflow) | ||
| 2185 | + target_bits |= 4; | ||
| 2186 | + if (host_bits & float_flag_underflow) | ||
| 2187 | + target_bits |= 8; | ||
| 2188 | + if (host_bits & float_flag_inexact) | ||
| 2189 | + target_bits |= 0x10; | ||
| 2190 | + return target_bits; | ||
| 2191 | +} | ||
| 2192 | + | ||
| 2193 | +uint32_t HELPER(vfp_get_fpscr)(CPUState *env) | ||
| 2194 | +{ | ||
| 2195 | + int i; | ||
| 2196 | + uint32_t fpscr; | ||
| 2197 | + | ||
| 2198 | + fpscr = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | ||
| 2199 | + | (env->vfp.vec_len << 16) | ||
| 2200 | + | (env->vfp.vec_stride << 20); | ||
| 2201 | + i = get_float_exception_flags(&env->vfp.fp_status); | ||
| 2202 | + fpscr |= vfp_exceptbits_from_host(i); | ||
| 2203 | + return fpscr; | ||
| 2204 | +} | ||
| 2205 | + | ||
| 2206 | +/* Convert vfp exception flags to target form. */ | ||
| 2207 | +static inline int vfp_exceptbits_to_host(int target_bits) | ||
| 2208 | +{ | ||
| 2209 | + int host_bits = 0; | ||
| 2210 | + | ||
| 2211 | + if (target_bits & 1) | ||
| 2212 | + host_bits |= float_flag_invalid; | ||
| 2213 | + if (target_bits & 2) | ||
| 2214 | + host_bits |= float_flag_divbyzero; | ||
| 2215 | + if (target_bits & 4) | ||
| 2216 | + host_bits |= float_flag_overflow; | ||
| 2217 | + if (target_bits & 8) | ||
| 2218 | + host_bits |= float_flag_underflow; | ||
| 2219 | + if (target_bits & 0x10) | ||
| 2220 | + host_bits |= float_flag_inexact; | ||
| 2221 | + return host_bits; | ||
| 2222 | +} | ||
| 2223 | + | ||
| 2224 | +void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val) | ||
| 2225 | +{ | ||
| 2226 | + int i; | ||
| 2227 | + uint32_t changed; | ||
| 2228 | + | ||
| 2229 | + changed = env->vfp.xregs[ARM_VFP_FPSCR]; | ||
| 2230 | + env->vfp.xregs[ARM_VFP_FPSCR] = (val & 0xffc8ffff); | ||
| 2231 | + env->vfp.vec_len = (val >> 16) & 7; | ||
| 2232 | + env->vfp.vec_stride = (val >> 20) & 3; | ||
| 2233 | + | ||
| 2234 | + changed ^= val; | ||
| 2235 | + if (changed & (3 << 22)) { | ||
| 2236 | + i = (val >> 22) & 3; | ||
| 2237 | + switch (i) { | ||
| 2238 | + case 0: | ||
| 2239 | + i = float_round_nearest_even; | ||
| 2240 | + break; | ||
| 2241 | + case 1: | ||
| 2242 | + i = float_round_up; | ||
| 2243 | + break; | ||
| 2244 | + case 2: | ||
| 2245 | + i = float_round_down; | ||
| 2246 | + break; | ||
| 2247 | + case 3: | ||
| 2248 | + i = float_round_to_zero; | ||
| 2249 | + break; | ||
| 2250 | + } | ||
| 2251 | + set_float_rounding_mode(i, &env->vfp.fp_status); | ||
| 2252 | + } | ||
| 2253 | + | ||
| 2254 | + i = vfp_exceptbits_to_host((val >> 8) & 0x1f); | ||
| 2255 | + set_float_exception_flags(i, &env->vfp.fp_status); | ||
| 2256 | + /* XXX: FZ and DN are not implemented. */ | ||
| 2257 | +} | ||
| 2258 | + | ||
| 2259 | +#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p)) | ||
| 2260 | + | ||
| 2261 | +#define VFP_BINOP(name) \ | ||
| 2262 | +float32 VFP_HELPER(name, s)(float32 a, float32 b, CPUState *env) \ | ||
| 2263 | +{ \ | ||
| 2264 | + return float32_ ## name (a, b, &env->vfp.fp_status); \ | ||
| 2265 | +} \ | ||
| 2266 | +float64 VFP_HELPER(name, d)(float64 a, float64 b, CPUState *env) \ | ||
| 2267 | +{ \ | ||
| 2268 | + return float64_ ## name (a, b, &env->vfp.fp_status); \ | ||
| 2269 | +} | ||
| 2270 | +VFP_BINOP(add) | ||
| 2271 | +VFP_BINOP(sub) | ||
| 2272 | +VFP_BINOP(mul) | ||
| 2273 | +VFP_BINOP(div) | ||
| 2274 | +#undef VFP_BINOP | ||
| 2275 | + | ||
| 2276 | +float32 VFP_HELPER(neg, s)(float32 a) | ||
| 2277 | +{ | ||
| 2278 | + return float32_chs(a); | ||
| 2279 | +} | ||
| 2280 | + | ||
| 2281 | +float64 VFP_HELPER(neg, d)(float64 a) | ||
| 2282 | +{ | ||
| 2283 | + return float32_chs(a); | ||
| 2284 | +} | ||
| 2285 | + | ||
| 2286 | +float32 VFP_HELPER(abs, s)(float32 a) | ||
| 2287 | +{ | ||
| 2288 | + return float32_abs(a); | ||
| 2289 | +} | ||
| 2290 | + | ||
| 2291 | +float64 VFP_HELPER(abs, d)(float64 a) | ||
| 2292 | +{ | ||
| 2293 | + return float32_abs(a); | ||
| 2294 | +} | ||
| 2295 | + | ||
| 2296 | +float32 VFP_HELPER(sqrt, s)(float32 a, CPUState *env) | ||
| 2297 | +{ | ||
| 2298 | + return float32_sqrt(a, &env->vfp.fp_status); | ||
| 2299 | +} | ||
| 2300 | + | ||
| 2301 | +float64 VFP_HELPER(sqrt, d)(float64 a, CPUState *env) | ||
| 2302 | +{ | ||
| 2303 | + return float64_sqrt(a, &env->vfp.fp_status); | ||
| 2304 | +} | ||
| 2305 | + | ||
| 2306 | +/* XXX: check quiet/signaling case */ | ||
| 2307 | +#define DO_VFP_cmp(p, type) \ | ||
| 2308 | +void VFP_HELPER(cmp, p)(type a, type b, CPUState *env) \ | ||
| 2309 | +{ \ | ||
| 2310 | + uint32_t flags; \ | ||
| 2311 | + switch(type ## _compare_quiet(a, b, &env->vfp.fp_status)) { \ | ||
| 2312 | + case 0: flags = 0x6; break; \ | ||
| 2313 | + case -1: flags = 0x8; break; \ | ||
| 2314 | + case 1: flags = 0x2; break; \ | ||
| 2315 | + default: case 2: flags = 0x3; break; \ | ||
| 2316 | + } \ | ||
| 2317 | + env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \ | ||
| 2318 | + | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \ | ||
| 2319 | +} \ | ||
| 2320 | +void VFP_HELPER(cmpe, p)(type a, type b, CPUState *env) \ | ||
| 2321 | +{ \ | ||
| 2322 | + uint32_t flags; \ | ||
| 2323 | + switch(type ## _compare(a, b, &env->vfp.fp_status)) { \ | ||
| 2324 | + case 0: flags = 0x6; break; \ | ||
| 2325 | + case -1: flags = 0x8; break; \ | ||
| 2326 | + case 1: flags = 0x2; break; \ | ||
| 2327 | + default: case 2: flags = 0x3; break; \ | ||
| 2328 | + } \ | ||
| 2329 | + env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28) \ | ||
| 2330 | + | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \ | ||
| 2331 | +} | ||
| 2332 | +DO_VFP_cmp(s, float32) | ||
| 2333 | +DO_VFP_cmp(d, float64) | ||
| 2334 | +#undef DO_VFP_cmp | ||
| 2335 | + | ||
| 2336 | +/* Helper routines to perform bitwise copies between float and int. */ | ||
| 2337 | +static inline float32 vfp_itos(uint32_t i) | ||
| 2338 | +{ | ||
| 2339 | + union { | ||
| 2340 | + uint32_t i; | ||
| 2341 | + float32 s; | ||
| 2342 | + } v; | ||
| 2343 | + | ||
| 2344 | + v.i = i; | ||
| 2345 | + return v.s; | ||
| 2346 | +} | ||
| 2347 | + | ||
| 2348 | +static inline uint32_t vfp_stoi(float32 s) | ||
| 2349 | +{ | ||
| 2350 | + union { | ||
| 2351 | + uint32_t i; | ||
| 2352 | + float32 s; | ||
| 2353 | + } v; | ||
| 2354 | + | ||
| 2355 | + v.s = s; | ||
| 2356 | + return v.i; | ||
| 2357 | +} | ||
| 2358 | + | ||
| 2359 | +static inline float64 vfp_itod(uint64_t i) | ||
| 2360 | +{ | ||
| 2361 | + union { | ||
| 2362 | + uint64_t i; | ||
| 2363 | + float64 d; | ||
| 2364 | + } v; | ||
| 2365 | + | ||
| 2366 | + v.i = i; | ||
| 2367 | + return v.d; | ||
| 2368 | +} | ||
| 2369 | + | ||
| 2370 | +static inline uint64_t vfp_dtoi(float64 d) | ||
| 2371 | +{ | ||
| 2372 | + union { | ||
| 2373 | + uint64_t i; | ||
| 2374 | + float64 d; | ||
| 2375 | + } v; | ||
| 2376 | + | ||
| 2377 | + v.d = d; | ||
| 2378 | + return v.i; | ||
| 2379 | +} | ||
| 2380 | + | ||
| 2381 | +/* Integer to float conversion. */ | ||
| 2382 | +float32 VFP_HELPER(uito, s)(float32 x, CPUState *env) | ||
| 2383 | +{ | ||
| 2384 | + return uint32_to_float32(vfp_stoi(x), &env->vfp.fp_status); | ||
| 2385 | +} | ||
| 2386 | + | ||
| 2387 | +float64 VFP_HELPER(uito, d)(float32 x, CPUState *env) | ||
| 2388 | +{ | ||
| 2389 | + return uint32_to_float64(vfp_stoi(x), &env->vfp.fp_status); | ||
| 2390 | +} | ||
| 2391 | + | ||
| 2392 | +float32 VFP_HELPER(sito, s)(float32 x, CPUState *env) | ||
| 2393 | +{ | ||
| 2394 | + return int32_to_float32(vfp_stoi(x), &env->vfp.fp_status); | ||
| 2395 | +} | ||
| 2396 | + | ||
| 2397 | +float64 VFP_HELPER(sito, d)(float32 x, CPUState *env) | ||
| 2398 | +{ | ||
| 2399 | + return int32_to_float64(vfp_stoi(x), &env->vfp.fp_status); | ||
| 2400 | +} | ||
| 2401 | + | ||
| 2402 | +/* Float to integer conversion. */ | ||
| 2403 | +float32 VFP_HELPER(toui, s)(float32 x, CPUState *env) | ||
| 2404 | +{ | ||
| 2405 | + return vfp_itos(float32_to_uint32(x, &env->vfp.fp_status)); | ||
| 2406 | +} | ||
| 2407 | + | ||
| 2408 | +float32 VFP_HELPER(toui, d)(float64 x, CPUState *env) | ||
| 2409 | +{ | ||
| 2410 | + return vfp_itos(float64_to_uint32(x, &env->vfp.fp_status)); | ||
| 2411 | +} | ||
| 2412 | + | ||
| 2413 | +float32 VFP_HELPER(tosi, s)(float32 x, CPUState *env) | ||
| 2414 | +{ | ||
| 2415 | + return vfp_itos(float32_to_int32(x, &env->vfp.fp_status)); | ||
| 2416 | +} | ||
| 2417 | + | ||
| 2418 | +float32 VFP_HELPER(tosi, d)(float64 x, CPUState *env) | ||
| 2419 | +{ | ||
| 2420 | + return vfp_itos(float64_to_int32(x, &env->vfp.fp_status)); | ||
| 2421 | +} | ||
| 2422 | + | ||
| 2423 | +float32 VFP_HELPER(touiz, s)(float32 x, CPUState *env) | ||
| 2424 | +{ | ||
| 2425 | + return vfp_itos(float32_to_uint32_round_to_zero(x, &env->vfp.fp_status)); | ||
| 2426 | +} | ||
| 2427 | + | ||
| 2428 | +float32 VFP_HELPER(touiz, d)(float64 x, CPUState *env) | ||
| 2429 | +{ | ||
| 2430 | + return vfp_itos(float64_to_uint32_round_to_zero(x, &env->vfp.fp_status)); | ||
| 2431 | +} | ||
| 2432 | + | ||
| 2433 | +float32 VFP_HELPER(tosiz, s)(float32 x, CPUState *env) | ||
| 2434 | +{ | ||
| 2435 | + return vfp_itos(float32_to_int32_round_to_zero(x, &env->vfp.fp_status)); | ||
| 2436 | +} | ||
| 2437 | + | ||
| 2438 | +float32 VFP_HELPER(tosiz, d)(float64 x, CPUState *env) | ||
| 2439 | +{ | ||
| 2440 | + return vfp_itos(float64_to_int32_round_to_zero(x, &env->vfp.fp_status)); | ||
| 2441 | +} | ||
| 2442 | + | ||
| 2443 | +/* floating point conversion */ | ||
| 2444 | +float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env) | ||
| 2445 | +{ | ||
| 2446 | + return float32_to_float64(x, &env->vfp.fp_status); | ||
| 2447 | +} | ||
| 2448 | + | ||
| 2449 | +float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env) | ||
| 2450 | +{ | ||
| 2451 | + return float64_to_float32(x, &env->vfp.fp_status); | ||
| 2452 | +} | ||
| 2453 | + | ||
| 2454 | +/* VFP3 fixed point conversion. */ | ||
| 2455 | +#define VFP_CONV_FIX(name, p, ftype, itype, sign) \ | ||
| 2456 | +ftype VFP_HELPER(name##to, p)(ftype x, uint32_t shift, CPUState *env) \ | ||
| 2457 | +{ \ | ||
| 2458 | + ftype tmp; \ | ||
| 2459 | + tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(x), \ | ||
| 2460 | + &env->vfp.fp_status); \ | ||
| 2461 | + return ftype##_scalbn(tmp, shift, &env->vfp.fp_status); \ | ||
| 2462 | +} \ | ||
| 2463 | +ftype VFP_HELPER(to##name, p)(ftype x, uint32_t shift, CPUState *env) \ | ||
| 2464 | +{ \ | ||
| 2465 | + ftype tmp; \ | ||
| 2466 | + tmp = ftype##_scalbn(x, shift, &env->vfp.fp_status); \ | ||
| 2467 | + return vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \ | ||
| 2468 | + &env->vfp.fp_status)); \ | ||
| 2469 | +} | ||
| 2470 | + | ||
| 2471 | +VFP_CONV_FIX(sh, d, float64, int16, ) | ||
| 2472 | +VFP_CONV_FIX(sl, d, float64, int32, ) | ||
| 2473 | +VFP_CONV_FIX(uh, d, float64, uint16, u) | ||
| 2474 | +VFP_CONV_FIX(ul, d, float64, uint32, u) | ||
| 2475 | +VFP_CONV_FIX(sh, s, float32, int16, ) | ||
| 2476 | +VFP_CONV_FIX(sl, s, float32, int32, ) | ||
| 2477 | +VFP_CONV_FIX(uh, s, float32, uint16, u) | ||
| 2478 | +VFP_CONV_FIX(ul, s, float32, uint32, u) | ||
| 2479 | +#undef VFP_CONV_FIX | ||
| 2480 | + | ||
| 2481 | +float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env) | ||
| 2482 | +{ | ||
| 2483 | + float_status *s = &env->vfp.fp_status; | ||
| 2484 | + float32 two = int32_to_float32(2, s); | ||
| 2485 | + return float32_sub(two, float32_mul(a, b, s), s); | ||
| 2486 | +} | ||
| 2487 | + | ||
| 2488 | +float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env) | ||
| 2489 | +{ | ||
| 2490 | + float_status *s = &env->vfp.fp_status; | ||
| 2491 | + float32 three = int32_to_float32(3, s); | ||
| 2492 | + return float32_sub(three, float32_mul(a, b, s), s); | ||
| 2493 | +} | ||
| 2494 | + | ||
| 2495 | +/* TODO: The architecture specifies the value that the estimate functions | ||
| 2496 | + should return. We return the exact reciprocal/root instead. */ | ||
| 2497 | +float32 HELPER(recpe_f32)(float32 a, CPUState *env) | ||
| 2498 | +{ | ||
| 2499 | + float_status *s = &env->vfp.fp_status; | ||
| 2500 | + float32 one = int32_to_float32(1, s); | ||
| 2501 | + return float32_div(one, a, s); | ||
| 2502 | +} | ||
| 2503 | + | ||
| 2504 | +float32 HELPER(rsqrte_f32)(float32 a, CPUState *env) | ||
| 2505 | +{ | ||
| 2506 | + float_status *s = &env->vfp.fp_status; | ||
| 2507 | + float32 one = int32_to_float32(1, s); | ||
| 2508 | + return float32_div(one, float32_sqrt(a, s), s); | ||
| 2509 | +} | ||
| 2510 | + | ||
| 2511 | +uint32_t HELPER(recpe_u32)(uint32_t a, CPUState *env) | ||
| 2512 | +{ | ||
| 2513 | + float_status *s = &env->vfp.fp_status; | ||
| 2514 | + float32 tmp; | ||
| 2515 | + tmp = int32_to_float32(a, s); | ||
| 2516 | + tmp = float32_scalbn(tmp, -32, s); | ||
| 2517 | + tmp = helper_recpe_f32(tmp, env); | ||
| 2518 | + tmp = float32_scalbn(tmp, 31, s); | ||
| 2519 | + return float32_to_int32(tmp, s); | ||
| 2520 | +} | ||
| 2521 | + | ||
| 2522 | +uint32_t HELPER(rsqrte_u32)(uint32_t a, CPUState *env) | ||
| 2523 | +{ | ||
| 2524 | + float_status *s = &env->vfp.fp_status; | ||
| 2525 | + float32 tmp; | ||
| 2526 | + tmp = int32_to_float32(a, s); | ||
| 2527 | + tmp = float32_scalbn(tmp, -32, s); | ||
| 2528 | + tmp = helper_rsqrte_f32(tmp, env); | ||
| 2529 | + tmp = float32_scalbn(tmp, 31, s); | ||
| 2530 | + return float32_to_int32(tmp, s); | ||
| 2531 | +} | ||
| 2532 | + |
target-arm/helpers.h
| @@ -122,6 +122,69 @@ DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t)) | @@ -122,6 +122,69 @@ DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t)) | ||
| 122 | DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t)) | 122 | DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t)) |
| 123 | DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t)) | 123 | DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t)) |
| 124 | 124 | ||
| 125 | +DEF_HELPER_1_1(vfp_get_fpscr, uint32_t, (CPUState *)) | ||
| 126 | +DEF_HELPER_0_2(vfp_set_fpscr, void, (CPUState *, uint32_t)) | ||
| 127 | + | ||
| 128 | +DEF_HELPER_1_3(vfp_adds, float32, (float32, float32, CPUState *)) | ||
| 129 | +DEF_HELPER_1_3(vfp_addd, float64, (float64, float64, CPUState *)) | ||
| 130 | +DEF_HELPER_1_3(vfp_subs, float32, (float32, float32, CPUState *)) | ||
| 131 | +DEF_HELPER_1_3(vfp_subd, float64, (float64, float64, CPUState *)) | ||
| 132 | +DEF_HELPER_1_3(vfp_muls, float32, (float32, float32, CPUState *)) | ||
| 133 | +DEF_HELPER_1_3(vfp_muld, float64, (float64, float64, CPUState *)) | ||
| 134 | +DEF_HELPER_1_3(vfp_divs, float32, (float32, float32, CPUState *)) | ||
| 135 | +DEF_HELPER_1_3(vfp_divd, float64, (float64, float64, CPUState *)) | ||
| 136 | +DEF_HELPER_1_1(vfp_negs, float32, (float32)) | ||
| 137 | +DEF_HELPER_1_1(vfp_negd, float64, (float64)) | ||
| 138 | +DEF_HELPER_1_1(vfp_abss, float32, (float32)) | ||
| 139 | +DEF_HELPER_1_1(vfp_absd, float64, (float64)) | ||
| 140 | +DEF_HELPER_1_2(vfp_sqrts, float32, (float32, CPUState *)) | ||
| 141 | +DEF_HELPER_1_2(vfp_sqrtd, float64, (float64, CPUState *)) | ||
| 142 | +DEF_HELPER_0_3(vfp_cmps, void, (float32, float32, CPUState *)) | ||
| 143 | +DEF_HELPER_0_3(vfp_cmpd, void, (float64, float64, CPUState *)) | ||
| 144 | +DEF_HELPER_0_3(vfp_cmpes, void, (float32, float32, CPUState *)) | ||
| 145 | +DEF_HELPER_0_3(vfp_cmped, void, (float64, float64, CPUState *)) | ||
| 146 | + | ||
| 147 | +DEF_HELPER_1_2(vfp_fcvtds, float64, (float32, CPUState *)) | ||
| 148 | +DEF_HELPER_1_2(vfp_fcvtsd, float32, (float64, CPUState *)) | ||
| 149 | + | ||
| 150 | +DEF_HELPER_1_2(vfp_uitos, float32, (float32, CPUState *)) | ||
| 151 | +DEF_HELPER_1_2(vfp_uitod, float64, (float32, CPUState *)) | ||
| 152 | +DEF_HELPER_1_2(vfp_sitos, float32, (float32, CPUState *)) | ||
| 153 | +DEF_HELPER_1_2(vfp_sitod, float64, (float32, CPUState *)) | ||
| 154 | + | ||
| 155 | +DEF_HELPER_1_2(vfp_touis, float32, (float32, CPUState *)) | ||
| 156 | +DEF_HELPER_1_2(vfp_touid, float32, (float64, CPUState *)) | ||
| 157 | +DEF_HELPER_1_2(vfp_touizs, float32, (float32, CPUState *)) | ||
| 158 | +DEF_HELPER_1_2(vfp_touizd, float32, (float64, CPUState *)) | ||
| 159 | +DEF_HELPER_1_2(vfp_tosis, float32, (float32, CPUState *)) | ||
| 160 | +DEF_HELPER_1_2(vfp_tosid, float32, (float64, CPUState *)) | ||
| 161 | +DEF_HELPER_1_2(vfp_tosizs, float32, (float32, CPUState *)) | ||
| 162 | +DEF_HELPER_1_2(vfp_tosizd, float32, (float64, CPUState *)) | ||
| 163 | + | ||
| 164 | +DEF_HELPER_1_3(vfp_toshs, float32, (float32, uint32_t, CPUState *)) | ||
| 165 | +DEF_HELPER_1_3(vfp_tosls, float32, (float32, uint32_t, CPUState *)) | ||
| 166 | +DEF_HELPER_1_3(vfp_touhs, float32, (float32, uint32_t, CPUState *)) | ||
| 167 | +DEF_HELPER_1_3(vfp_touls, float32, (float32, uint32_t, CPUState *)) | ||
| 168 | +DEF_HELPER_1_3(vfp_toshd, float64, (float64, uint32_t, CPUState *)) | ||
| 169 | +DEF_HELPER_1_3(vfp_tosld, float64, (float64, uint32_t, CPUState *)) | ||
| 170 | +DEF_HELPER_1_3(vfp_touhd, float64, (float64, uint32_t, CPUState *)) | ||
| 171 | +DEF_HELPER_1_3(vfp_tould, float64, (float64, uint32_t, CPUState *)) | ||
| 172 | +DEF_HELPER_1_3(vfp_shtos, float32, (float32, uint32_t, CPUState *)) | ||
| 173 | +DEF_HELPER_1_3(vfp_sltos, float32, (float32, uint32_t, CPUState *)) | ||
| 174 | +DEF_HELPER_1_3(vfp_uhtos, float32, (float32, uint32_t, CPUState *)) | ||
| 175 | +DEF_HELPER_1_3(vfp_ultos, float32, (float32, uint32_t, CPUState *)) | ||
| 176 | +DEF_HELPER_1_3(vfp_shtod, float64, (float64, uint32_t, CPUState *)) | ||
| 177 | +DEF_HELPER_1_3(vfp_sltod, float64, (float64, uint32_t, CPUState *)) | ||
| 178 | +DEF_HELPER_1_3(vfp_uhtod, float64, (float64, uint32_t, CPUState *)) | ||
| 179 | +DEF_HELPER_1_3(vfp_ultod, float64, (float64, uint32_t, CPUState *)) | ||
| 180 | + | ||
| 181 | +DEF_HELPER_1_3(recps_f32, float32, (float32, float32, CPUState *)) | ||
| 182 | +DEF_HELPER_1_3(rsqrts_f32, float32, (float32, float32, CPUState *)) | ||
| 183 | +DEF_HELPER_1_2(recpe_f32, float32, (float32, CPUState *)) | ||
| 184 | +DEF_HELPER_1_2(rsqrte_f32, float32, (float32, CPUState *)) | ||
| 185 | +DEF_HELPER_1_2(recpe_u32, uint32_t, (uint32_t, CPUState *)) | ||
| 186 | +DEF_HELPER_1_2(rsqrte_u32, uint32_t, (uint32_t, CPUState *)) | ||
| 187 | + | ||
| 125 | #undef DEF_HELPER | 188 | #undef DEF_HELPER |
| 126 | #undef DEF_HELPER_0_0 | 189 | #undef DEF_HELPER_0_0 |
| 127 | #undef DEF_HELPER_0_1 | 190 | #undef DEF_HELPER_0_1 |
target-arm/op.c
| @@ -252,319 +252,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) | @@ -252,319 +252,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) | ||
| 252 | FORCE_RET(); | 252 | FORCE_RET(); |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | -/* VFP support. We follow the convention used for VFP instrunctions: | ||
| 256 | - Single precition routines have a "s" suffix, double precision a | ||
| 257 | - "d" suffix. */ | ||
| 258 | - | ||
| 259 | -#define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void) | ||
| 260 | - | ||
| 261 | -#define VFP_BINOP(name) \ | ||
| 262 | -VFP_OP(name, s) \ | ||
| 263 | -{ \ | ||
| 264 | - FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status); \ | ||
| 265 | -} \ | ||
| 266 | -VFP_OP(name, d) \ | ||
| 267 | -{ \ | ||
| 268 | - FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status); \ | ||
| 269 | -} | ||
| 270 | -VFP_BINOP(add) | ||
| 271 | -VFP_BINOP(sub) | ||
| 272 | -VFP_BINOP(mul) | ||
| 273 | -VFP_BINOP(div) | ||
| 274 | -#undef VFP_BINOP | ||
| 275 | - | ||
| 276 | -#define VFP_HELPER(name) \ | ||
| 277 | -VFP_OP(name, s) \ | ||
| 278 | -{ \ | ||
| 279 | - do_vfp_##name##s(); \ | ||
| 280 | -} \ | ||
| 281 | -VFP_OP(name, d) \ | ||
| 282 | -{ \ | ||
| 283 | - do_vfp_##name##d(); \ | ||
| 284 | -} | ||
| 285 | -VFP_HELPER(abs) | ||
| 286 | -VFP_HELPER(sqrt) | ||
| 287 | -VFP_HELPER(cmp) | ||
| 288 | -VFP_HELPER(cmpe) | ||
| 289 | -#undef VFP_HELPER | ||
| 290 | - | ||
| 291 | -/* XXX: Will this do the right thing for NANs. Should invert the signbit | ||
| 292 | - without looking at the rest of the value. */ | ||
| 293 | -VFP_OP(neg, s) | ||
| 294 | -{ | ||
| 295 | - FT0s = float32_chs(FT0s); | ||
| 296 | -} | ||
| 297 | - | ||
| 298 | -VFP_OP(neg, d) | ||
| 299 | -{ | ||
| 300 | - FT0d = float64_chs(FT0d); | ||
| 301 | -} | ||
| 302 | - | ||
| 303 | -VFP_OP(F1_ld0, s) | ||
| 304 | -{ | ||
| 305 | - union { | ||
| 306 | - uint32_t i; | ||
| 307 | - float32 s; | ||
| 308 | - } v; | ||
| 309 | - v.i = 0; | ||
| 310 | - FT1s = v.s; | ||
| 311 | -} | ||
| 312 | - | ||
| 313 | -VFP_OP(F1_ld0, d) | ||
| 314 | -{ | ||
| 315 | - union { | ||
| 316 | - uint64_t i; | ||
| 317 | - float64 d; | ||
| 318 | - } v; | ||
| 319 | - v.i = 0; | ||
| 320 | - FT1d = v.d; | ||
| 321 | -} | ||
| 322 | - | ||
| 323 | -/* Helper routines to perform bitwise copies between float and int. */ | ||
| 324 | -static inline float32 vfp_itos(uint32_t i) | ||
| 325 | -{ | ||
| 326 | - union { | ||
| 327 | - uint32_t i; | ||
| 328 | - float32 s; | ||
| 329 | - } v; | ||
| 330 | - | ||
| 331 | - v.i = i; | ||
| 332 | - return v.s; | ||
| 333 | -} | ||
| 334 | - | ||
| 335 | -static inline uint32_t vfp_stoi(float32 s) | ||
| 336 | -{ | ||
| 337 | - union { | ||
| 338 | - uint32_t i; | ||
| 339 | - float32 s; | ||
| 340 | - } v; | ||
| 341 | - | ||
| 342 | - v.s = s; | ||
| 343 | - return v.i; | ||
| 344 | -} | ||
| 345 | - | ||
| 346 | -static inline float64 vfp_itod(uint64_t i) | ||
| 347 | -{ | ||
| 348 | - union { | ||
| 349 | - uint64_t i; | ||
| 350 | - float64 d; | ||
| 351 | - } v; | ||
| 352 | - | ||
| 353 | - v.i = i; | ||
| 354 | - return v.d; | ||
| 355 | -} | ||
| 356 | - | ||
| 357 | -static inline uint64_t vfp_dtoi(float64 d) | ||
| 358 | -{ | ||
| 359 | - union { | ||
| 360 | - uint64_t i; | ||
| 361 | - float64 d; | ||
| 362 | - } v; | ||
| 363 | - | ||
| 364 | - v.d = d; | ||
| 365 | - return v.i; | ||
| 366 | -} | ||
| 367 | - | ||
| 368 | -/* Integer to float conversion. */ | ||
| 369 | -VFP_OP(uito, s) | ||
| 370 | -{ | ||
| 371 | - FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); | ||
| 372 | -} | ||
| 373 | - | ||
| 374 | -VFP_OP(uito, d) | ||
| 375 | -{ | ||
| 376 | - FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); | ||
| 377 | -} | ||
| 378 | - | ||
| 379 | -VFP_OP(sito, s) | ||
| 380 | -{ | ||
| 381 | - FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status); | ||
| 382 | -} | ||
| 383 | - | ||
| 384 | -VFP_OP(sito, d) | ||
| 385 | -{ | ||
| 386 | - FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status); | ||
| 387 | -} | ||
| 388 | - | ||
| 389 | -/* Float to integer conversion. */ | ||
| 390 | -VFP_OP(toui, s) | ||
| 391 | -{ | ||
| 392 | - FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status)); | ||
| 393 | -} | ||
| 394 | - | ||
| 395 | -VFP_OP(toui, d) | ||
| 396 | -{ | ||
| 397 | - FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status)); | ||
| 398 | -} | ||
| 399 | - | ||
| 400 | -VFP_OP(tosi, s) | ||
| 401 | -{ | ||
| 402 | - FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status)); | ||
| 403 | -} | ||
| 404 | - | ||
| 405 | -VFP_OP(tosi, d) | ||
| 406 | -{ | ||
| 407 | - FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status)); | ||
| 408 | -} | ||
| 409 | - | ||
| 410 | -/* TODO: Set rounding mode properly. */ | ||
| 411 | -VFP_OP(touiz, s) | ||
| 412 | -{ | ||
| 413 | - FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status)); | ||
| 414 | -} | ||
| 415 | - | ||
| 416 | -VFP_OP(touiz, d) | ||
| 417 | -{ | ||
| 418 | - FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status)); | ||
| 419 | -} | ||
| 420 | - | ||
| 421 | -VFP_OP(tosiz, s) | ||
| 422 | -{ | ||
| 423 | - FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status)); | ||
| 424 | -} | ||
| 425 | - | ||
| 426 | -VFP_OP(tosiz, d) | ||
| 427 | -{ | ||
| 428 | - FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status)); | ||
| 429 | -} | ||
| 430 | - | ||
| 431 | -/* floating point conversion */ | ||
| 432 | -VFP_OP(fcvtd, s) | ||
| 433 | -{ | ||
| 434 | - FT0d = float32_to_float64(FT0s, &env->vfp.fp_status); | ||
| 435 | -} | ||
| 436 | - | ||
| 437 | -VFP_OP(fcvts, d) | ||
| 438 | -{ | ||
| 439 | - FT0s = float64_to_float32(FT0d, &env->vfp.fp_status); | ||
| 440 | -} | ||
| 441 | - | ||
| 442 | -/* VFP3 fixed point conversion. */ | ||
| 443 | -#define VFP_CONV_FIX(name, p, ftype, itype, sign) \ | ||
| 444 | -VFP_OP(name##to, p) \ | ||
| 445 | -{ \ | ||
| 446 | - ftype tmp; \ | ||
| 447 | - tmp = sign##int32_to_##ftype ((itype)vfp_##p##toi(FT0##p), \ | ||
| 448 | - &env->vfp.fp_status); \ | ||
| 449 | - FT0##p = ftype##_scalbn(tmp, PARAM1, &env->vfp.fp_status); \ | ||
| 450 | -} \ | ||
| 451 | -VFP_OP(to##name, p) \ | ||
| 452 | -{ \ | ||
| 453 | - ftype tmp; \ | ||
| 454 | - tmp = ftype##_scalbn(FT0##p, PARAM1, &env->vfp.fp_status); \ | ||
| 455 | - FT0##p = vfp_ito##p((itype)ftype##_to_##sign##int32_round_to_zero(tmp, \ | ||
| 456 | - &env->vfp.fp_status)); \ | ||
| 457 | -} | ||
| 458 | - | ||
| 459 | -VFP_CONV_FIX(sh, d, float64, int16, ) | ||
| 460 | -VFP_CONV_FIX(sl, d, float64, int32, ) | ||
| 461 | -VFP_CONV_FIX(uh, d, float64, uint16, u) | ||
| 462 | -VFP_CONV_FIX(ul, d, float64, uint32, u) | ||
| 463 | -VFP_CONV_FIX(sh, s, float32, int16, ) | ||
| 464 | -VFP_CONV_FIX(sl, s, float32, int32, ) | ||
| 465 | -VFP_CONV_FIX(uh, s, float32, uint16, u) | ||
| 466 | -VFP_CONV_FIX(ul, s, float32, uint32, u) | ||
| 467 | - | ||
| 468 | -/* Get and Put values from registers. */ | ||
| 469 | -VFP_OP(getreg_F0, d) | ||
| 470 | -{ | ||
| 471 | - FT0d = *(float64 *)((char *) env + PARAM1); | ||
| 472 | -} | ||
| 473 | - | ||
| 474 | -VFP_OP(getreg_F0, s) | ||
| 475 | -{ | ||
| 476 | - FT0s = *(float32 *)((char *) env + PARAM1); | ||
| 477 | -} | ||
| 478 | - | ||
| 479 | -VFP_OP(getreg_F1, d) | ||
| 480 | -{ | ||
| 481 | - FT1d = *(float64 *)((char *) env + PARAM1); | ||
| 482 | -} | ||
| 483 | - | ||
| 484 | -VFP_OP(getreg_F1, s) | ||
| 485 | -{ | ||
| 486 | - FT1s = *(float32 *)((char *) env + PARAM1); | ||
| 487 | -} | ||
| 488 | - | ||
| 489 | -VFP_OP(setreg_F0, d) | ||
| 490 | -{ | ||
| 491 | - *(float64 *)((char *) env + PARAM1) = FT0d; | ||
| 492 | -} | ||
| 493 | - | ||
| 494 | -VFP_OP(setreg_F0, s) | ||
| 495 | -{ | ||
| 496 | - *(float32 *)((char *) env + PARAM1) = FT0s; | ||
| 497 | -} | ||
| 498 | - | ||
| 499 | -void OPPROTO op_vfp_movl_T0_fpscr(void) | ||
| 500 | -{ | ||
| 501 | - do_vfp_get_fpscr (); | ||
| 502 | -} | ||
| 503 | - | ||
| 504 | -void OPPROTO op_vfp_movl_T0_fpscr_flags(void) | ||
| 505 | -{ | ||
| 506 | - T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28); | ||
| 507 | -} | ||
| 508 | - | ||
| 509 | -void OPPROTO op_vfp_movl_fpscr_T0(void) | ||
| 510 | -{ | ||
| 511 | - do_vfp_set_fpscr(); | ||
| 512 | -} | ||
| 513 | - | ||
| 514 | -void OPPROTO op_vfp_movl_T0_xreg(void) | ||
| 515 | -{ | ||
| 516 | - T0 = env->vfp.xregs[PARAM1]; | ||
| 517 | -} | ||
| 518 | - | ||
| 519 | -void OPPROTO op_vfp_movl_xreg_T0(void) | ||
| 520 | -{ | ||
| 521 | - env->vfp.xregs[PARAM1] = T0; | ||
| 522 | -} | ||
| 523 | - | ||
| 524 | -/* Move between FT0s to T0 */ | ||
| 525 | -void OPPROTO op_vfp_mrs(void) | ||
| 526 | -{ | ||
| 527 | - T0 = vfp_stoi(FT0s); | ||
| 528 | -} | ||
| 529 | - | ||
| 530 | -void OPPROTO op_vfp_msr(void) | ||
| 531 | -{ | ||
| 532 | - FT0s = vfp_itos(T0); | ||
| 533 | -} | ||
| 534 | - | ||
| 535 | -/* Move between FT0d and {T0,T1} */ | ||
| 536 | -void OPPROTO op_vfp_mrrd(void) | ||
| 537 | -{ | ||
| 538 | - CPU_DoubleU u; | ||
| 539 | - | ||
| 540 | - u.d = FT0d; | ||
| 541 | - T0 = u.l.lower; | ||
| 542 | - T1 = u.l.upper; | ||
| 543 | -} | ||
| 544 | - | ||
| 545 | -void OPPROTO op_vfp_mdrr(void) | ||
| 546 | -{ | ||
| 547 | - CPU_DoubleU u; | ||
| 548 | - | ||
| 549 | - u.l.lower = T0; | ||
| 550 | - u.l.upper = T1; | ||
| 551 | - FT0d = u.d; | ||
| 552 | -} | ||
| 553 | - | ||
| 554 | -/* Load immediate. PARAM1 is the 32 most significant bits of the value. */ | ||
| 555 | -void OPPROTO op_vfp_fconstd(void) | ||
| 556 | -{ | ||
| 557 | - CPU_DoubleU u; | ||
| 558 | - u.l.upper = PARAM1; | ||
| 559 | - u.l.lower = 0; | ||
| 560 | - FT0d = u.d; | ||
| 561 | -} | ||
| 562 | - | ||
| 563 | -void OPPROTO op_vfp_fconsts(void) | ||
| 564 | -{ | ||
| 565 | - FT0s = vfp_itos(PARAM1); | ||
| 566 | -} | ||
| 567 | - | ||
| 568 | void OPPROTO op_movl_cp_T0(void) | 255 | void OPPROTO op_movl_cp_T0(void) |
| 569 | { | 256 | { |
| 570 | helper_set_cp(env, PARAM1, T0); | 257 | helper_set_cp(env, PARAM1, T0); |
target-arm/op_helper.c
| @@ -40,194 +40,6 @@ void cpu_unlock(void) | @@ -40,194 +40,6 @@ void cpu_unlock(void) | ||
| 40 | spin_unlock(&global_cpu_lock); | 40 | spin_unlock(&global_cpu_lock); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | -/* VFP support. */ | ||
| 44 | - | ||
| 45 | -void do_vfp_abss(void) | ||
| 46 | -{ | ||
| 47 | - FT0s = float32_abs(FT0s); | ||
| 48 | -} | ||
| 49 | - | ||
| 50 | -void do_vfp_absd(void) | ||
| 51 | -{ | ||
| 52 | - FT0d = float64_abs(FT0d); | ||
| 53 | -} | ||
| 54 | - | ||
| 55 | -void do_vfp_sqrts(void) | ||
| 56 | -{ | ||
| 57 | - FT0s = float32_sqrt(FT0s, &env->vfp.fp_status); | ||
| 58 | -} | ||
| 59 | - | ||
| 60 | -void do_vfp_sqrtd(void) | ||
| 61 | -{ | ||
| 62 | - FT0d = float64_sqrt(FT0d, &env->vfp.fp_status); | ||
| 63 | -} | ||
| 64 | - | ||
| 65 | -/* XXX: check quiet/signaling case */ | ||
| 66 | -#define DO_VFP_cmp(p, size) \ | ||
| 67 | -void do_vfp_cmp##p(void) \ | ||
| 68 | -{ \ | ||
| 69 | - uint32_t flags; \ | ||
| 70 | - switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\ | ||
| 71 | - case 0: flags = 0x6; break;\ | ||
| 72 | - case -1: flags = 0x8; break;\ | ||
| 73 | - case 1: flags = 0x2; break;\ | ||
| 74 | - default: case 2: flags = 0x3; break;\ | ||
| 75 | - }\ | ||
| 76 | - env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\ | ||
| 77 | - | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \ | ||
| 78 | - FORCE_RET(); \ | ||
| 79 | -}\ | ||
| 80 | -\ | ||
| 81 | -void do_vfp_cmpe##p(void) \ | ||
| 82 | -{ \ | ||
| 83 | - uint32_t flags; \ | ||
| 84 | - switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\ | ||
| 85 | - case 0: flags = 0x6; break;\ | ||
| 86 | - case -1: flags = 0x8; break;\ | ||
| 87 | - case 1: flags = 0x2; break;\ | ||
| 88 | - default: case 2: flags = 0x3; break;\ | ||
| 89 | - }\ | ||
| 90 | - env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\ | ||
| 91 | - | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \ | ||
| 92 | - FORCE_RET(); \ | ||
| 93 | -} | ||
| 94 | -DO_VFP_cmp(s, 32) | ||
| 95 | -DO_VFP_cmp(d, 64) | ||
| 96 | -#undef DO_VFP_cmp | ||
| 97 | - | ||
| 98 | -/* Convert host exception flags to vfp form. */ | ||
| 99 | -static inline int vfp_exceptbits_from_host(int host_bits) | ||
| 100 | -{ | ||
| 101 | - int target_bits = 0; | ||
| 102 | - | ||
| 103 | - if (host_bits & float_flag_invalid) | ||
| 104 | - target_bits |= 1; | ||
| 105 | - if (host_bits & float_flag_divbyzero) | ||
| 106 | - target_bits |= 2; | ||
| 107 | - if (host_bits & float_flag_overflow) | ||
| 108 | - target_bits |= 4; | ||
| 109 | - if (host_bits & float_flag_underflow) | ||
| 110 | - target_bits |= 8; | ||
| 111 | - if (host_bits & float_flag_inexact) | ||
| 112 | - target_bits |= 0x10; | ||
| 113 | - return target_bits; | ||
| 114 | -} | ||
| 115 | - | ||
| 116 | -/* Convert vfp exception flags to target form. */ | ||
| 117 | -static inline int vfp_exceptbits_to_host(int target_bits) | ||
| 118 | -{ | ||
| 119 | - int host_bits = 0; | ||
| 120 | - | ||
| 121 | - if (target_bits & 1) | ||
| 122 | - host_bits |= float_flag_invalid; | ||
| 123 | - if (target_bits & 2) | ||
| 124 | - host_bits |= float_flag_divbyzero; | ||
| 125 | - if (target_bits & 4) | ||
| 126 | - host_bits |= float_flag_overflow; | ||
| 127 | - if (target_bits & 8) | ||
| 128 | - host_bits |= float_flag_underflow; | ||
| 129 | - if (target_bits & 0x10) | ||
| 130 | - host_bits |= float_flag_inexact; | ||
| 131 | - return host_bits; | ||
| 132 | -} | ||
| 133 | - | ||
| 134 | -void do_vfp_set_fpscr(void) | ||
| 135 | -{ | ||
| 136 | - int i; | ||
| 137 | - uint32_t changed; | ||
| 138 | - | ||
| 139 | - changed = env->vfp.xregs[ARM_VFP_FPSCR]; | ||
| 140 | - env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff); | ||
| 141 | - env->vfp.vec_len = (T0 >> 16) & 7; | ||
| 142 | - env->vfp.vec_stride = (T0 >> 20) & 3; | ||
| 143 | - | ||
| 144 | - changed ^= T0; | ||
| 145 | - if (changed & (3 << 22)) { | ||
| 146 | - i = (T0 >> 22) & 3; | ||
| 147 | - switch (i) { | ||
| 148 | - case 0: | ||
| 149 | - i = float_round_nearest_even; | ||
| 150 | - break; | ||
| 151 | - case 1: | ||
| 152 | - i = float_round_up; | ||
| 153 | - break; | ||
| 154 | - case 2: | ||
| 155 | - i = float_round_down; | ||
| 156 | - break; | ||
| 157 | - case 3: | ||
| 158 | - i = float_round_to_zero; | ||
| 159 | - break; | ||
| 160 | - } | ||
| 161 | - set_float_rounding_mode(i, &env->vfp.fp_status); | ||
| 162 | - } | ||
| 163 | - | ||
| 164 | - i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f); | ||
| 165 | - set_float_exception_flags(i, &env->vfp.fp_status); | ||
| 166 | - /* XXX: FZ and DN are not implemented. */ | ||
| 167 | -} | ||
| 168 | - | ||
| 169 | -void do_vfp_get_fpscr(void) | ||
| 170 | -{ | ||
| 171 | - int i; | ||
| 172 | - | ||
| 173 | - T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16) | ||
| 174 | - | (env->vfp.vec_stride << 20); | ||
| 175 | - i = get_float_exception_flags(&env->vfp.fp_status); | ||
| 176 | - T0 |= vfp_exceptbits_from_host(i); | ||
| 177 | -} | ||
| 178 | - | ||
| 179 | -float32 helper_recps_f32(float32 a, float32 b) | ||
| 180 | -{ | ||
| 181 | - float_status *s = &env->vfp.fp_status; | ||
| 182 | - float32 two = int32_to_float32(2, s); | ||
| 183 | - return float32_sub(two, float32_mul(a, b, s), s); | ||
| 184 | -} | ||
| 185 | - | ||
| 186 | -float32 helper_rsqrts_f32(float32 a, float32 b) | ||
| 187 | -{ | ||
| 188 | - float_status *s = &env->vfp.fp_status; | ||
| 189 | - float32 three = int32_to_float32(3, s); | ||
| 190 | - return float32_sub(three, float32_mul(a, b, s), s); | ||
| 191 | -} | ||
| 192 | - | ||
| 193 | -/* TODO: The architecture specifies the value that the estimate functions | ||
| 194 | - should return. We return the exact reciprocal/root instead. */ | ||
| 195 | -float32 helper_recpe_f32(float32 a) | ||
| 196 | -{ | ||
| 197 | - float_status *s = &env->vfp.fp_status; | ||
| 198 | - float32 one = int32_to_float32(1, s); | ||
| 199 | - return float32_div(one, a, s); | ||
| 200 | -} | ||
| 201 | - | ||
| 202 | -float32 helper_rsqrte_f32(float32 a) | ||
| 203 | -{ | ||
| 204 | - float_status *s = &env->vfp.fp_status; | ||
| 205 | - float32 one = int32_to_float32(1, s); | ||
| 206 | - return float32_div(one, float32_sqrt(a, s), s); | ||
| 207 | -} | ||
| 208 | - | ||
| 209 | -uint32_t helper_recpe_u32(uint32_t a) | ||
| 210 | -{ | ||
| 211 | - float_status *s = &env->vfp.fp_status; | ||
| 212 | - float32 tmp; | ||
| 213 | - tmp = int32_to_float32(a, s); | ||
| 214 | - tmp = float32_scalbn(tmp, -32, s); | ||
| 215 | - tmp = helper_recpe_f32(tmp); | ||
| 216 | - tmp = float32_scalbn(tmp, 31, s); | ||
| 217 | - return float32_to_int32(tmp, s); | ||
| 218 | -} | ||
| 219 | - | ||
| 220 | -uint32_t helper_rsqrte_u32(uint32_t a) | ||
| 221 | -{ | ||
| 222 | - float_status *s = &env->vfp.fp_status; | ||
| 223 | - float32 tmp; | ||
| 224 | - tmp = int32_to_float32(a, s); | ||
| 225 | - tmp = float32_scalbn(tmp, -32, s); | ||
| 226 | - tmp = helper_rsqrte_f32(tmp); | ||
| 227 | - tmp = float32_scalbn(tmp, 31, s); | ||
| 228 | - return float32_to_int32(tmp, s); | ||
| 229 | -} | ||
| 230 | - | ||
| 231 | void helper_neon_tbl(int rn, int maxindex) | 43 | void helper_neon_tbl(int rn, int maxindex) |
| 232 | { | 44 | { |
| 233 | uint32_t val; | 45 | uint32_t val; |
target-arm/op_mem.h
| @@ -77,24 +77,6 @@ void OPPROTO glue(op_stqex,MEMSUFFIX)(void) | @@ -77,24 +77,6 @@ void OPPROTO glue(op_stqex,MEMSUFFIX)(void) | ||
| 77 | FORCE_RET(); | 77 | FORCE_RET(); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | -/* Floating point load/store. Address is in T1 */ | ||
| 81 | -#define VFP_MEM_OP(p, w) \ | ||
| 82 | -void OPPROTO glue(op_vfp_ld##p,MEMSUFFIX)(void) \ | ||
| 83 | -{ \ | ||
| 84 | - FT0##p = glue(ldf##w,MEMSUFFIX)(T1); \ | ||
| 85 | - FORCE_RET(); \ | ||
| 86 | -} \ | ||
| 87 | -void OPPROTO glue(op_vfp_st##p,MEMSUFFIX)(void) \ | ||
| 88 | -{ \ | ||
| 89 | - glue(stf##w,MEMSUFFIX)(T1, FT0##p); \ | ||
| 90 | - FORCE_RET(); \ | ||
| 91 | -} | ||
| 92 | - | ||
| 93 | -VFP_MEM_OP(s,l) | ||
| 94 | -VFP_MEM_OP(d,q) | ||
| 95 | - | ||
| 96 | -#undef VFP_MEM_OP | ||
| 97 | - | ||
| 98 | /* iwMMXt load/store. Address is in T1 */ | 80 | /* iwMMXt load/store. Address is in T1 */ |
| 99 | #define MMX_MEM_OP(name, ldname) \ | 81 | #define MMX_MEM_OP(name, ldname) \ |
| 100 | void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \ | 82 | void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \ |
target-arm/op_neon.h
| @@ -14,6 +14,29 @@ | @@ -14,6 +14,29 @@ | ||
| 14 | #define NFS &env->vfp.fp_status | 14 | #define NFS &env->vfp.fp_status |
| 15 | #define NEON_OP(name) void OPPROTO op_neon_##name (void) | 15 | #define NEON_OP(name) void OPPROTO op_neon_##name (void) |
| 16 | 16 | ||
| 17 | +/* Helper routines to perform bitwise copies between float and int. */ | ||
| 18 | +static inline float32 vfp_itos(uint32_t i) | ||
| 19 | +{ | ||
| 20 | + union { | ||
| 21 | + uint32_t i; | ||
| 22 | + float32 s; | ||
| 23 | + } v; | ||
| 24 | + | ||
| 25 | + v.i = i; | ||
| 26 | + return v.s; | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +static inline uint32_t vfp_stoi(float32 s) | ||
| 30 | +{ | ||
| 31 | + union { | ||
| 32 | + uint32_t i; | ||
| 33 | + float32 s; | ||
| 34 | + } v; | ||
| 35 | + | ||
| 36 | + v.s = s; | ||
| 37 | + return v.i; | ||
| 38 | +} | ||
| 39 | + | ||
| 17 | NEON_OP(getreg_T0) | 40 | NEON_OP(getreg_T0) |
| 18 | { | 41 | { |
| 19 | T0 = *(uint32_t *)((char *) env + PARAM1); | 42 | T0 = *(uint32_t *)((char *) env + PARAM1); |
| @@ -754,18 +777,6 @@ NEON_VOP(qrdmulh_s32, neon_s32, 1) | @@ -754,18 +777,6 @@ NEON_VOP(qrdmulh_s32, neon_s32, 1) | ||
| 754 | #undef NEON_FN | 777 | #undef NEON_FN |
| 755 | #undef NEON_QDMULH32 | 778 | #undef NEON_QDMULH32 |
| 756 | 779 | ||
| 757 | -NEON_OP(recps_f32) | ||
| 758 | -{ | ||
| 759 | - T0 = vfp_stoi(helper_recps_f32(vfp_itos(T0), vfp_itos(T1))); | ||
| 760 | - FORCE_RET(); | ||
| 761 | -} | ||
| 762 | - | ||
| 763 | -NEON_OP(rsqrts_f32) | ||
| 764 | -{ | ||
| 765 | - T0 = vfp_stoi(helper_rsqrts_f32(vfp_itos(T0), vfp_itos(T1))); | ||
| 766 | - FORCE_RET(); | ||
| 767 | -} | ||
| 768 | - | ||
| 769 | /* Floating point comparisons produce an integer result. */ | 780 | /* Floating point comparisons produce an integer result. */ |
| 770 | #define NEON_VOP_FCMP(name, cmp) \ | 781 | #define NEON_VOP_FCMP(name, cmp) \ |
| 771 | NEON_OP(name) \ | 782 | NEON_OP(name) \ |
| @@ -1702,27 +1713,6 @@ NEON_OP(zip_u16) | @@ -1702,27 +1713,6 @@ NEON_OP(zip_u16) | ||
| 1702 | FORCE_RET(); | 1713 | FORCE_RET(); |
| 1703 | } | 1714 | } |
| 1704 | 1715 | ||
| 1705 | -/* Reciprocal/root estimate. */ | ||
| 1706 | -NEON_OP(recpe_u32) | ||
| 1707 | -{ | ||
| 1708 | - T0 = helper_recpe_u32(T0); | ||
| 1709 | -} | ||
| 1710 | - | ||
| 1711 | -NEON_OP(rsqrte_u32) | ||
| 1712 | -{ | ||
| 1713 | - T0 = helper_rsqrte_u32(T0); | ||
| 1714 | -} | ||
| 1715 | - | ||
| 1716 | -NEON_OP(recpe_f32) | ||
| 1717 | -{ | ||
| 1718 | - FT0s = helper_recpe_f32(FT0s); | ||
| 1719 | -} | ||
| 1720 | - | ||
| 1721 | -NEON_OP(rsqrte_f32) | ||
| 1722 | -{ | ||
| 1723 | - FT0s = helper_rsqrte_f32(FT0s); | ||
| 1724 | -} | ||
| 1725 | - | ||
| 1726 | /* Table lookup. This accessed the register file directly. */ | 1716 | /* Table lookup. This accessed the register file directly. */ |
| 1727 | NEON_OP(tbl) | 1717 | NEON_OP(tbl) |
| 1728 | { | 1718 | { |
target-arm/translate.c
| @@ -79,6 +79,7 @@ extern int loglevel; | @@ -79,6 +79,7 @@ extern int loglevel; | ||
| 79 | static TCGv cpu_env; | 79 | static TCGv cpu_env; |
| 80 | /* FIXME: These should be removed. */ | 80 | /* FIXME: These should be removed. */ |
| 81 | static TCGv cpu_T[3]; | 81 | static TCGv cpu_T[3]; |
| 82 | +static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d; | ||
| 82 | 83 | ||
| 83 | /* initialize TCG globals. */ | 84 | /* initialize TCG globals. */ |
| 84 | void arm_translate_init(void) | 85 | void arm_translate_init(void) |
| @@ -959,16 +960,16 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, | @@ -959,16 +960,16 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, | ||
| 959 | } | 960 | } |
| 960 | } | 961 | } |
| 961 | 962 | ||
| 962 | -#define VFP_OP(name) \ | ||
| 963 | -static inline void gen_vfp_##name(int dp) \ | ||
| 964 | -{ \ | ||
| 965 | - if (dp) \ | ||
| 966 | - gen_op_vfp_##name##d(); \ | ||
| 967 | - else \ | ||
| 968 | - gen_op_vfp_##name##s(); \ | 963 | +#define VFP_OP2(name) \ |
| 964 | +static inline void gen_vfp_##name(int dp) \ | ||
| 965 | +{ \ | ||
| 966 | + if (dp) \ | ||
| 967 | + gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \ | ||
| 968 | + else \ | ||
| 969 | + gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \ | ||
| 969 | } | 970 | } |
| 970 | 971 | ||
| 971 | -#define VFP_OP1(name) \ | 972 | +#define VFP_OP1i(name) \ |
| 972 | static inline void gen_vfp_##name(int dp, int arg) \ | 973 | static inline void gen_vfp_##name(int dp, int arg) \ |
| 973 | { \ | 974 | { \ |
| 974 | if (dp) \ | 975 | if (dp) \ |
| @@ -977,55 +978,141 @@ static inline void gen_vfp_##name(int dp, int arg) \ | @@ -977,55 +978,141 @@ static inline void gen_vfp_##name(int dp, int arg) \ | ||
| 977 | gen_op_vfp_##name##s(arg); \ | 978 | gen_op_vfp_##name##s(arg); \ |
| 978 | } | 979 | } |
| 979 | 980 | ||
| 980 | -VFP_OP(add) | ||
| 981 | -VFP_OP(sub) | ||
| 982 | -VFP_OP(mul) | ||
| 983 | -VFP_OP(div) | ||
| 984 | -VFP_OP(neg) | ||
| 985 | -VFP_OP(abs) | ||
| 986 | -VFP_OP(sqrt) | ||
| 987 | -VFP_OP(cmp) | ||
| 988 | -VFP_OP(cmpe) | ||
| 989 | -VFP_OP(F1_ld0) | ||
| 990 | -VFP_OP(uito) | ||
| 991 | -VFP_OP(sito) | ||
| 992 | -VFP_OP(toui) | ||
| 993 | -VFP_OP(touiz) | ||
| 994 | -VFP_OP(tosi) | ||
| 995 | -VFP_OP(tosiz) | ||
| 996 | -VFP_OP1(tosh) | ||
| 997 | -VFP_OP1(tosl) | ||
| 998 | -VFP_OP1(touh) | ||
| 999 | -VFP_OP1(toul) | ||
| 1000 | -VFP_OP1(shto) | ||
| 1001 | -VFP_OP1(slto) | ||
| 1002 | -VFP_OP1(uhto) | ||
| 1003 | -VFP_OP1(ulto) | ||
| 1004 | - | ||
| 1005 | -#undef VFP_OP | ||
| 1006 | - | ||
| 1007 | -static inline void gen_vfp_fconst(int dp, uint32_t val) | 981 | +VFP_OP2(add) |
| 982 | +VFP_OP2(sub) | ||
| 983 | +VFP_OP2(mul) | ||
| 984 | +VFP_OP2(div) | ||
| 985 | + | ||
| 986 | +#undef VFP_OP2 | ||
| 987 | + | ||
| 988 | +static inline void gen_vfp_abs(int dp) | ||
| 989 | +{ | ||
| 990 | + if (dp) | ||
| 991 | + gen_helper_vfp_absd(cpu_F0d, cpu_F0d); | ||
| 992 | + else | ||
| 993 | + gen_helper_vfp_abss(cpu_F0s, cpu_F0s); | ||
| 994 | +} | ||
| 995 | + | ||
| 996 | +static inline void gen_vfp_neg(int dp) | ||
| 997 | +{ | ||
| 998 | + if (dp) | ||
| 999 | + gen_helper_vfp_negd(cpu_F0d, cpu_F0d); | ||
| 1000 | + else | ||
| 1001 | + gen_helper_vfp_negs(cpu_F0s, cpu_F0s); | ||
| 1002 | +} | ||
| 1003 | + | ||
| 1004 | +static inline void gen_vfp_sqrt(int dp) | ||
| 1005 | +{ | ||
| 1006 | + if (dp) | ||
| 1007 | + gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env); | ||
| 1008 | + else | ||
| 1009 | + gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1010 | +} | ||
| 1011 | + | ||
| 1012 | +static inline void gen_vfp_cmp(int dp) | ||
| 1013 | +{ | ||
| 1014 | + if (dp) | ||
| 1015 | + gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env); | ||
| 1016 | + else | ||
| 1017 | + gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env); | ||
| 1018 | +} | ||
| 1019 | + | ||
| 1020 | +static inline void gen_vfp_cmpe(int dp) | ||
| 1021 | +{ | ||
| 1022 | + if (dp) | ||
| 1023 | + gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env); | ||
| 1024 | + else | ||
| 1025 | + gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env); | ||
| 1026 | +} | ||
| 1027 | + | ||
| 1028 | +static inline void gen_vfp_F1_ld0(int dp) | ||
| 1029 | +{ | ||
| 1030 | + if (dp) | ||
| 1031 | + tcg_gen_movi_i64(cpu_F0d, 0); | ||
| 1032 | + else | ||
| 1033 | + tcg_gen_movi_i32(cpu_F0s, 0); | ||
| 1034 | +} | ||
| 1035 | + | ||
| 1036 | +static inline void gen_vfp_uito(int dp) | ||
| 1037 | +{ | ||
| 1038 | + if (dp) | ||
| 1039 | + gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env); | ||
| 1040 | + else | ||
| 1041 | + gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1042 | +} | ||
| 1043 | + | ||
| 1044 | +static inline void gen_vfp_sito(int dp) | ||
| 1045 | +{ | ||
| 1046 | + if (dp) | ||
| 1047 | + gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env); | ||
| 1048 | + else | ||
| 1049 | + gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1050 | +} | ||
| 1051 | + | ||
| 1052 | +static inline void gen_vfp_toui(int dp) | ||
| 1053 | +{ | ||
| 1054 | + if (dp) | ||
| 1055 | + gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env); | ||
| 1056 | + else | ||
| 1057 | + gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1058 | +} | ||
| 1059 | + | ||
| 1060 | +static inline void gen_vfp_touiz(int dp) | ||
| 1061 | +{ | ||
| 1062 | + if (dp) | ||
| 1063 | + gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env); | ||
| 1064 | + else | ||
| 1065 | + gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1066 | +} | ||
| 1067 | + | ||
| 1068 | +static inline void gen_vfp_tosi(int dp) | ||
| 1069 | +{ | ||
| 1070 | + if (dp) | ||
| 1071 | + gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env); | ||
| 1072 | + else | ||
| 1073 | + gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env); | ||
| 1074 | +} | ||
| 1075 | + | ||
| 1076 | +static inline void gen_vfp_tosiz(int dp) | ||
| 1008 | { | 1077 | { |
| 1009 | if (dp) | 1078 | if (dp) |
| 1010 | - gen_op_vfp_fconstd(val); | 1079 | + gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env); |
| 1011 | else | 1080 | else |
| 1012 | - gen_op_vfp_fconsts(val); | 1081 | + gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env); |
| 1082 | +} | ||
| 1083 | + | ||
| 1084 | +#define VFP_GEN_FIX(name) \ | ||
| 1085 | +static inline void gen_vfp_##name(int dp, int shift) \ | ||
| 1086 | +{ \ | ||
| 1087 | + if (dp) \ | ||
| 1088 | + gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\ | ||
| 1089 | + else \ | ||
| 1090 | + gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\ | ||
| 1013 | } | 1091 | } |
| 1092 | +VFP_GEN_FIX(tosh) | ||
| 1093 | +VFP_GEN_FIX(tosl) | ||
| 1094 | +VFP_GEN_FIX(touh) | ||
| 1095 | +VFP_GEN_FIX(toul) | ||
| 1096 | +VFP_GEN_FIX(shto) | ||
| 1097 | +VFP_GEN_FIX(slto) | ||
| 1098 | +VFP_GEN_FIX(uhto) | ||
| 1099 | +VFP_GEN_FIX(ulto) | ||
| 1100 | +#undef VFP_GEN_FIX | ||
| 1014 | 1101 | ||
| 1015 | static inline void gen_vfp_ld(DisasContext *s, int dp) | 1102 | static inline void gen_vfp_ld(DisasContext *s, int dp) |
| 1016 | { | 1103 | { |
| 1017 | if (dp) | 1104 | if (dp) |
| 1018 | - gen_ldst(vfp_ldd, s); | 1105 | + tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s)); |
| 1019 | else | 1106 | else |
| 1020 | - gen_ldst(vfp_lds, s); | 1107 | + tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s)); |
| 1021 | } | 1108 | } |
| 1022 | 1109 | ||
| 1023 | static inline void gen_vfp_st(DisasContext *s, int dp) | 1110 | static inline void gen_vfp_st(DisasContext *s, int dp) |
| 1024 | { | 1111 | { |
| 1025 | if (dp) | 1112 | if (dp) |
| 1026 | - gen_ldst(vfp_std, s); | 1113 | + tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s)); |
| 1027 | else | 1114 | else |
| 1028 | - gen_ldst(vfp_sts, s); | 1115 | + tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s)); |
| 1029 | } | 1116 | } |
| 1030 | 1117 | ||
| 1031 | static inline long | 1118 | static inline long |
| @@ -1055,28 +1142,33 @@ neon_reg_offset (int reg, int n) | @@ -1055,28 +1142,33 @@ neon_reg_offset (int reg, int n) | ||
| 1055 | #define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n)) | 1142 | #define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n)) |
| 1056 | #define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n)) | 1143 | #define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n)) |
| 1057 | 1144 | ||
| 1145 | +#define tcg_gen_ld_f32 tcg_gen_ld_i32 | ||
| 1146 | +#define tcg_gen_ld_f64 tcg_gen_ld_i64 | ||
| 1147 | +#define tcg_gen_st_f32 tcg_gen_st_i32 | ||
| 1148 | +#define tcg_gen_st_f64 tcg_gen_st_i64 | ||
| 1149 | + | ||
| 1058 | static inline void gen_mov_F0_vreg(int dp, int reg) | 1150 | static inline void gen_mov_F0_vreg(int dp, int reg) |
| 1059 | { | 1151 | { |
| 1060 | if (dp) | 1152 | if (dp) |
| 1061 | - gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg)); | 1153 | + tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); |
| 1062 | else | 1154 | else |
| 1063 | - gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg)); | 1155 | + tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); |
| 1064 | } | 1156 | } |
| 1065 | 1157 | ||
| 1066 | static inline void gen_mov_F1_vreg(int dp, int reg) | 1158 | static inline void gen_mov_F1_vreg(int dp, int reg) |
| 1067 | { | 1159 | { |
| 1068 | if (dp) | 1160 | if (dp) |
| 1069 | - gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg)); | 1161 | + tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg)); |
| 1070 | else | 1162 | else |
| 1071 | - gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg)); | 1163 | + tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg)); |
| 1072 | } | 1164 | } |
| 1073 | 1165 | ||
| 1074 | static inline void gen_mov_vreg_F0(int dp, int reg) | 1166 | static inline void gen_mov_vreg_F0(int dp, int reg) |
| 1075 | { | 1167 | { |
| 1076 | if (dp) | 1168 | if (dp) |
| 1077 | - gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg)); | 1169 | + tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); |
| 1078 | else | 1170 | else |
| 1079 | - gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg)); | 1171 | + tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); |
| 1080 | } | 1172 | } |
| 1081 | 1173 | ||
| 1082 | #define ARM_CP_RW_BIT (1 << 20) | 1174 | #define ARM_CP_RW_BIT (1 << 20) |
| @@ -2262,6 +2354,20 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) | @@ -2262,6 +2354,20 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) | ||
| 2262 | #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) | 2354 | #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) |
| 2263 | #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) | 2355 | #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) |
| 2264 | 2356 | ||
| 2357 | +/* Move between integer and VFP cores. */ | ||
| 2358 | +static TCGv gen_vfp_mrs(void) | ||
| 2359 | +{ | ||
| 2360 | + TCGv tmp = new_tmp(); | ||
| 2361 | + tcg_gen_mov_i32(tmp, cpu_F0s); | ||
| 2362 | + return tmp; | ||
| 2363 | +} | ||
| 2364 | + | ||
| 2365 | +static void gen_vfp_msr(TCGv tmp) | ||
| 2366 | +{ | ||
| 2367 | + tcg_gen_mov_i32(cpu_F0s, tmp); | ||
| 2368 | + dead_tmp(tmp); | ||
| 2369 | +} | ||
| 2370 | + | ||
| 2265 | static inline int | 2371 | static inline int |
| 2266 | vfp_enabled(CPUState * env) | 2372 | vfp_enabled(CPUState * env) |
| 2267 | { | 2373 | { |
| @@ -2274,6 +2380,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2274,6 +2380,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2274 | { | 2380 | { |
| 2275 | uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; | 2381 | uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; |
| 2276 | int dp, veclen; | 2382 | int dp, veclen; |
| 2383 | + TCGv tmp; | ||
| 2277 | 2384 | ||
| 2278 | if (!arm_feature(env, ARM_FEATURE_VFP)) | 2385 | if (!arm_feature(env, ARM_FEATURE_VFP)) |
| 2279 | return 1; | 2386 | return 1; |
| @@ -2396,18 +2503,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2396,18 +2503,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2396 | 2503 | ||
| 2397 | switch (rn) { | 2504 | switch (rn) { |
| 2398 | case ARM_VFP_FPSID: | 2505 | case ARM_VFP_FPSID: |
| 2399 | - /* VFP2 allows access for FSID from userspace. | 2506 | + /* VFP2 allows access to FSID from userspace. |
| 2400 | VFP3 restricts all id registers to privileged | 2507 | VFP3 restricts all id registers to privileged |
| 2401 | accesses. */ | 2508 | accesses. */ |
| 2402 | if (IS_USER(s) | 2509 | if (IS_USER(s) |
| 2403 | && arm_feature(env, ARM_FEATURE_VFP3)) | 2510 | && arm_feature(env, ARM_FEATURE_VFP3)) |
| 2404 | return 1; | 2511 | return 1; |
| 2405 | - gen_op_vfp_movl_T0_xreg(rn); | 2512 | + tmp = load_cpu_field(vfp.xregs[rn]); |
| 2406 | break; | 2513 | break; |
| 2407 | case ARM_VFP_FPEXC: | 2514 | case ARM_VFP_FPEXC: |
| 2408 | if (IS_USER(s)) | 2515 | if (IS_USER(s)) |
| 2409 | return 1; | 2516 | return 1; |
| 2410 | - gen_op_vfp_movl_T0_xreg(rn); | 2517 | + tmp = load_cpu_field(vfp.xregs[rn]); |
| 2411 | break; | 2518 | break; |
| 2412 | case ARM_VFP_FPINST: | 2519 | case ARM_VFP_FPINST: |
| 2413 | case ARM_VFP_FPINST2: | 2520 | case ARM_VFP_FPINST2: |
| @@ -2415,36 +2522,41 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2415,36 +2522,41 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2415 | if (IS_USER(s) | 2522 | if (IS_USER(s) |
| 2416 | || arm_feature(env, ARM_FEATURE_VFP3)) | 2523 | || arm_feature(env, ARM_FEATURE_VFP3)) |
| 2417 | return 1; | 2524 | return 1; |
| 2418 | - gen_op_vfp_movl_T0_xreg(rn); | 2525 | + tmp = load_cpu_field(vfp.xregs[rn]); |
| 2419 | break; | 2526 | break; |
| 2420 | case ARM_VFP_FPSCR: | 2527 | case ARM_VFP_FPSCR: |
| 2421 | - if (rd == 15) | ||
| 2422 | - gen_op_vfp_movl_T0_fpscr_flags(); | ||
| 2423 | - else | ||
| 2424 | - gen_op_vfp_movl_T0_fpscr(); | 2528 | + if (rd == 15) { |
| 2529 | + tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]); | ||
| 2530 | + tcg_gen_andi_i32(tmp, tmp, 0xf0000000); | ||
| 2531 | + } else { | ||
| 2532 | + tmp = new_tmp(); | ||
| 2533 | + gen_helper_vfp_get_fpscr(tmp, cpu_env); | ||
| 2534 | + } | ||
| 2425 | break; | 2535 | break; |
| 2426 | case ARM_VFP_MVFR0: | 2536 | case ARM_VFP_MVFR0: |
| 2427 | case ARM_VFP_MVFR1: | 2537 | case ARM_VFP_MVFR1: |
| 2428 | if (IS_USER(s) | 2538 | if (IS_USER(s) |
| 2429 | || !arm_feature(env, ARM_FEATURE_VFP3)) | 2539 | || !arm_feature(env, ARM_FEATURE_VFP3)) |
| 2430 | return 1; | 2540 | return 1; |
| 2431 | - gen_op_vfp_movl_T0_xreg(rn); | 2541 | + tmp = load_cpu_field(vfp.xregs[rn]); |
| 2432 | break; | 2542 | break; |
| 2433 | default: | 2543 | default: |
| 2434 | return 1; | 2544 | return 1; |
| 2435 | } | 2545 | } |
| 2436 | } else { | 2546 | } else { |
| 2437 | gen_mov_F0_vreg(0, rn); | 2547 | gen_mov_F0_vreg(0, rn); |
| 2438 | - gen_op_vfp_mrs(); | 2548 | + tmp = gen_vfp_mrs(); |
| 2439 | } | 2549 | } |
| 2440 | if (rd == 15) { | 2550 | if (rd == 15) { |
| 2441 | /* Set the 4 flag bits in the CPSR. */ | 2551 | /* Set the 4 flag bits in the CPSR. */ |
| 2442 | - gen_set_nzcv(cpu_T[0]); | ||
| 2443 | - } else | ||
| 2444 | - gen_movl_reg_T0(s, rd); | 2552 | + gen_set_nzcv(tmp); |
| 2553 | + dead_tmp(tmp); | ||
| 2554 | + } else { | ||
| 2555 | + store_reg(s, rd, tmp); | ||
| 2556 | + } | ||
| 2445 | } else { | 2557 | } else { |
| 2446 | /* arm->vfp */ | 2558 | /* arm->vfp */ |
| 2447 | - gen_movl_T0_reg(s, rd); | 2559 | + tmp = load_reg(s, rd); |
| 2448 | if (insn & (1 << 21)) { | 2560 | if (insn & (1 << 21)) { |
| 2449 | rn >>= 1; | 2561 | rn >>= 1; |
| 2450 | /* system register */ | 2562 | /* system register */ |
| @@ -2455,24 +2567,25 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2455,24 +2567,25 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2455 | /* Writes are ignored. */ | 2567 | /* Writes are ignored. */ |
| 2456 | break; | 2568 | break; |
| 2457 | case ARM_VFP_FPSCR: | 2569 | case ARM_VFP_FPSCR: |
| 2458 | - gen_op_vfp_movl_fpscr_T0(); | 2570 | + gen_helper_vfp_set_fpscr(cpu_env, tmp); |
| 2571 | + dead_tmp(tmp); | ||
| 2459 | gen_lookup_tb(s); | 2572 | gen_lookup_tb(s); |
| 2460 | break; | 2573 | break; |
| 2461 | case ARM_VFP_FPEXC: | 2574 | case ARM_VFP_FPEXC: |
| 2462 | if (IS_USER(s)) | 2575 | if (IS_USER(s)) |
| 2463 | return 1; | 2576 | return 1; |
| 2464 | - gen_op_vfp_movl_xreg_T0(rn); | 2577 | + store_cpu_field(tmp, vfp.xregs[rn]); |
| 2465 | gen_lookup_tb(s); | 2578 | gen_lookup_tb(s); |
| 2466 | break; | 2579 | break; |
| 2467 | case ARM_VFP_FPINST: | 2580 | case ARM_VFP_FPINST: |
| 2468 | case ARM_VFP_FPINST2: | 2581 | case ARM_VFP_FPINST2: |
| 2469 | - gen_op_vfp_movl_xreg_T0(rn); | 2582 | + store_cpu_field(tmp, vfp.xregs[rn]); |
| 2470 | break; | 2583 | break; |
| 2471 | default: | 2584 | default: |
| 2472 | return 1; | 2585 | return 1; |
| 2473 | } | 2586 | } |
| 2474 | } else { | 2587 | } else { |
| 2475 | - gen_op_vfp_msr(); | 2588 | + gen_vfp_msr(tmp); |
| 2476 | gen_mov_vreg_F0(0, rn); | 2589 | gen_mov_vreg_F0(0, rn); |
| 2477 | } | 2590 | } |
| 2478 | } | 2591 | } |
| @@ -2640,14 +2753,15 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2640,14 +2753,15 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2640 | else | 2753 | else |
| 2641 | i |= 0x4000; | 2754 | i |= 0x4000; |
| 2642 | n |= i << 16; | 2755 | n |= i << 16; |
| 2756 | + tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32); | ||
| 2643 | } else { | 2757 | } else { |
| 2644 | if (i & 0x40) | 2758 | if (i & 0x40) |
| 2645 | i |= 0x780; | 2759 | i |= 0x780; |
| 2646 | else | 2760 | else |
| 2647 | i |= 0x800; | 2761 | i |= 0x800; |
| 2648 | n |= i << 19; | 2762 | n |= i << 19; |
| 2763 | + tcg_gen_movi_i32(cpu_F0d, ((uint64_t)n) << 32); | ||
| 2649 | } | 2764 | } |
| 2650 | - gen_vfp_fconst(dp, n); | ||
| 2651 | break; | 2765 | break; |
| 2652 | case 15: /* extension space */ | 2766 | case 15: /* extension space */ |
| 2653 | switch (rn) { | 2767 | switch (rn) { |
| @@ -2678,9 +2792,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2678,9 +2792,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2678 | break; | 2792 | break; |
| 2679 | case 15: /* single<->double conversion */ | 2793 | case 15: /* single<->double conversion */ |
| 2680 | if (dp) | 2794 | if (dp) |
| 2681 | - gen_op_vfp_fcvtsd(); | 2795 | + gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env); |
| 2682 | else | 2796 | else |
| 2683 | - gen_op_vfp_fcvtds(); | 2797 | + gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env); |
| 2684 | break; | 2798 | break; |
| 2685 | case 16: /* fuito */ | 2799 | case 16: /* fuito */ |
| 2686 | gen_vfp_uito(dp); | 2800 | gen_vfp_uito(dp); |
| @@ -2814,31 +2928,35 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -2814,31 +2928,35 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 2814 | if (insn & ARM_CP_RW_BIT) { | 2928 | if (insn & ARM_CP_RW_BIT) { |
| 2815 | /* vfp->arm */ | 2929 | /* vfp->arm */ |
| 2816 | if (dp) { | 2930 | if (dp) { |
| 2817 | - gen_mov_F0_vreg(1, rm); | ||
| 2818 | - gen_op_vfp_mrrd(); | ||
| 2819 | - gen_movl_reg_T0(s, rd); | ||
| 2820 | - gen_movl_reg_T1(s, rn); | 2931 | + gen_mov_F0_vreg(0, rm * 2); |
| 2932 | + tmp = gen_vfp_mrs(); | ||
| 2933 | + store_reg(s, rd, tmp); | ||
| 2934 | + gen_mov_F0_vreg(0, rm * 2 + 1); | ||
| 2935 | + tmp = gen_vfp_mrs(); | ||
| 2936 | + store_reg(s, rn, tmp); | ||
| 2821 | } else { | 2937 | } else { |
| 2822 | gen_mov_F0_vreg(0, rm); | 2938 | gen_mov_F0_vreg(0, rm); |
| 2823 | - gen_op_vfp_mrs(); | ||
| 2824 | - gen_movl_reg_T0(s, rn); | 2939 | + tmp = gen_vfp_mrs(); |
| 2940 | + store_reg(s, rn, tmp); | ||
| 2825 | gen_mov_F0_vreg(0, rm + 1); | 2941 | gen_mov_F0_vreg(0, rm + 1); |
| 2826 | - gen_op_vfp_mrs(); | ||
| 2827 | - gen_movl_reg_T0(s, rd); | 2942 | + tmp = gen_vfp_mrs(); |
| 2943 | + store_reg(s, rd, tmp); | ||
| 2828 | } | 2944 | } |
| 2829 | } else { | 2945 | } else { |
| 2830 | /* arm->vfp */ | 2946 | /* arm->vfp */ |
| 2831 | if (dp) { | 2947 | if (dp) { |
| 2832 | - gen_movl_T0_reg(s, rd); | ||
| 2833 | - gen_movl_T1_reg(s, rn); | ||
| 2834 | - gen_op_vfp_mdrr(); | ||
| 2835 | - gen_mov_vreg_F0(1, rm); | 2948 | + tmp = load_reg(s, rd); |
| 2949 | + gen_vfp_msr(tmp); | ||
| 2950 | + gen_mov_vreg_F0(0, rm * 2); | ||
| 2951 | + tmp = load_reg(s, rn); | ||
| 2952 | + gen_vfp_msr(tmp); | ||
| 2953 | + gen_mov_vreg_F0(0, rm * 2 + 1); | ||
| 2836 | } else { | 2954 | } else { |
| 2837 | - gen_movl_T0_reg(s, rn); | ||
| 2838 | - gen_op_vfp_msr(); | 2955 | + tmp = load_reg(s, rn); |
| 2956 | + gen_vfp_msr(tmp); | ||
| 2839 | gen_mov_vreg_F0(0, rm); | 2957 | gen_mov_vreg_F0(0, rm); |
| 2840 | - gen_movl_T0_reg(s, rd); | ||
| 2841 | - gen_op_vfp_msr(); | 2958 | + tmp = load_reg(s, rd); |
| 2959 | + gen_vfp_msr(tmp); | ||
| 2842 | gen_mov_vreg_F0(0, rm + 1); | 2960 | gen_mov_vreg_F0(0, rm + 1); |
| 2843 | } | 2961 | } |
| 2844 | } | 2962 | } |
| @@ -3993,9 +4111,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -3993,9 +4111,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 3993 | break; | 4111 | break; |
| 3994 | case 31: | 4112 | case 31: |
| 3995 | if (size == 0) | 4113 | if (size == 0) |
| 3996 | - gen_op_neon_recps_f32(); | 4114 | + gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env); |
| 3997 | else | 4115 | else |
| 3998 | - gen_op_neon_rsqrts_f32(); | 4116 | + gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env); |
| 3999 | break; | 4117 | break; |
| 4000 | default: | 4118 | default: |
| 4001 | abort(); | 4119 | abort(); |
| @@ -4242,19 +4360,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -4242,19 +4360,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 4242 | } else if (op == 15 || op == 16) { | 4360 | } else if (op == 15 || op == 16) { |
| 4243 | /* VCVT fixed-point. */ | 4361 | /* VCVT fixed-point. */ |
| 4244 | for (pass = 0; pass < (q ? 4 : 2); pass++) { | 4362 | for (pass = 0; pass < (q ? 4 : 2); pass++) { |
| 4245 | - gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass)); | 4363 | + tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); |
| 4246 | if (op & 1) { | 4364 | if (op & 1) { |
| 4247 | if (u) | 4365 | if (u) |
| 4248 | - gen_op_vfp_ultos(shift); | 4366 | + gen_vfp_ulto(0, shift); |
| 4249 | else | 4367 | else |
| 4250 | - gen_op_vfp_sltos(shift); | 4368 | + gen_vfp_slto(0, shift); |
| 4251 | } else { | 4369 | } else { |
| 4252 | if (u) | 4370 | if (u) |
| 4253 | - gen_op_vfp_touls(shift); | 4371 | + gen_vfp_toul(0, shift); |
| 4254 | else | 4372 | else |
| 4255 | - gen_op_vfp_tosls(shift); | 4373 | + gen_vfp_tosl(0, shift); |
| 4256 | } | 4374 | } |
| 4257 | - gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass)); | 4375 | + tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); |
| 4258 | } | 4376 | } |
| 4259 | } else { | 4377 | } else { |
| 4260 | return 1; | 4378 | return 1; |
| @@ -4898,7 +5016,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -4898,7 +5016,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 4898 | elementwise: | 5016 | elementwise: |
| 4899 | for (pass = 0; pass < (q ? 4 : 2); pass++) { | 5017 | for (pass = 0; pass < (q ? 4 : 2); pass++) { |
| 4900 | if (op == 30 || op == 31 || op >= 58) { | 5018 | if (op == 30 || op == 31 || op >= 58) { |
| 4901 | - gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass)); | 5019 | + tcg_gen_ld_f32(cpu_F0s, cpu_env, |
| 5020 | + neon_reg_offset(rm, pass)); | ||
| 4902 | } else { | 5021 | } else { |
| 4903 | NEON_GET_REG(T0, rm, pass); | 5022 | NEON_GET_REG(T0, rm, pass); |
| 4904 | } | 5023 | } |
| @@ -5041,10 +5160,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -5041,10 +5160,10 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 5041 | gen_op_neon_ceq_f32(); | 5160 | gen_op_neon_ceq_f32(); |
| 5042 | break; | 5161 | break; |
| 5043 | case 30: /* Float VABS */ | 5162 | case 30: /* Float VABS */ |
| 5044 | - gen_op_vfp_abss(); | 5163 | + gen_vfp_abs(0); |
| 5045 | break; | 5164 | break; |
| 5046 | case 31: /* Float VNEG */ | 5165 | case 31: /* Float VNEG */ |
| 5047 | - gen_op_vfp_negs(); | 5166 | + gen_vfp_neg(0); |
| 5048 | break; | 5167 | break; |
| 5049 | case 32: /* VSWP */ | 5168 | case 32: /* VSWP */ |
| 5050 | NEON_GET_REG(T1, rd, pass); | 5169 | NEON_GET_REG(T1, rd, pass); |
| @@ -5061,35 +5180,36 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | @@ -5061,35 +5180,36 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) | ||
| 5061 | NEON_SET_REG(T1, rm, pass); | 5180 | NEON_SET_REG(T1, rm, pass); |
| 5062 | break; | 5181 | break; |
| 5063 | case 56: /* Integer VRECPE */ | 5182 | case 56: /* Integer VRECPE */ |
| 5064 | - gen_op_neon_recpe_u32(); | 5183 | + gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env); |
| 5065 | break; | 5184 | break; |
| 5066 | case 57: /* Integer VRSQRTE */ | 5185 | case 57: /* Integer VRSQRTE */ |
| 5067 | - gen_op_neon_rsqrte_u32(); | 5186 | + gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env); |
| 5068 | break; | 5187 | break; |
| 5069 | case 58: /* Float VRECPE */ | 5188 | case 58: /* Float VRECPE */ |
| 5070 | - gen_op_neon_recpe_f32(); | 5189 | + gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env); |
| 5071 | break; | 5190 | break; |
| 5072 | case 59: /* Float VRSQRTE */ | 5191 | case 59: /* Float VRSQRTE */ |
| 5073 | - gen_op_neon_rsqrte_f32(); | 5192 | + gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env); |
| 5074 | break; | 5193 | break; |
| 5075 | case 60: /* VCVT.F32.S32 */ | 5194 | case 60: /* VCVT.F32.S32 */ |
| 5076 | - gen_op_vfp_tosizs(); | 5195 | + gen_vfp_tosiz(0); |
| 5077 | break; | 5196 | break; |
| 5078 | case 61: /* VCVT.F32.U32 */ | 5197 | case 61: /* VCVT.F32.U32 */ |
| 5079 | - gen_op_vfp_touizs(); | 5198 | + gen_vfp_touiz(0); |
| 5080 | break; | 5199 | break; |
| 5081 | case 62: /* VCVT.S32.F32 */ | 5200 | case 62: /* VCVT.S32.F32 */ |
| 5082 | - gen_op_vfp_sitos(); | 5201 | + gen_vfp_sito(0); |
| 5083 | break; | 5202 | break; |
| 5084 | case 63: /* VCVT.U32.F32 */ | 5203 | case 63: /* VCVT.U32.F32 */ |
| 5085 | - gen_op_vfp_uitos(); | 5204 | + gen_vfp_uito(0); |
| 5086 | break; | 5205 | break; |
| 5087 | default: | 5206 | default: |
| 5088 | /* Reserved: 21, 29, 39-56 */ | 5207 | /* Reserved: 21, 29, 39-56 */ |
| 5089 | return 1; | 5208 | return 1; |
| 5090 | } | 5209 | } |
| 5091 | if (op == 30 || op == 31 || op >= 58) { | 5210 | if (op == 30 || op == 31 || op >= 58) { |
| 5092 | - gen_op_vfp_setreg_F0s(neon_reg_offset(rm, pass)); | 5211 | + tcg_gen_st_f32(cpu_F0s, cpu_env, |
| 5212 | + neon_reg_offset(rd, pass)); | ||
| 5093 | } else { | 5213 | } else { |
| 5094 | NEON_SET_REG(T0, rd, pass); | 5214 | NEON_SET_REG(T0, rd, pass); |
| 5095 | } | 5215 | } |
| @@ -8062,6 +8182,10 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -8062,6 +8182,10 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
| 8062 | dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR; | 8182 | dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR; |
| 8063 | } | 8183 | } |
| 8064 | #endif | 8184 | #endif |
| 8185 | + cpu_F0s = tcg_temp_new(TCG_TYPE_I32); | ||
| 8186 | + cpu_F1s = tcg_temp_new(TCG_TYPE_I32); | ||
| 8187 | + cpu_F0d = tcg_temp_new(TCG_TYPE_I64); | ||
| 8188 | + cpu_F1d = tcg_temp_new(TCG_TYPE_I64); | ||
| 8065 | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; | 8189 | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
| 8066 | lj = -1; | 8190 | lj = -1; |
| 8067 | /* Reset the conditional execution bits immediately. This avoids | 8191 | /* Reset the conditional execution bits immediately. This avoids |