diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-14 17:15:19 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-14 17:15:19 +0000 |
commit | 43057ab1272ba2b9b052b19a3453fb0f3b510149 (patch) | |
tree | fc5f9fdb5393b9ea7e019d0c6ef089e0c9d6d2e8 | |
parent | c5d6edc3fc660fa188e3161f364ba73940219c10 (diff) | |
download | qemu-43057ab1272ba2b9b052b19a3453fb0f3b510149.zip qemu-43057ab1272ba2b9b052b19a3453fb0f3b510149.tar.gz qemu-43057ab1272ba2b9b052b19a3453fb0f3b510149.tar.bz2 |
use constants for TLB handling (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1978 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-mips/cpu.h | 2 | ||||
-rw-r--r-- | target-mips/helper.c | 67 |
2 files changed, 36 insertions, 33 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h index de6be29..fcc1fdf 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -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; diff --git a/target-mips/helper.c b/target-mips/helper.c index 8b60b2c..8325d48 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -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; - if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { - *physical = tlb->PFN[n] | (address & 0xFFF); + if (!(n ? tlb->V1 : tlb->V0)) + return TLBRET_INVALID; + if (rw == 0 || (n ? tlb->D1 : tlb->D0)) { + *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, - is_user, is_softmmu); + 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; |