Commit d4218d996d2274f4136b8bd22e946bf56f050c9e
1 parent
fcc72045
Fix Sparc lda/ldda/sta/stda asi handling, fault on misaligned register ldd/std a…
…nd illegal cwp on wrpsr (Aurelien Jarno) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2568 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
40 additions
and
2 deletions
target-sparc/cpu.h
| ... | ... | @@ -269,7 +269,7 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); |
| 269 | 269 | env->psrs = (_tmp & PSR_S)? 1 : 0; \ |
| 270 | 270 | env->psrps = (_tmp & PSR_PS)? 1 : 0; \ |
| 271 | 271 | env->psret = (_tmp & PSR_ET)? 1 : 0; \ |
| 272 | - cpu_set_cwp(env, _tmp & PSR_CWP & (NWINDOWS - 1)); \ | |
| 272 | + cpu_set_cwp(env, _tmp & PSR_CWP); \ | |
| 273 | 273 | } while (0) |
| 274 | 274 | |
| 275 | 275 | #ifdef TARGET_SPARC64 | ... | ... |
target-sparc/op_helper.c
| ... | ... | @@ -615,6 +615,9 @@ void helper_rett() |
| 615 | 615 | { |
| 616 | 616 | unsigned int cwp; |
| 617 | 617 | |
| 618 | + if (env->psret == 1) | |
| 619 | + raise_exception(TT_ILL_INSN); | |
| 620 | + | |
| 618 | 621 | env->psret = 1; |
| 619 | 622 | cwp = (env->cwp + 1) & (NWINDOWS - 1); |
| 620 | 623 | if (env->wim & (1 << cwp)) { |
| ... | ... | @@ -655,7 +658,10 @@ void helper_debug() |
| 655 | 658 | #ifndef TARGET_SPARC64 |
| 656 | 659 | void do_wrpsr() |
| 657 | 660 | { |
| 658 | - PUT_PSR(env, T0); | |
| 661 | + if ((T0 & PSR_CWP) >= NWINDOWS) | |
| 662 | + raise_exception(TT_ILL_INSN); | |
| 663 | + else | |
| 664 | + PUT_PSR(env, T0); | |
| 659 | 665 | } |
| 660 | 666 | |
| 661 | 667 | void do_rdpsr() | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -2341,6 +2341,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2341 | 2341 | gen_op_ldst(lduh); |
| 2342 | 2342 | break; |
| 2343 | 2343 | case 0x3: /* load double word */ |
| 2344 | + if (rd & 1) | |
| 2345 | + goto illegal_insn; | |
| 2344 | 2346 | gen_op_ldst(ldd); |
| 2345 | 2347 | gen_movl_T0_reg(rd + 1); |
| 2346 | 2348 | break; |
| ... | ... | @@ -2360,6 +2362,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2360 | 2362 | #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) |
| 2361 | 2363 | case 0x10: /* load word alternate */ |
| 2362 | 2364 | #ifndef TARGET_SPARC64 |
| 2365 | + if (IS_IMM) | |
| 2366 | + goto illegal_insn; | |
| 2363 | 2367 | if (!supervisor(dc)) |
| 2364 | 2368 | goto priv_insn; |
| 2365 | 2369 | #endif |
| ... | ... | @@ -2367,6 +2371,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2367 | 2371 | break; |
| 2368 | 2372 | case 0x11: /* load unsigned byte alternate */ |
| 2369 | 2373 | #ifndef TARGET_SPARC64 |
| 2374 | + if (IS_IMM) | |
| 2375 | + goto illegal_insn; | |
| 2370 | 2376 | if (!supervisor(dc)) |
| 2371 | 2377 | goto priv_insn; |
| 2372 | 2378 | #endif |
| ... | ... | @@ -2374,6 +2380,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2374 | 2380 | break; |
| 2375 | 2381 | case 0x12: /* load unsigned halfword alternate */ |
| 2376 | 2382 | #ifndef TARGET_SPARC64 |
| 2383 | + if (IS_IMM) | |
| 2384 | + goto illegal_insn; | |
| 2377 | 2385 | if (!supervisor(dc)) |
| 2378 | 2386 | goto priv_insn; |
| 2379 | 2387 | #endif |
| ... | ... | @@ -2381,14 +2389,20 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2381 | 2389 | break; |
| 2382 | 2390 | case 0x13: /* load double word alternate */ |
| 2383 | 2391 | #ifndef TARGET_SPARC64 |
| 2392 | + if (IS_IMM) | |
| 2393 | + goto illegal_insn; | |
| 2384 | 2394 | if (!supervisor(dc)) |
| 2385 | 2395 | goto priv_insn; |
| 2386 | 2396 | #endif |
| 2397 | + if (rd & 1) | |
| 2398 | + goto illegal_insn; | |
| 2387 | 2399 | gen_op_ldda(insn, 1, 8, 0); |
| 2388 | 2400 | gen_movl_T0_reg(rd + 1); |
| 2389 | 2401 | break; |
| 2390 | 2402 | case 0x19: /* load signed byte alternate */ |
| 2391 | 2403 | #ifndef TARGET_SPARC64 |
| 2404 | + if (IS_IMM) | |
| 2405 | + goto illegal_insn; | |
| 2392 | 2406 | if (!supervisor(dc)) |
| 2393 | 2407 | goto priv_insn; |
| 2394 | 2408 | #endif |
| ... | ... | @@ -2396,6 +2410,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2396 | 2410 | break; |
| 2397 | 2411 | case 0x1a: /* load signed halfword alternate */ |
| 2398 | 2412 | #ifndef TARGET_SPARC64 |
| 2413 | + if (IS_IMM) | |
| 2414 | + goto illegal_insn; | |
| 2399 | 2415 | if (!supervisor(dc)) |
| 2400 | 2416 | goto priv_insn; |
| 2401 | 2417 | #endif |
| ... | ... | @@ -2403,6 +2419,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2403 | 2419 | break; |
| 2404 | 2420 | case 0x1d: /* ldstuba -- XXX: should be atomically */ |
| 2405 | 2421 | #ifndef TARGET_SPARC64 |
| 2422 | + if (IS_IMM) | |
| 2423 | + goto illegal_insn; | |
| 2406 | 2424 | if (!supervisor(dc)) |
| 2407 | 2425 | goto priv_insn; |
| 2408 | 2426 | #endif |
| ... | ... | @@ -2410,6 +2428,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2410 | 2428 | break; |
| 2411 | 2429 | case 0x1f: /* swap reg with alt. memory. Also atomically */ |
| 2412 | 2430 | #ifndef TARGET_SPARC64 |
| 2431 | + if (IS_IMM) | |
| 2432 | + goto illegal_insn; | |
| 2413 | 2433 | if (!supervisor(dc)) |
| 2414 | 2434 | goto priv_insn; |
| 2415 | 2435 | #endif |
| ... | ... | @@ -2508,6 +2528,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2508 | 2528 | gen_op_ldst(sth); |
| 2509 | 2529 | break; |
| 2510 | 2530 | case 0x7: |
| 2531 | + if (rd & 1) | |
| 2532 | + goto illegal_insn; | |
| 2511 | 2533 | flush_T2(dc); |
| 2512 | 2534 | gen_movl_reg_T2(rd + 1); |
| 2513 | 2535 | gen_op_ldst(std); |
| ... | ... | @@ -2515,6 +2537,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2515 | 2537 | #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) |
| 2516 | 2538 | case 0x14: |
| 2517 | 2539 | #ifndef TARGET_SPARC64 |
| 2540 | + if (IS_IMM) | |
| 2541 | + goto illegal_insn; | |
| 2518 | 2542 | if (!supervisor(dc)) |
| 2519 | 2543 | goto priv_insn; |
| 2520 | 2544 | #endif |
| ... | ... | @@ -2522,6 +2546,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2522 | 2546 | break; |
| 2523 | 2547 | case 0x15: |
| 2524 | 2548 | #ifndef TARGET_SPARC64 |
| 2549 | + if (IS_IMM) | |
| 2550 | + goto illegal_insn; | |
| 2525 | 2551 | if (!supervisor(dc)) |
| 2526 | 2552 | goto priv_insn; |
| 2527 | 2553 | #endif |
| ... | ... | @@ -2529,6 +2555,8 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2529 | 2555 | break; |
| 2530 | 2556 | case 0x16: |
| 2531 | 2557 | #ifndef TARGET_SPARC64 |
| 2558 | + if (IS_IMM) | |
| 2559 | + goto illegal_insn; | |
| 2532 | 2560 | if (!supervisor(dc)) |
| 2533 | 2561 | goto priv_insn; |
| 2534 | 2562 | #endif |
| ... | ... | @@ -2536,9 +2564,13 @@ static void disas_sparc_insn(DisasContext * dc) |
| 2536 | 2564 | break; |
| 2537 | 2565 | case 0x17: |
| 2538 | 2566 | #ifndef TARGET_SPARC64 |
| 2567 | + if (IS_IMM) | |
| 2568 | + goto illegal_insn; | |
| 2539 | 2569 | if (!supervisor(dc)) |
| 2540 | 2570 | goto priv_insn; |
| 2541 | 2571 | #endif |
| 2572 | + if (rd & 1) | |
| 2573 | + goto illegal_insn; | |
| 2542 | 2574 | flush_T2(dc); |
| 2543 | 2575 | gen_movl_reg_T2(rd + 1); |
| 2544 | 2576 | gen_op_stda(insn, 0, 8, 0); | ... | ... |