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 | 168 | int vec_len; |
169 | 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 | 171 | /* scratch space when Tn are not sufficient. */ |
175 | 172 | uint32_t scratch[8]; |
176 | 173 | ... | ... |
target-arm/exec.h
... | ... | @@ -25,13 +25,6 @@ register uint32_t T0 asm(AREG1); |
25 | 25 | register uint32_t T1 asm(AREG2); |
26 | 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 | 28 | #define M0 env->iwmmxt.val |
36 | 29 | |
37 | 30 | #include "cpu.h" |
... | ... | @@ -83,23 +76,5 @@ void cpu_loop_exit(void); |
83 | 76 | |
84 | 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 | 79 | void helper_neon_tbl(int rn, int maxindex); |
105 | 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 | 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 | 122 | DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t)) |
123 | 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 | 188 | #undef DEF_HELPER |
126 | 189 | #undef DEF_HELPER_0_0 |
127 | 190 | #undef DEF_HELPER_0_1 | ... | ... |
target-arm/op.c
... | ... | @@ -252,319 +252,6 @@ void OPPROTO op_rorl_T1_T0_cc(void) |
252 | 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 | 255 | void OPPROTO op_movl_cp_T0(void) |
569 | 256 | { |
570 | 257 | helper_set_cp(env, PARAM1, T0); | ... | ... |
target-arm/op_helper.c
... | ... | @@ -40,194 +40,6 @@ void cpu_unlock(void) |
40 | 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 | 43 | void helper_neon_tbl(int rn, int maxindex) |
232 | 44 | { |
233 | 45 | uint32_t val; | ... | ... |
target-arm/op_mem.h
... | ... | @@ -77,24 +77,6 @@ void OPPROTO glue(op_stqex,MEMSUFFIX)(void) |
77 | 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 | 80 | /* iwMMXt load/store. Address is in T1 */ |
99 | 81 | #define MMX_MEM_OP(name, ldname) \ |
100 | 82 | void OPPROTO glue(op_iwmmxt_ld##name,MEMSUFFIX)(void) \ | ... | ... |
target-arm/op_neon.h
... | ... | @@ -14,6 +14,29 @@ |
14 | 14 | #define NFS &env->vfp.fp_status |
15 | 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 | 40 | NEON_OP(getreg_T0) |
18 | 41 | { |
19 | 42 | T0 = *(uint32_t *)((char *) env + PARAM1); |
... | ... | @@ -754,18 +777,6 @@ NEON_VOP(qrdmulh_s32, neon_s32, 1) |
754 | 777 | #undef NEON_FN |
755 | 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 | 780 | /* Floating point comparisons produce an integer result. */ |
770 | 781 | #define NEON_VOP_FCMP(name, cmp) \ |
771 | 782 | NEON_OP(name) \ |
... | ... | @@ -1702,27 +1713,6 @@ NEON_OP(zip_u16) |
1702 | 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 | 1716 | /* Table lookup. This accessed the register file directly. */ |
1727 | 1717 | NEON_OP(tbl) |
1728 | 1718 | { | ... | ... |
target-arm/translate.c
... | ... | @@ -79,6 +79,7 @@ extern int loglevel; |
79 | 79 | static TCGv cpu_env; |
80 | 80 | /* FIXME: These should be removed. */ |
81 | 81 | static TCGv cpu_T[3]; |
82 | +static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d; | |
82 | 83 | |
83 | 84 | /* initialize TCG globals. */ |
84 | 85 | void arm_translate_init(void) |
... | ... | @@ -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 | 973 | static inline void gen_vfp_##name(int dp, int arg) \ |
973 | 974 | { \ |
974 | 975 | if (dp) \ |
... | ... | @@ -977,55 +978,141 @@ static inline void gen_vfp_##name(int dp, int arg) \ |
977 | 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 | 1078 | if (dp) |
1010 | - gen_op_vfp_fconstd(val); | |
1079 | + gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env); | |
1011 | 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 | 1102 | static inline void gen_vfp_ld(DisasContext *s, int dp) |
1016 | 1103 | { |
1017 | 1104 | if (dp) |
1018 | - gen_ldst(vfp_ldd, s); | |
1105 | + tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s)); | |
1019 | 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 | 1110 | static inline void gen_vfp_st(DisasContext *s, int dp) |
1024 | 1111 | { |
1025 | 1112 | if (dp) |
1026 | - gen_ldst(vfp_std, s); | |
1113 | + tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s)); | |
1027 | 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 | 1118 | static inline long |
... | ... | @@ -1055,28 +1142,33 @@ neon_reg_offset (int reg, int n) |
1055 | 1142 | #define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n)) |
1056 | 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 | 1150 | static inline void gen_mov_F0_vreg(int dp, int reg) |
1059 | 1151 | { |
1060 | 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 | 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 | 1158 | static inline void gen_mov_F1_vreg(int dp, int reg) |
1067 | 1159 | { |
1068 | 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 | 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 | 1166 | static inline void gen_mov_vreg_F0(int dp, int reg) |
1075 | 1167 | { |
1076 | 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 | 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 | 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 | 2354 | #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) |
2263 | 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 | 2371 | static inline int |
2266 | 2372 | vfp_enabled(CPUState * env) |
2267 | 2373 | { |
... | ... | @@ -2274,6 +2380,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2274 | 2380 | { |
2275 | 2381 | uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; |
2276 | 2382 | int dp, veclen; |
2383 | + TCGv tmp; | |
2277 | 2384 | |
2278 | 2385 | if (!arm_feature(env, ARM_FEATURE_VFP)) |
2279 | 2386 | return 1; |
... | ... | @@ -2396,18 +2503,18 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2396 | 2503 | |
2397 | 2504 | switch (rn) { |
2398 | 2505 | case ARM_VFP_FPSID: |
2399 | - /* VFP2 allows access for FSID from userspace. | |
2506 | + /* VFP2 allows access to FSID from userspace. | |
2400 | 2507 | VFP3 restricts all id registers to privileged |
2401 | 2508 | accesses. */ |
2402 | 2509 | if (IS_USER(s) |
2403 | 2510 | && arm_feature(env, ARM_FEATURE_VFP3)) |
2404 | 2511 | return 1; |
2405 | - gen_op_vfp_movl_T0_xreg(rn); | |
2512 | + tmp = load_cpu_field(vfp.xregs[rn]); | |
2406 | 2513 | break; |
2407 | 2514 | case ARM_VFP_FPEXC: |
2408 | 2515 | if (IS_USER(s)) |
2409 | 2516 | return 1; |
2410 | - gen_op_vfp_movl_T0_xreg(rn); | |
2517 | + tmp = load_cpu_field(vfp.xregs[rn]); | |
2411 | 2518 | break; |
2412 | 2519 | case ARM_VFP_FPINST: |
2413 | 2520 | case ARM_VFP_FPINST2: |
... | ... | @@ -2415,36 +2522,41 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2415 | 2522 | if (IS_USER(s) |
2416 | 2523 | || arm_feature(env, ARM_FEATURE_VFP3)) |
2417 | 2524 | return 1; |
2418 | - gen_op_vfp_movl_T0_xreg(rn); | |
2525 | + tmp = load_cpu_field(vfp.xregs[rn]); | |
2419 | 2526 | break; |
2420 | 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 | 2535 | break; |
2426 | 2536 | case ARM_VFP_MVFR0: |
2427 | 2537 | case ARM_VFP_MVFR1: |
2428 | 2538 | if (IS_USER(s) |
2429 | 2539 | || !arm_feature(env, ARM_FEATURE_VFP3)) |
2430 | 2540 | return 1; |
2431 | - gen_op_vfp_movl_T0_xreg(rn); | |
2541 | + tmp = load_cpu_field(vfp.xregs[rn]); | |
2432 | 2542 | break; |
2433 | 2543 | default: |
2434 | 2544 | return 1; |
2435 | 2545 | } |
2436 | 2546 | } else { |
2437 | 2547 | gen_mov_F0_vreg(0, rn); |
2438 | - gen_op_vfp_mrs(); | |
2548 | + tmp = gen_vfp_mrs(); | |
2439 | 2549 | } |
2440 | 2550 | if (rd == 15) { |
2441 | 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 | 2557 | } else { |
2446 | 2558 | /* arm->vfp */ |
2447 | - gen_movl_T0_reg(s, rd); | |
2559 | + tmp = load_reg(s, rd); | |
2448 | 2560 | if (insn & (1 << 21)) { |
2449 | 2561 | rn >>= 1; |
2450 | 2562 | /* system register */ |
... | ... | @@ -2455,24 +2567,25 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2455 | 2567 | /* Writes are ignored. */ |
2456 | 2568 | break; |
2457 | 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 | 2572 | gen_lookup_tb(s); |
2460 | 2573 | break; |
2461 | 2574 | case ARM_VFP_FPEXC: |
2462 | 2575 | if (IS_USER(s)) |
2463 | 2576 | return 1; |
2464 | - gen_op_vfp_movl_xreg_T0(rn); | |
2577 | + store_cpu_field(tmp, vfp.xregs[rn]); | |
2465 | 2578 | gen_lookup_tb(s); |
2466 | 2579 | break; |
2467 | 2580 | case ARM_VFP_FPINST: |
2468 | 2581 | case ARM_VFP_FPINST2: |
2469 | - gen_op_vfp_movl_xreg_T0(rn); | |
2582 | + store_cpu_field(tmp, vfp.xregs[rn]); | |
2470 | 2583 | break; |
2471 | 2584 | default: |
2472 | 2585 | return 1; |
2473 | 2586 | } |
2474 | 2587 | } else { |
2475 | - gen_op_vfp_msr(); | |
2588 | + gen_vfp_msr(tmp); | |
2476 | 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 | 2753 | else |
2641 | 2754 | i |= 0x4000; |
2642 | 2755 | n |= i << 16; |
2756 | + tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32); | |
2643 | 2757 | } else { |
2644 | 2758 | if (i & 0x40) |
2645 | 2759 | i |= 0x780; |
2646 | 2760 | else |
2647 | 2761 | i |= 0x800; |
2648 | 2762 | n |= i << 19; |
2763 | + tcg_gen_movi_i32(cpu_F0d, ((uint64_t)n) << 32); | |
2649 | 2764 | } |
2650 | - gen_vfp_fconst(dp, n); | |
2651 | 2765 | break; |
2652 | 2766 | case 15: /* extension space */ |
2653 | 2767 | switch (rn) { |
... | ... | @@ -2678,9 +2792,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2678 | 2792 | break; |
2679 | 2793 | case 15: /* single<->double conversion */ |
2680 | 2794 | if (dp) |
2681 | - gen_op_vfp_fcvtsd(); | |
2795 | + gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env); | |
2682 | 2796 | else |
2683 | - gen_op_vfp_fcvtds(); | |
2797 | + gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env); | |
2684 | 2798 | break; |
2685 | 2799 | case 16: /* fuito */ |
2686 | 2800 | gen_vfp_uito(dp); |
... | ... | @@ -2814,31 +2928,35 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) |
2814 | 2928 | if (insn & ARM_CP_RW_BIT) { |
2815 | 2929 | /* vfp->arm */ |
2816 | 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 | 2937 | } else { |
2822 | 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 | 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 | 2945 | } else { |
2830 | 2946 | /* arm->vfp */ |
2831 | 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 | 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 | 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 | 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 | 4111 | break; |
3994 | 4112 | case 31: |
3995 | 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 | 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 | 4117 | break; |
4000 | 4118 | default: |
4001 | 4119 | abort(); |
... | ... | @@ -4242,19 +4360,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
4242 | 4360 | } else if (op == 15 || op == 16) { |
4243 | 4361 | /* VCVT fixed-point. */ |
4244 | 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 | 4364 | if (op & 1) { |
4247 | 4365 | if (u) |
4248 | - gen_op_vfp_ultos(shift); | |
4366 | + gen_vfp_ulto(0, shift); | |
4249 | 4367 | else |
4250 | - gen_op_vfp_sltos(shift); | |
4368 | + gen_vfp_slto(0, shift); | |
4251 | 4369 | } else { |
4252 | 4370 | if (u) |
4253 | - gen_op_vfp_touls(shift); | |
4371 | + gen_vfp_toul(0, shift); | |
4254 | 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 | 4377 | } else { |
4260 | 4378 | return 1; |
... | ... | @@ -4898,7 +5016,8 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
4898 | 5016 | elementwise: |
4899 | 5017 | for (pass = 0; pass < (q ? 4 : 2); pass++) { |
4900 | 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 | 5021 | } else { |
4903 | 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 | 5160 | gen_op_neon_ceq_f32(); |
5042 | 5161 | break; |
5043 | 5162 | case 30: /* Float VABS */ |
5044 | - gen_op_vfp_abss(); | |
5163 | + gen_vfp_abs(0); | |
5045 | 5164 | break; |
5046 | 5165 | case 31: /* Float VNEG */ |
5047 | - gen_op_vfp_negs(); | |
5166 | + gen_vfp_neg(0); | |
5048 | 5167 | break; |
5049 | 5168 | case 32: /* VSWP */ |
5050 | 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 | 5180 | NEON_SET_REG(T1, rm, pass); |
5062 | 5181 | break; |
5063 | 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 | 5184 | break; |
5066 | 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 | 5187 | break; |
5069 | 5188 | case 58: /* Float VRECPE */ |
5070 | - gen_op_neon_recpe_f32(); | |
5189 | + gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env); | |
5071 | 5190 | break; |
5072 | 5191 | case 59: /* Float VRSQRTE */ |
5073 | - gen_op_neon_rsqrte_f32(); | |
5192 | + gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env); | |
5074 | 5193 | break; |
5075 | 5194 | case 60: /* VCVT.F32.S32 */ |
5076 | - gen_op_vfp_tosizs(); | |
5195 | + gen_vfp_tosiz(0); | |
5077 | 5196 | break; |
5078 | 5197 | case 61: /* VCVT.F32.U32 */ |
5079 | - gen_op_vfp_touizs(); | |
5198 | + gen_vfp_touiz(0); | |
5080 | 5199 | break; |
5081 | 5200 | case 62: /* VCVT.S32.F32 */ |
5082 | - gen_op_vfp_sitos(); | |
5201 | + gen_vfp_sito(0); | |
5083 | 5202 | break; |
5084 | 5203 | case 63: /* VCVT.U32.F32 */ |
5085 | - gen_op_vfp_uitos(); | |
5204 | + gen_vfp_uito(0); | |
5086 | 5205 | break; |
5087 | 5206 | default: |
5088 | 5207 | /* Reserved: 21, 29, 39-56 */ |
5089 | 5208 | return 1; |
5090 | 5209 | } |
5091 | 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 | 5213 | } else { |
5094 | 5214 | NEON_SET_REG(T0, rd, pass); |
5095 | 5215 | } |
... | ... | @@ -8062,6 +8182,10 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
8062 | 8182 | dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR; |
8063 | 8183 | } |
8064 | 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 | 8189 | next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; |
8066 | 8190 | lj = -1; |
8067 | 8191 | /* Reset the conditional execution bits immediately. This avoids | ... | ... |