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