Commit 43057ab1 authored by Fabrice Bellard's avatar Fabrice Bellard
Browse files

use constants for TLB handling (Thiemo Seufer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1978 c046a42c-6fe2-441c-8c8c-71466251a162
parent c5d6edc3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ struct CPUMIPSState {
		
#endif
#if defined(MIPS_USES_R4K_TLB)
    tlb_t tlb[16];
    tlb_t tlb[MIPS_TLB_NB];
#endif
    uint32_t CP0_index;
    uint32_t CP0_random;
+35 −32
Original line number Diff line number Diff line
@@ -28,53 +28,56 @@
#include "cpu.h"
#include "exec-all.h"

enum {
    TLBRET_DIRTY = -4,
    TLBRET_INVALID = -3,
    TLBRET_NOMATCH = -2,
    TLBRET_BADADDR = -1,
    TLBRET_MATCH = 0
};

/* MIPS32 4K MMU emulation */
#ifdef MIPS_USES_R4K_TLB
static int map_address (CPUState *env, target_ulong *physical, int *prot,
                        target_ulong address, int rw, int access_type)
{
    target_ulong tag = address & (TARGET_PAGE_MASK << 1);
    uint8_t ASID = env->CP0_EntryHi & 0xFF;
    tlb_t *tlb;
    target_ulong tag;
    uint8_t ASID;
    int i, n;
    int ret;

    ret = -2;
    tag = address & 0xFFFFE000;
    ASID = env->CP0_EntryHi & 0xFF;
    for (i = 0; i < MIPS_TLB_NB; i++) {
        tlb = &env->tlb[i];
        /* Check ASID, virtual page number & size */
        if ((tlb->G == 1 || tlb->ASID == ASID) &&
            tlb->VPN == tag && address < tlb->end2) {
            /* TLB match */
            n = (address >> 12) & 1;
            n = (address >> TARGET_PAGE_BITS) & 1;
            /* Check access rights */
           if (!(n ? tlb->V1 : tlb->V0))
                return -3;
                return TLBRET_INVALID;
           if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
                *physical = tlb->PFN[n] | (address & 0xFFF);
                *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK);
                *prot = PAGE_READ;
                if (n ? tlb->D1 : tlb->D0)
                    *prot |= PAGE_WRITE;
                return 0;
                return TLBRET_MATCH;
            }
            return -4;
            return TLBRET_DIRTY;
        }
    }

    return ret;
    return TLBRET_NOMATCH;
}
#endif

int get_physical_address (CPUState *env, target_ulong *physical, int *prot,
                          target_ulong address, int rw, int access_type)
static int get_physical_address (CPUState *env, target_ulong *physical,
                                int *prot, target_ulong address,
                                int rw, int access_type)
{
    int user_mode;
    int ret;

    /* User mode can only access useg */
    user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
    int user_mode = (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM;
    int ret = TLBRET_MATCH;

#if 0
    if (logfile) {
        fprintf(logfile, "user mode %d h %08x\n",
@@ -82,8 +85,7 @@ int get_physical_address (CPUState *env, target_ulong *physical, int *prot,
    }
#endif
    if (user_mode && address > 0x7FFFFFFFUL)
        return -1;
    ret = 0;
        return TLBRET_BADADDR;
    if (address < 0x80000000UL) {
        if (!(env->hflags & MIPS_HFLAG_ERL)) {
#ifdef MIPS_USES_R4K_TLB
@@ -181,7 +183,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
    access_type = ACCESS_INT;
    if (env->user_mode_only) {
        /* user mode only emulation */
        ret = -2;
        ret = TLBRET_NOMATCH;
        goto do_fault;
    }
    ret = get_physical_address(env, &physical, &prot,
@@ -190,14 +192,15 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
        fprintf(logfile, "%s address=%08x ret %d physical %08x prot %d\n",
                __func__, address, ret, physical, prot);
    }
    if (ret == 0) {
	ret = tlb_set_page(env, address & ~0xFFF, physical & ~0xFFF, prot,
    if (ret == TLBRET_MATCH) {
       ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
                          physical & TARGET_PAGE_MASK, prot,
                          is_user, is_softmmu);
    } else if (ret < 0) {
    do_fault:
        switch (ret) {
        default:
        case -1:
        case TLBRET_BADADDR:
            /* Reference to kernel address from user mode or supervisor mode */
            /* Reference to supervisor address from user mode */
            if (rw)
@@ -205,7 +208,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
            else
                exception = EXCP_AdEL;
            break;
        case -2:
        case TLBRET_NOMATCH:
            /* No TLB match for a mapped address */
            if (rw)
                exception = EXCP_TLBS;
@@ -213,14 +216,14 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                exception = EXCP_TLBL;
            error_code = 1;
            break;
        case -3:
        case TLBRET_INVALID:
            /* TLB match with no valid bit */
            if (rw)
                exception = EXCP_TLBS;
            else
                exception = EXCP_TLBL;
            break;
        case -4:
        case TLBRET_DIRTY:
            /* TLB match but 'D' bit is cleared */
            exception = EXCP_LTLBL;
            break;
@@ -231,7 +234,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
        env->CP0_Context = (env->CP0_Context & 0xff800000) |
	                   ((address >> 9) &   0x007ffff0);
        env->CP0_EntryHi =
            (env->CP0_EntryHi & 0xFF) | (address & 0xFFFFE000);
            (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
        env->exception_index = exception;
        env->error_code = error_code;
        ret = 1;