int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 

                             int is_write, int is_user, int is_softmmu)

{

    uint8_t *pde_ptr, *pte_ptr;

    uint32_t pde, pte, virt_addr, ptep;

    int error_code, is_dirty, prot, page_size, ret;

    unsigned long paddr, vaddr, page_offset;

    

#if defined(DEBUG_MMU)

    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 

           addr, is_write, is_user, env->eip);

#endif



    if (env->user_mode_only) {

        /* user mode only emulation */

        error_code = 0;

        goto do_fault;

    }



    if (!(env->cr[0] & CR0_PG_MASK)) {

        pte = addr;

        virt_addr = addr & TARGET_PAGE_MASK;

        prot = PROT_READ | PROT_WRITE;

        page_size = 4096;

        goto do_mapping;

    }



    /* page directory entry */

    pde_ptr = phys_ram_base + 

        (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask);

    pde = ldl_raw(pde_ptr);

    if (!(pde & PG_PRESENT_MASK)) {

        error_code = 0;

        goto do_fault;

    }

    /* if PSE bit is set, then we use a 4MB page */

    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {

        if (is_user) {

            if (!(pde & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(pde & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&

                is_write && !(pde & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pde & PG_DIRTY_MASK);

        if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

            pde |= PG_ACCESSED_MASK;

            if (is_dirty)

                pde |= PG_DIRTY_MASK;

            stl_raw(pde_ptr, pde);

        }

        

        pte = pde & ~0x003ff000; /* align to 4MB */

        ptep = pte;

        page_size = 4096 * 1024;

        virt_addr = addr & ~0x003fffff;

    } else {

        if (!(pde & PG_ACCESSED_MASK)) {

            pde |= PG_ACCESSED_MASK;

            stl_raw(pde_ptr, pde);

        }



        /* page directory entry */

        pte_ptr = phys_ram_base + 

            (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask);

        pte = ldl_raw(pte_ptr);

        if (!(pte & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        /* combine pde and pte user and rw protections */

        ptep = pte & pde;

        if (is_user) {

            if (!(ptep & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(ptep & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&

                is_write && !(ptep & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pte & PG_DIRTY_MASK);

        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

            pte |= PG_ACCESSED_MASK;

            if (is_dirty)

                pte |= PG_DIRTY_MASK;

            stl_raw(pte_ptr, pte);

        }

        page_size = 4096;

        virt_addr = addr & ~0xfff;

    }



    /* the page can be put in the TLB */

    prot = PROT_READ;

    if (pte & PG_DIRTY_MASK) {

        /* only set write access if already dirty... otherwise wait

           for dirty access */

        if (is_user) {

            if (ptep & PG_RW_MASK)

                prot |= PROT_WRITE;

        } else {

            if (!(env->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||

                (ptep & PG_RW_MASK))

                prot |= PROT_WRITE;

        }

    }



 do_mapping:

    pte = pte & a20_mask;



    /* Even if 4MB pages, we map only one 4KB page in the cache to

       avoid filling it too fast */

    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;

    

    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);

    return ret;

 do_fault_protect:

    error_code = PG_ERROR_P_MASK;

 do_fault:

    env->cr[2] = addr;

    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;

    if (is_user)

        env->error_code |= PG_ERROR_U_MASK;

    return 1;

}

int cpu_x86_handle_mmu_fault(CPUX86State *env, uint32_t addr, 

                             int is_write, int is_user, int is_softmmu)

{

    uint8_t *pde_ptr, *pte_ptr;

    uint32_t pde, pte, virt_addr, ptep;

    int error_code, is_dirty, prot, page_size, ret;

    unsigned long paddr, vaddr, page_offset;

    

#if defined(DEBUG_MMU)

    printf("MMU fault: addr=0x%08x w=%d u=%d eip=%08x\n", 

           addr, is_write, is_user, env->eip);

#endif



    if (env->user_mode_only) {

        

        error_code = 0;

        goto do_fault;

    }



    if (!(env->cr[0] & CR0_PG_MASK)) {

        pte = addr;

        virt_addr = addr & TARGET_PAGE_MASK;

        prot = PROT_READ | PROT_WRITE;

        page_size = 4096;

        goto do_mapping;

    }



    

    pde_ptr = phys_ram_base + 

        (((env->cr[3] & ~0xfff) + ((addr >> 20) & ~3)) & a20_mask);

    pde = ldl_raw(pde_ptr);

    if (!(pde & PG_PRESENT_MASK)) {

        error_code = 0;

        goto do_fault;

    }

    

    if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) {

        if (is_user) {

            if (!(pde & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(pde & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&

                is_write && !(pde & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pde & PG_DIRTY_MASK);

        if (!(pde & PG_ACCESSED_MASK) || is_dirty) {

            pde |= PG_ACCESSED_MASK;

            if (is_dirty)

                pde |= PG_DIRTY_MASK;

            stl_raw(pde_ptr, pde);

        }

        

        pte = pde & ~0x003ff000; 

        ptep = pte;

        page_size = 4096 * 1024;

        virt_addr = addr & ~0x003fffff;

    } else {

        if (!(pde & PG_ACCESSED_MASK)) {

            pde |= PG_ACCESSED_MASK;

            stl_raw(pde_ptr, pde);

        }



        

        pte_ptr = phys_ram_base + 

            (((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask);

        pte = ldl_raw(pte_ptr);

        if (!(pte & PG_PRESENT_MASK)) {

            error_code = 0;

            goto do_fault;

        }

        

        ptep = pte & pde;

        if (is_user) {

            if (!(ptep & PG_USER_MASK))

                goto do_fault_protect;

            if (is_write && !(ptep & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((env->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&

                is_write && !(ptep & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        is_dirty = is_write && !(pte & PG_DIRTY_MASK);

        if (!(pte & PG_ACCESSED_MASK) || is_dirty) {

            pte |= PG_ACCESSED_MASK;

            if (is_dirty)

                pte |= PG_DIRTY_MASK;

            stl_raw(pte_ptr, pte);

        }

        page_size = 4096;

        virt_addr = addr & ~0xfff;

    }



    

    prot = PROT_READ;

    if (pte & PG_DIRTY_MASK) {

        



        if (is_user) {

            if (ptep & PG_RW_MASK)

                prot |= PROT_WRITE;

        } else {

            if (!(env->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||

                (ptep & PG_RW_MASK))

                prot |= PROT_WRITE;

        }

    }



 do_mapping:

    pte = pte & a20_mask;



    



    page_offset = (addr & TARGET_PAGE_MASK) & (page_size - 1);

    paddr = (pte & TARGET_PAGE_MASK) + page_offset;

    vaddr = virt_addr + page_offset;

    

    ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);

    return ret;

 do_fault_protect:

    error_code = PG_ERROR_P_MASK;

 do_fault:

    env->cr[2] = addr;

    env->error_code = (is_write << PG_ERROR_W_BIT) | error_code;

    if (is_user)

        env->error_code |= PG_ERROR_U_MASK;

    return 1;

}

int FUNC_0(CPUX86State *VAR_0, uint32_t VAR_1, 

                             int VAR_2, int VAR_3, int VAR_4)

{

    uint8_t *pde_ptr, *pte_ptr;

    uint32_t pde, pte, virt_addr, ptep;

    int VAR_5, VAR_6, VAR_7, VAR_8, VAR_9;

    unsigned long VAR_10, VAR_11, VAR_12;

    

#if defined(DEBUG_MMU)

    printf("MMU fault: VAR_1=0x%08x w=%d u=%d eip=%08x\n", 

           VAR_1, VAR_2, VAR_3, VAR_0->eip);

#endif



    if (VAR_0->user_mode_only) {

        

        VAR_5 = 0;

        goto do_fault;

    }



    if (!(VAR_0->cr[0] & CR0_PG_MASK)) {

        pte = VAR_1;

        virt_addr = VAR_1 & TARGET_PAGE_MASK;

        VAR_7 = PROT_READ | PROT_WRITE;

        VAR_8 = 4096;

        goto do_mapping;

    }



    

    pde_ptr = phys_ram_base + 

        (((VAR_0->cr[3] & ~0xfff) + ((VAR_1 >> 20) & ~3)) & a20_mask);

    pde = ldl_raw(pde_ptr);

    if (!(pde & PG_PRESENT_MASK)) {

        VAR_5 = 0;

        goto do_fault;

    }

    

    if ((pde & PG_PSE_MASK) && (VAR_0->cr[4] & CR4_PSE_MASK)) {

        if (VAR_3) {

            if (!(pde & PG_USER_MASK))

                goto do_fault_protect;

            if (VAR_2 && !(pde & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((VAR_0->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&

                VAR_2 && !(pde & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        VAR_6 = VAR_2 && !(pde & PG_DIRTY_MASK);

        if (!(pde & PG_ACCESSED_MASK) || VAR_6) {

            pde |= PG_ACCESSED_MASK;

            if (VAR_6)

                pde |= PG_DIRTY_MASK;

            stl_raw(pde_ptr, pde);

        }

        

        pte = pde & ~0x003ff000; 

        ptep = pte;

        VAR_8 = 4096 * 1024;

        virt_addr = VAR_1 & ~0x003fffff;

    } else {

        if (!(pde & PG_ACCESSED_MASK)) {

            pde |= PG_ACCESSED_MASK;

            stl_raw(pde_ptr, pde);

        }



        

        pte_ptr = phys_ram_base + 

            (((pde & ~0xfff) + ((VAR_1 >> 10) & 0xffc)) & a20_mask);

        pte = ldl_raw(pte_ptr);

        if (!(pte & PG_PRESENT_MASK)) {

            VAR_5 = 0;

            goto do_fault;

        }

        

        ptep = pte & pde;

        if (VAR_3) {

            if (!(ptep & PG_USER_MASK))

                goto do_fault_protect;

            if (VAR_2 && !(ptep & PG_RW_MASK))

                goto do_fault_protect;

        } else {

            if ((VAR_0->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&

                VAR_2 && !(ptep & PG_RW_MASK)) 

                goto do_fault_protect;

        }

        VAR_6 = VAR_2 && !(pte & PG_DIRTY_MASK);

        if (!(pte & PG_ACCESSED_MASK) || VAR_6) {

            pte |= PG_ACCESSED_MASK;

            if (VAR_6)

                pte |= PG_DIRTY_MASK;

            stl_raw(pte_ptr, pte);

        }

        VAR_8 = 4096;

        virt_addr = VAR_1 & ~0xfff;

    }



    

    VAR_7 = PROT_READ;

    if (pte & PG_DIRTY_MASK) {

        



        if (VAR_3) {

            if (ptep & PG_RW_MASK)

                VAR_7 |= PROT_WRITE;

        } else {

            if (!(VAR_0->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||

                (ptep & PG_RW_MASK))

                VAR_7 |= PROT_WRITE;

        }

    }



 do_mapping:

    pte = pte & a20_mask;



    



    VAR_12 = (VAR_1 & TARGET_PAGE_MASK) & (VAR_8 - 1);

    VAR_10 = (pte & TARGET_PAGE_MASK) + VAR_12;

    VAR_11 = virt_addr + VAR_12;

    

    VAR_9 = tlb_set_page(VAR_0, VAR_11, VAR_10, VAR_7, VAR_3, VAR_4);

    return VAR_9;

 do_fault_protect:

    VAR_5 = PG_ERROR_P_MASK;

 do_fault:

    VAR_0->cr[2] = VAR_1;

    VAR_0->VAR_5 = (VAR_2 << PG_ERROR_W_BIT) | VAR_5;

    if (VAR_3)

        VAR_0->VAR_5 |= PG_ERROR_U_MASK;

    return 1;

}

int FUNC_0(CPUX86State *VAR_0, uint32_t VAR_1,
int VAR_2, int VAR_3, int VAR_4)
{ uint8_t *pde_ptr, *pte_ptr; uint32_t pde, pte, virt_addr, ptep; int VAR_5, VAR_6, VAR_7, VAR_8, VAR_9; unsigned long VAR_10, VAR_11, VAR_12; #if defined(DEBUG_MMU)
printf("MMU fault: VAR_1=0x%08x w=%d u=%d eip=%08x\n",
VAR_1, VAR_2, VAR_3, VAR_0->eip); #endif
if (VAR_0->user_mode_only) { VAR_5 = 0; goto do_fault; } if (!(VAR_0->cr[0] & CR0_PG_MASK)) { pte = VAR_1; virt_addr = VAR_1 & TARGET_PAGE_MASK; VAR_7 = PROT_READ | PROT_WRITE; VAR_8 = 4096; goto do_mapping; } pde_ptr = phys_ram_base +
(((VAR_0->cr[3] & ~0xfff) + ((VAR_1 >> 20) & ~3)) & a20_mask); pde = ldl_raw(pde_ptr); if (!(pde & PG_PRESENT_MASK)) { VAR_5 = 0; goto do_fault; } if ((pde & PG_PSE_MASK) && (VAR_0->cr[4] & CR4_PSE_MASK)) { if (VAR_3) { if (!(pde & PG_USER_MASK))
goto do_fault_protect; if (VAR_2 && !(pde & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) && (pde & PG_USER_MASK) &&
VAR_2 && !(pde & PG_RW_MASK))
goto do_fault_protect; } VAR_6 = VAR_2 && !(pde & PG_DIRTY_MASK); if (!(pde & PG_ACCESSED_MASK) || VAR_6) { pde |= PG_ACCESSED_MASK; if (VAR_6)
pde |= PG_DIRTY_MASK; stl_raw(pde_ptr, pde); } pte = pde & ~0x003ff000; ptep = pte; VAR_8 = 4096 * 1024; virt_addr = VAR_1 & ~0x003fffff; } else { if (!(pde & PG_ACCESSED_MASK)) { pde |= PG_ACCESSED_MASK; stl_raw(pde_ptr, pde); } pte_ptr = phys_ram_base +
(((pde & ~0xfff) + ((VAR_1 >> 10) & 0xffc)) & a20_mask); pte = ldl_raw(pte_ptr); if (!(pte & PG_PRESENT_MASK)) { VAR_5 = 0; goto do_fault; } ptep = pte & pde; if (VAR_3) { if (!(ptep & PG_USER_MASK))
goto do_fault_protect; if (VAR_2 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } else { if ((VAR_0->cr[0] & CR0_WP_MASK) && (ptep & PG_USER_MASK) &&
VAR_2 && !(ptep & PG_RW_MASK))
goto do_fault_protect; } VAR_6 = VAR_2 && !(pte & PG_DIRTY_MASK); if (!(pte & PG_ACCESSED_MASK) || VAR_6) { pte |= PG_ACCESSED_MASK; if (VAR_6)
pte |= PG_DIRTY_MASK; stl_raw(pte_ptr, pte); } VAR_8 = 4096; virt_addr = VAR_1 & ~0xfff; } VAR_7 = PROT_READ; if (pte & PG_DIRTY_MASK) { if (VAR_3) { if (ptep & PG_RW_MASK)
VAR_7 |= PROT_WRITE; } else { if (!(VAR_0->cr[0] & CR0_WP_MASK) || !(ptep & PG_USER_MASK) ||
(ptep & PG_RW_MASK))
VAR_7 |= PROT_WRITE; } } do_mapping:
pte = pte & a20_mask; VAR_12 = (VAR_1 & TARGET_PAGE_MASK) & (VAR_8 - 1); VAR_10 = (pte & TARGET_PAGE_MASK) + VAR_12; VAR_11 = virt_addr + VAR_12; VAR_9 = tlb_set_page(VAR_0, VAR_11, VAR_10, VAR_7, VAR_3, VAR_4); return VAR_9; do_fault_protect:
VAR_5 = PG_ERROR_P_MASK; do_fault:
VAR_0->cr[2] = VAR_1; VAR_0->VAR_5 = (VAR_2 << PG_ERROR_W_BIT) | VAR_5; if (VAR_3)
VAR_0->VAR_5 |= PG_ERROR_U_MASK; return 1; }