Commit ee5bbe38b1193bb2a8c2a450acb3d4679663fba1
1 parent
e37e863f
correct split between helper.c and op_helper.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1506 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
201 additions
and
186 deletions
target-sparc/exec.h
| ... | ... | @@ -72,8 +72,8 @@ void do_ldd_raw(target_ulong addr); |
| 72 | 72 | void do_interrupt(int intno); |
| 73 | 73 | void raise_exception(int tt); |
| 74 | 74 | void memcpy32(target_ulong *dst, const target_ulong *src); |
| 75 | -target_ulong mmu_probe(target_ulong address, int mmulev); | |
| 76 | -void dump_mmu(void); | |
| 75 | +target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev); | |
| 76 | +void dump_mmu(CPUState *env); | |
| 77 | 77 | void helper_debug(); |
| 78 | 78 | void do_wrpsr(); |
| 79 | 79 | void do_rdpsr(); | ... | ... |
target-sparc/helper.c
| ... | ... | @@ -17,7 +17,16 @@ |
| 17 | 17 | * License along with this library; if not, write to the Free Software |
| 18 | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | 19 | */ |
| 20 | -#include "exec.h" | |
| 20 | +#include <stdarg.h> | |
| 21 | +#include <stdlib.h> | |
| 22 | +#include <stdio.h> | |
| 23 | +#include <string.h> | |
| 24 | +#include <inttypes.h> | |
| 25 | +#include <signal.h> | |
| 26 | +#include <assert.h> | |
| 27 | + | |
| 28 | +#include "cpu.h" | |
| 29 | +#include "exec-all.h" | |
| 21 | 30 | |
| 22 | 31 | //#define DEBUG_PCALL |
| 23 | 32 | //#define DEBUG_MMU |
| ... | ... | @@ -52,55 +61,6 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, |
| 52 | 61 | |
| 53 | 62 | #else |
| 54 | 63 | |
| 55 | -#define MMUSUFFIX _mmu | |
| 56 | -#define GETPC() (__builtin_return_address(0)) | |
| 57 | - | |
| 58 | -#define SHIFT 0 | |
| 59 | -#include "softmmu_template.h" | |
| 60 | - | |
| 61 | -#define SHIFT 1 | |
| 62 | -#include "softmmu_template.h" | |
| 63 | - | |
| 64 | -#define SHIFT 2 | |
| 65 | -#include "softmmu_template.h" | |
| 66 | - | |
| 67 | -#define SHIFT 3 | |
| 68 | -#include "softmmu_template.h" | |
| 69 | - | |
| 70 | - | |
| 71 | -/* try to fill the TLB and return an exception if error. If retaddr is | |
| 72 | - NULL, it means that the function was called in C code (i.e. not | |
| 73 | - from generated code or from helper.c) */ | |
| 74 | -/* XXX: fix it to restore all registers */ | |
| 75 | -void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) | |
| 76 | -{ | |
| 77 | - TranslationBlock *tb; | |
| 78 | - int ret; | |
| 79 | - unsigned long pc; | |
| 80 | - CPUState *saved_env; | |
| 81 | - | |
| 82 | - /* XXX: hack to restore env in all cases, even if not called from | |
| 83 | - generated code */ | |
| 84 | - saved_env = env; | |
| 85 | - env = cpu_single_env; | |
| 86 | - | |
| 87 | - ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1); | |
| 88 | - if (ret) { | |
| 89 | - if (retaddr) { | |
| 90 | - /* now we have a real cpu fault */ | |
| 91 | - pc = (unsigned long)retaddr; | |
| 92 | - tb = tb_find_pc(pc); | |
| 93 | - if (tb) { | |
| 94 | - /* the PC is inside the translated code. It means that we have | |
| 95 | - a virtual CPU fault */ | |
| 96 | - cpu_restore_state(tb, env, pc, (void *)T2); | |
| 97 | - } | |
| 98 | - } | |
| 99 | - cpu_loop_exit(); | |
| 100 | - } | |
| 101 | - env = saved_env; | |
| 102 | -} | |
| 103 | - | |
| 104 | 64 | #ifndef TARGET_SPARC64 |
| 105 | 65 | static const int access_table[8][8] = { |
| 106 | 66 | { 0, 0, 0, 0, 2, 0, 3, 3 }, |
| ... | ... | @@ -412,131 +372,8 @@ void memcpy32(target_ulong *dst, const target_ulong *src) |
| 412 | 372 | dst[7] = src[7]; |
| 413 | 373 | } |
| 414 | 374 | |
| 415 | -void set_cwp(int new_cwp) | |
| 416 | -{ | |
| 417 | - /* put the modified wrap registers at their proper location */ | |
| 418 | - if (env->cwp == (NWINDOWS - 1)) | |
| 419 | - memcpy32(env->regbase, env->regbase + NWINDOWS * 16); | |
| 420 | - env->cwp = new_cwp; | |
| 421 | - /* put the wrap registers at their temporary location */ | |
| 422 | - if (new_cwp == (NWINDOWS - 1)) | |
| 423 | - memcpy32(env->regbase + NWINDOWS * 16, env->regbase); | |
| 424 | - env->regwptr = env->regbase + (new_cwp * 16); | |
| 425 | - REGWPTR = env->regwptr; | |
| 426 | -} | |
| 427 | - | |
| 428 | -void cpu_set_cwp(CPUState *env1, int new_cwp) | |
| 429 | -{ | |
| 430 | - CPUState *saved_env; | |
| 431 | -#ifdef reg_REGWPTR | |
| 432 | - target_ulong *saved_regwptr; | |
| 433 | -#endif | |
| 434 | - | |
| 435 | - saved_env = env; | |
| 436 | -#ifdef reg_REGWPTR | |
| 437 | - saved_regwptr = REGWPTR; | |
| 438 | -#endif | |
| 439 | - env = env1; | |
| 440 | - set_cwp(new_cwp); | |
| 441 | - env = saved_env; | |
| 442 | -#ifdef reg_REGWPTR | |
| 443 | - REGWPTR = saved_regwptr; | |
| 444 | -#endif | |
| 445 | -} | |
| 446 | - | |
| 447 | -#ifdef TARGET_SPARC64 | |
| 448 | -void do_interrupt(int intno) | |
| 449 | -{ | |
| 450 | -#ifdef DEBUG_PCALL | |
| 451 | - if (loglevel & CPU_LOG_INT) { | |
| 452 | - static int count; | |
| 453 | - fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", | |
| 454 | - count, intno, | |
| 455 | - env->pc, | |
| 456 | - env->npc, env->regwptr[6]); | |
| 457 | - cpu_dump_state(env, logfile, fprintf, 0); | |
| 458 | -#if 0 | |
| 459 | - { | |
| 460 | - int i; | |
| 461 | - uint8_t *ptr; | |
| 462 | - | |
| 463 | - fprintf(logfile, " code="); | |
| 464 | - ptr = (uint8_t *)env->pc; | |
| 465 | - for(i = 0; i < 16; i++) { | |
| 466 | - fprintf(logfile, " %02x", ldub(ptr + i)); | |
| 467 | - } | |
| 468 | - fprintf(logfile, "\n"); | |
| 469 | - } | |
| 470 | -#endif | |
| 471 | - count++; | |
| 472 | - } | |
| 473 | -#endif | |
| 474 | -#if !defined(CONFIG_USER_ONLY) | |
| 475 | - if (env->pstate & PS_IE) { | |
| 476 | - cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); | |
| 477 | - return; | |
| 478 | - } | |
| 479 | -#endif | |
| 480 | - env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | | |
| 481 | - ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff); | |
| 482 | - env->tpc[env->tl] = env->pc; | |
| 483 | - env->tnpc[env->tl] = env->npc; | |
| 484 | - env->tt[env->tl] = intno; | |
| 485 | - env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4); | |
| 486 | - env->tl++; | |
| 487 | - env->pc = env->tbr; | |
| 488 | - env->npc = env->pc + 4; | |
| 489 | - env->exception_index = 0; | |
| 490 | -} | |
| 491 | -#else | |
| 492 | -void do_interrupt(int intno) | |
| 493 | -{ | |
| 494 | - int cwp; | |
| 495 | - | |
| 496 | -#ifdef DEBUG_PCALL | |
| 497 | - if (loglevel & CPU_LOG_INT) { | |
| 498 | - static int count; | |
| 499 | - fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", | |
| 500 | - count, intno, | |
| 501 | - env->pc, | |
| 502 | - env->npc, env->regwptr[6]); | |
| 503 | - cpu_dump_state(env, logfile, fprintf, 0); | |
| 504 | -#if 0 | |
| 505 | - { | |
| 506 | - int i; | |
| 507 | - uint8_t *ptr; | |
| 508 | - | |
| 509 | - fprintf(logfile, " code="); | |
| 510 | - ptr = (uint8_t *)env->pc; | |
| 511 | - for(i = 0; i < 16; i++) { | |
| 512 | - fprintf(logfile, " %02x", ldub(ptr + i)); | |
| 513 | - } | |
| 514 | - fprintf(logfile, "\n"); | |
| 515 | - } | |
| 516 | -#endif | |
| 517 | - count++; | |
| 518 | - } | |
| 519 | -#endif | |
| 520 | -#if !defined(CONFIG_USER_ONLY) | |
| 521 | - if (env->psret == 0) { | |
| 522 | - cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); | |
| 523 | - return; | |
| 524 | - } | |
| 525 | -#endif | |
| 526 | - env->psret = 0; | |
| 527 | - cwp = (env->cwp - 1) & (NWINDOWS - 1); | |
| 528 | - set_cwp(cwp); | |
| 529 | - env->regwptr[9] = env->pc; | |
| 530 | - env->regwptr[10] = env->npc; | |
| 531 | - env->psrps = env->psrs; | |
| 532 | - env->psrs = 1; | |
| 533 | - env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); | |
| 534 | - env->pc = env->tbr; | |
| 535 | - env->npc = env->pc + 4; | |
| 536 | - env->exception_index = 0; | |
| 537 | -} | |
| 538 | - | |
| 539 | -target_ulong mmu_probe(target_ulong address, int mmulev) | |
| 375 | +#if !defined(TARGET_SPARC64) | |
| 376 | +target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev) | |
| 540 | 377 | { |
| 541 | 378 | target_phys_addr_t pde_ptr; |
| 542 | 379 | uint32_t pde; |
| ... | ... | @@ -599,7 +436,7 @@ target_ulong mmu_probe(target_ulong address, int mmulev) |
| 599 | 436 | } |
| 600 | 437 | |
| 601 | 438 | #ifdef DEBUG_MMU |
| 602 | -void dump_mmu(void) | |
| 439 | +void dump_mmu(CPUState *env) | |
| 603 | 440 | { |
| 604 | 441 | target_ulong va, va1, va2; |
| 605 | 442 | unsigned int n, m, o; |
| ... | ... | @@ -611,17 +448,17 @@ void dump_mmu(void) |
| 611 | 448 | pde = ldl_phys(pde_ptr); |
| 612 | 449 | printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]); |
| 613 | 450 | for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) { |
| 614 | - pde_ptr = mmu_probe(va, 2); | |
| 451 | + pde_ptr = mmu_probe(env, va, 2); | |
| 615 | 452 | if (pde_ptr) { |
| 616 | 453 | pa = cpu_get_phys_page_debug(env, va); |
| 617 | 454 | printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr); |
| 618 | 455 | for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) { |
| 619 | - pde_ptr = mmu_probe(va1, 1); | |
| 456 | + pde_ptr = mmu_probe(env, va1, 1); | |
| 620 | 457 | if (pde_ptr) { |
| 621 | 458 | pa = cpu_get_phys_page_debug(env, va1); |
| 622 | 459 | printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr); |
| 623 | 460 | for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) { |
| 624 | - pde_ptr = mmu_probe(va2, 0); | |
| 461 | + pde_ptr = mmu_probe(env, va2, 0); | |
| 625 | 462 | if (pde_ptr) { |
| 626 | 463 | pa = cpu_get_phys_page_debug(env, va2); |
| 627 | 464 | printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr); | ... | ... |
target-sparc/op_helper.c
| ... | ... | @@ -234,7 +234,7 @@ void helper_ld_asi(int asi, int size, int sign) |
| 234 | 234 | if (mmulev > 4) |
| 235 | 235 | ret = 0; |
| 236 | 236 | else { |
| 237 | - ret = mmu_probe(T0, mmulev); | |
| 237 | + ret = mmu_probe(env, T0, mmulev); | |
| 238 | 238 | //bswap32s(&ret); |
| 239 | 239 | } |
| 240 | 240 | #ifdef DEBUG_MMU |
| ... | ... | @@ -293,7 +293,7 @@ void helper_st_asi(int asi, int size, int sign) |
| 293 | 293 | break; |
| 294 | 294 | } |
| 295 | 295 | #ifdef DEBUG_MMU |
| 296 | - dump_mmu(); | |
| 296 | + dump_mmu(env); | |
| 297 | 297 | #endif |
| 298 | 298 | return; |
| 299 | 299 | } |
| ... | ... | @@ -330,7 +330,7 @@ void helper_st_asi(int asi, int size, int sign) |
| 330 | 330 | if (oldreg != env->mmuregs[reg]) { |
| 331 | 331 | printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); |
| 332 | 332 | } |
| 333 | - dump_mmu(); | |
| 333 | + dump_mmu(env); | |
| 334 | 334 | #endif |
| 335 | 335 | return; |
| 336 | 336 | } |
| ... | ... | @@ -508,7 +508,7 @@ void helper_st_asi(int asi, int size, int sign) |
| 508 | 508 | if (oldreg != env->immuregs[reg]) { |
| 509 | 509 | printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]); |
| 510 | 510 | } |
| 511 | - dump_mmu(); | |
| 511 | + dump_mmu(env); | |
| 512 | 512 | #endif |
| 513 | 513 | return; |
| 514 | 514 | } |
| ... | ... | @@ -576,7 +576,7 @@ void helper_st_asi(int asi, int size, int sign) |
| 576 | 576 | if (oldreg != env->dmmuregs[reg]) { |
| 577 | 577 | printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]); |
| 578 | 578 | } |
| 579 | - dump_mmu(); | |
| 579 | + dump_mmu(env); | |
| 580 | 580 | #endif |
| 581 | 581 | return; |
| 582 | 582 | } |
| ... | ... | @@ -705,3 +705,181 @@ void do_popc() |
| 705 | 705 | T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL); |
| 706 | 706 | } |
| 707 | 707 | #endif |
| 708 | + | |
| 709 | +void set_cwp(int new_cwp) | |
| 710 | +{ | |
| 711 | + /* put the modified wrap registers at their proper location */ | |
| 712 | + if (env->cwp == (NWINDOWS - 1)) | |
| 713 | + memcpy32(env->regbase, env->regbase + NWINDOWS * 16); | |
| 714 | + env->cwp = new_cwp; | |
| 715 | + /* put the wrap registers at their temporary location */ | |
| 716 | + if (new_cwp == (NWINDOWS - 1)) | |
| 717 | + memcpy32(env->regbase + NWINDOWS * 16, env->regbase); | |
| 718 | + env->regwptr = env->regbase + (new_cwp * 16); | |
| 719 | + REGWPTR = env->regwptr; | |
| 720 | +} | |
| 721 | + | |
| 722 | +void cpu_set_cwp(CPUState *env1, int new_cwp) | |
| 723 | +{ | |
| 724 | + CPUState *saved_env; | |
| 725 | +#ifdef reg_REGWPTR | |
| 726 | + target_ulong *saved_regwptr; | |
| 727 | +#endif | |
| 728 | + | |
| 729 | + saved_env = env; | |
| 730 | +#ifdef reg_REGWPTR | |
| 731 | + saved_regwptr = REGWPTR; | |
| 732 | +#endif | |
| 733 | + env = env1; | |
| 734 | + set_cwp(new_cwp); | |
| 735 | + env = saved_env; | |
| 736 | +#ifdef reg_REGWPTR | |
| 737 | + REGWPTR = saved_regwptr; | |
| 738 | +#endif | |
| 739 | +} | |
| 740 | + | |
| 741 | +#ifdef TARGET_SPARC64 | |
| 742 | +void do_interrupt(int intno) | |
| 743 | +{ | |
| 744 | +#ifdef DEBUG_PCALL | |
| 745 | + if (loglevel & CPU_LOG_INT) { | |
| 746 | + static int count; | |
| 747 | + fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", | |
| 748 | + count, intno, | |
| 749 | + env->pc, | |
| 750 | + env->npc, env->regwptr[6]); | |
| 751 | + cpu_dump_state(env, logfile, fprintf, 0); | |
| 752 | +#if 0 | |
| 753 | + { | |
| 754 | + int i; | |
| 755 | + uint8_t *ptr; | |
| 756 | + | |
| 757 | + fprintf(logfile, " code="); | |
| 758 | + ptr = (uint8_t *)env->pc; | |
| 759 | + for(i = 0; i < 16; i++) { | |
| 760 | + fprintf(logfile, " %02x", ldub(ptr + i)); | |
| 761 | + } | |
| 762 | + fprintf(logfile, "\n"); | |
| 763 | + } | |
| 764 | +#endif | |
| 765 | + count++; | |
| 766 | + } | |
| 767 | +#endif | |
| 768 | +#if !defined(CONFIG_USER_ONLY) | |
| 769 | + if (env->pstate & PS_IE) { | |
| 770 | + cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); | |
| 771 | + return; | |
| 772 | + } | |
| 773 | +#endif | |
| 774 | + env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | | |
| 775 | + ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff); | |
| 776 | + env->tpc[env->tl] = env->pc; | |
| 777 | + env->tnpc[env->tl] = env->npc; | |
| 778 | + env->tt[env->tl] = intno; | |
| 779 | + env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4); | |
| 780 | + env->tl++; | |
| 781 | + env->pc = env->tbr; | |
| 782 | + env->npc = env->pc + 4; | |
| 783 | + env->exception_index = 0; | |
| 784 | +} | |
| 785 | +#else | |
| 786 | +void do_interrupt(int intno) | |
| 787 | +{ | |
| 788 | + int cwp; | |
| 789 | + | |
| 790 | +#ifdef DEBUG_PCALL | |
| 791 | + if (loglevel & CPU_LOG_INT) { | |
| 792 | + static int count; | |
| 793 | + fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", | |
| 794 | + count, intno, | |
| 795 | + env->pc, | |
| 796 | + env->npc, env->regwptr[6]); | |
| 797 | + cpu_dump_state(env, logfile, fprintf, 0); | |
| 798 | +#if 0 | |
| 799 | + { | |
| 800 | + int i; | |
| 801 | + uint8_t *ptr; | |
| 802 | + | |
| 803 | + fprintf(logfile, " code="); | |
| 804 | + ptr = (uint8_t *)env->pc; | |
| 805 | + for(i = 0; i < 16; i++) { | |
| 806 | + fprintf(logfile, " %02x", ldub(ptr + i)); | |
| 807 | + } | |
| 808 | + fprintf(logfile, "\n"); | |
| 809 | + } | |
| 810 | +#endif | |
| 811 | + count++; | |
| 812 | + } | |
| 813 | +#endif | |
| 814 | +#if !defined(CONFIG_USER_ONLY) | |
| 815 | + if (env->psret == 0) { | |
| 816 | + cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); | |
| 817 | + return; | |
| 818 | + } | |
| 819 | +#endif | |
| 820 | + env->psret = 0; | |
| 821 | + cwp = (env->cwp - 1) & (NWINDOWS - 1); | |
| 822 | + set_cwp(cwp); | |
| 823 | + env->regwptr[9] = env->pc; | |
| 824 | + env->regwptr[10] = env->npc; | |
| 825 | + env->psrps = env->psrs; | |
| 826 | + env->psrs = 1; | |
| 827 | + env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); | |
| 828 | + env->pc = env->tbr; | |
| 829 | + env->npc = env->pc + 4; | |
| 830 | + env->exception_index = 0; | |
| 831 | +} | |
| 832 | +#endif | |
| 833 | + | |
| 834 | +#if !defined(CONFIG_USER_ONLY) | |
| 835 | + | |
| 836 | +#define MMUSUFFIX _mmu | |
| 837 | +#define GETPC() (__builtin_return_address(0)) | |
| 838 | + | |
| 839 | +#define SHIFT 0 | |
| 840 | +#include "softmmu_template.h" | |
| 841 | + | |
| 842 | +#define SHIFT 1 | |
| 843 | +#include "softmmu_template.h" | |
| 844 | + | |
| 845 | +#define SHIFT 2 | |
| 846 | +#include "softmmu_template.h" | |
| 847 | + | |
| 848 | +#define SHIFT 3 | |
| 849 | +#include "softmmu_template.h" | |
| 850 | + | |
| 851 | + | |
| 852 | +/* try to fill the TLB and return an exception if error. If retaddr is | |
| 853 | + NULL, it means that the function was called in C code (i.e. not | |
| 854 | + from generated code or from helper.c) */ | |
| 855 | +/* XXX: fix it to restore all registers */ | |
| 856 | +void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) | |
| 857 | +{ | |
| 858 | + TranslationBlock *tb; | |
| 859 | + int ret; | |
| 860 | + unsigned long pc; | |
| 861 | + CPUState *saved_env; | |
| 862 | + | |
| 863 | + /* XXX: hack to restore env in all cases, even if not called from | |
| 864 | + generated code */ | |
| 865 | + saved_env = env; | |
| 866 | + env = cpu_single_env; | |
| 867 | + | |
| 868 | + ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1); | |
| 869 | + if (ret) { | |
| 870 | + if (retaddr) { | |
| 871 | + /* now we have a real cpu fault */ | |
| 872 | + pc = (unsigned long)retaddr; | |
| 873 | + tb = tb_find_pc(pc); | |
| 874 | + if (tb) { | |
| 875 | + /* the PC is inside the translated code. It means that we have | |
| 876 | + a virtual CPU fault */ | |
| 877 | + cpu_restore_state(tb, env, pc, (void *)T2); | |
| 878 | + } | |
| 879 | + } | |
| 880 | + cpu_loop_exit(); | |
| 881 | + } | |
| 882 | + env = saved_env; | |
| 883 | +} | |
| 884 | + | |
| 885 | +#endif | ... | ... |