Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ 157777ef

History | View | Annotate | Download (12 kB)

1 e8af50a3 bellard
/*
2 e8af50a3 bellard
 *  sparc helpers
3 e8af50a3 bellard
 * 
4 e8af50a3 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 e8af50a3 bellard
 *
6 e8af50a3 bellard
 * This library is free software; you can redistribute it and/or
7 e8af50a3 bellard
 * modify it under the terms of the GNU Lesser General Public
8 e8af50a3 bellard
 * License as published by the Free Software Foundation; either
9 e8af50a3 bellard
 * version 2 of the License, or (at your option) any later version.
10 e8af50a3 bellard
 *
11 e8af50a3 bellard
 * This library is distributed in the hope that it will be useful,
12 e8af50a3 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 e8af50a3 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 e8af50a3 bellard
 * Lesser General Public License for more details.
15 e8af50a3 bellard
 *
16 e8af50a3 bellard
 * You should have received a copy of the GNU Lesser General Public
17 e8af50a3 bellard
 * License along with this library; if not, write to the Free Software
18 e8af50a3 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 e8af50a3 bellard
 */
20 e8af50a3 bellard
#include "exec.h"
21 e8af50a3 bellard
22 e80cfcfc bellard
//#define DEBUG_PCALL
23 e80cfcfc bellard
//#define DEBUG_MMU
24 e8af50a3 bellard
25 e8af50a3 bellard
/* Sparc MMU emulation */
26 e8af50a3 bellard
27 e8af50a3 bellard
/* thread support */
28 e8af50a3 bellard
29 e8af50a3 bellard
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
30 e8af50a3 bellard
31 e8af50a3 bellard
void cpu_lock(void)
32 e8af50a3 bellard
{
33 e8af50a3 bellard
    spin_lock(&global_cpu_lock);
34 e8af50a3 bellard
}
35 e8af50a3 bellard
36 e8af50a3 bellard
void cpu_unlock(void)
37 e8af50a3 bellard
{
38 e8af50a3 bellard
    spin_unlock(&global_cpu_lock);
39 e8af50a3 bellard
}
40 e8af50a3 bellard
41 9d893301 bellard
#if defined(CONFIG_USER_ONLY) 
42 9d893301 bellard
43 9d893301 bellard
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
44 9d893301 bellard
                               int is_user, int is_softmmu)
45 9d893301 bellard
{
46 9d893301 bellard
    env->mmuregs[4] = address;
47 878d3096 bellard
    if (rw & 2)
48 878d3096 bellard
        env->exception_index = TT_TFAULT;
49 878d3096 bellard
    else
50 878d3096 bellard
        env->exception_index = TT_DFAULT;
51 9d893301 bellard
    return 1;
52 9d893301 bellard
}
53 9d893301 bellard
54 9d893301 bellard
#else
55 e8af50a3 bellard
56 e8af50a3 bellard
#define MMUSUFFIX _mmu
57 e8af50a3 bellard
#define GETPC() (__builtin_return_address(0))
58 e8af50a3 bellard
59 e8af50a3 bellard
#define SHIFT 0
60 e8af50a3 bellard
#include "softmmu_template.h"
61 e8af50a3 bellard
62 e8af50a3 bellard
#define SHIFT 1
63 e8af50a3 bellard
#include "softmmu_template.h"
64 e8af50a3 bellard
65 e8af50a3 bellard
#define SHIFT 2
66 e8af50a3 bellard
#include "softmmu_template.h"
67 e8af50a3 bellard
68 e8af50a3 bellard
#define SHIFT 3
69 e8af50a3 bellard
#include "softmmu_template.h"
70 e8af50a3 bellard
71 e8af50a3 bellard
72 e8af50a3 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
73 e8af50a3 bellard
   NULL, it means that the function was called in C code (i.e. not
74 e8af50a3 bellard
   from generated code or from helper.c) */
75 e8af50a3 bellard
/* XXX: fix it to restore all registers */
76 0fa85d43 bellard
void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
77 e8af50a3 bellard
{
78 e8af50a3 bellard
    TranslationBlock *tb;
79 e8af50a3 bellard
    int ret;
80 e8af50a3 bellard
    unsigned long pc;
81 e8af50a3 bellard
    CPUState *saved_env;
82 e8af50a3 bellard
83 e8af50a3 bellard
    /* XXX: hack to restore env in all cases, even if not called from
84 e8af50a3 bellard
       generated code */
85 e8af50a3 bellard
    saved_env = env;
86 e8af50a3 bellard
    env = cpu_single_env;
87 e8af50a3 bellard
88 e8af50a3 bellard
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
89 e8af50a3 bellard
    if (ret) {
90 e8af50a3 bellard
        if (retaddr) {
91 e8af50a3 bellard
            /* now we have a real cpu fault */
92 e8af50a3 bellard
            pc = (unsigned long)retaddr;
93 e8af50a3 bellard
            tb = tb_find_pc(pc);
94 e8af50a3 bellard
            if (tb) {
95 e8af50a3 bellard
                /* the PC is inside the translated code. It means that we have
96 e8af50a3 bellard
                   a virtual CPU fault */
97 e8af50a3 bellard
                cpu_restore_state(tb, env, pc, NULL);
98 e8af50a3 bellard
            }
99 e8af50a3 bellard
        }
100 878d3096 bellard
        cpu_loop_exit();
101 e8af50a3 bellard
    }
102 e8af50a3 bellard
    env = saved_env;
103 e8af50a3 bellard
}
104 e8af50a3 bellard
105 e8af50a3 bellard
static const int access_table[8][8] = {
106 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 3, 3 },
107 e8af50a3 bellard
    { 0, 0, 0, 0, 2, 0, 0, 0 },
108 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 3, 3 },
109 e8af50a3 bellard
    { 2, 2, 0, 0, 0, 2, 0, 0 },
110 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 2, 3, 3 },
111 e8af50a3 bellard
    { 2, 0, 2, 0, 2, 0, 2, 0 },
112 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 3, 3 },
113 e8af50a3 bellard
    { 2, 2, 2, 0, 2, 2, 2, 0 }
114 e8af50a3 bellard
};
115 e8af50a3 bellard
116 e8af50a3 bellard
/* 1 = write OK */
117 e8af50a3 bellard
static const int rw_table[2][8] = {
118 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 1, 0, 1 },
119 e8af50a3 bellard
    { 0, 1, 0, 1, 0, 0, 0, 0 }
120 e8af50a3 bellard
};
121 e8af50a3 bellard
122 af7bf89b bellard
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
123 af7bf89b bellard
                          int *access_index, target_ulong address, int rw,
124 e80cfcfc bellard
                          int is_user)
125 e8af50a3 bellard
{
126 e80cfcfc bellard
    int access_perms = 0;
127 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
128 af7bf89b bellard
    uint32_t pde;
129 af7bf89b bellard
    target_ulong virt_addr;
130 e80cfcfc bellard
    int error_code = 0, is_dirty;
131 e80cfcfc bellard
    unsigned long page_offset;
132 e8af50a3 bellard
133 e8af50a3 bellard
    virt_addr = address & TARGET_PAGE_MASK;
134 e8af50a3 bellard
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
135 e80cfcfc bellard
        *physical = address;
136 e80cfcfc bellard
        *prot = PAGE_READ | PAGE_WRITE;
137 e80cfcfc bellard
        return 0;
138 e8af50a3 bellard
    }
139 e8af50a3 bellard
140 7483750d bellard
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
141 7483750d bellard
142 e8af50a3 bellard
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
143 e8af50a3 bellard
    /* Context base + context number */
144 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
145 49be8030 bellard
    pde = ldl_phys(pde_ptr);
146 e8af50a3 bellard
147 e8af50a3 bellard
    /* Ctx pde */
148 e8af50a3 bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
149 e80cfcfc bellard
    default:
150 e8af50a3 bellard
    case 0: /* Invalid */
151 7483750d bellard
        return 1 << 2;
152 e80cfcfc bellard
    case 2: /* L0 PTE, maybe should not happen? */
153 e8af50a3 bellard
    case 3: /* Reserved */
154 7483750d bellard
        return 4 << 2;
155 e80cfcfc bellard
    case 1: /* L0 PDE */
156 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
157 49be8030 bellard
        pde = ldl_phys(pde_ptr);
158 e8af50a3 bellard
159 e8af50a3 bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
160 e80cfcfc bellard
        default:
161 e8af50a3 bellard
        case 0: /* Invalid */
162 7483750d bellard
            return (1 << 8) | (1 << 2);
163 e8af50a3 bellard
        case 3: /* Reserved */
164 7483750d bellard
            return (1 << 8) | (4 << 2);
165 e80cfcfc bellard
        case 1: /* L1 PDE */
166 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
167 49be8030 bellard
            pde = ldl_phys(pde_ptr);
168 e8af50a3 bellard
169 e8af50a3 bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
170 e80cfcfc bellard
            default:
171 e8af50a3 bellard
            case 0: /* Invalid */
172 7483750d bellard
                return (2 << 8) | (1 << 2);
173 e8af50a3 bellard
            case 3: /* Reserved */
174 7483750d bellard
                return (2 << 8) | (4 << 2);
175 e80cfcfc bellard
            case 1: /* L2 PDE */
176 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
177 49be8030 bellard
                pde = ldl_phys(pde_ptr);
178 e8af50a3 bellard
179 e8af50a3 bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
180 e80cfcfc bellard
                default:
181 e8af50a3 bellard
                case 0: /* Invalid */
182 7483750d bellard
                    return (3 << 8) | (1 << 2);
183 e8af50a3 bellard
                case 1: /* PDE, should not happen */
184 e8af50a3 bellard
                case 3: /* Reserved */
185 7483750d bellard
                    return (3 << 8) | (4 << 2);
186 e8af50a3 bellard
                case 2: /* L3 PTE */
187 e8af50a3 bellard
                    virt_addr = address & TARGET_PAGE_MASK;
188 e8af50a3 bellard
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
189 e8af50a3 bellard
                }
190 e8af50a3 bellard
                break;
191 e8af50a3 bellard
            case 2: /* L2 PTE */
192 e8af50a3 bellard
                virt_addr = address & ~0x3ffff;
193 e8af50a3 bellard
                page_offset = address & 0x3ffff;
194 e8af50a3 bellard
            }
195 e8af50a3 bellard
            break;
196 e8af50a3 bellard
        case 2: /* L1 PTE */
197 e8af50a3 bellard
            virt_addr = address & ~0xffffff;
198 e8af50a3 bellard
            page_offset = address & 0xffffff;
199 e8af50a3 bellard
        }
200 e8af50a3 bellard
    }
201 e8af50a3 bellard
202 e8af50a3 bellard
    /* update page modified and dirty bits */
203 b769d8fe bellard
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
204 e8af50a3 bellard
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
205 e8af50a3 bellard
        pde |= PG_ACCESSED_MASK;
206 e8af50a3 bellard
        if (is_dirty)
207 e8af50a3 bellard
            pde |= PG_MODIFIED_MASK;
208 49be8030 bellard
        stl_phys_notdirty(pde_ptr, pde);
209 e8af50a3 bellard
    }
210 e8af50a3 bellard
    /* check access */
211 e8af50a3 bellard
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
212 e80cfcfc bellard
    error_code = access_table[*access_index][access_perms];
213 e8af50a3 bellard
    if (error_code)
214 e80cfcfc bellard
        return error_code;
215 e8af50a3 bellard
216 e8af50a3 bellard
    /* the page can be put in the TLB */
217 e80cfcfc bellard
    *prot = PAGE_READ;
218 e8af50a3 bellard
    if (pde & PG_MODIFIED_MASK) {
219 e8af50a3 bellard
        /* only set write access if already dirty... otherwise wait
220 e8af50a3 bellard
           for dirty access */
221 e8af50a3 bellard
        if (rw_table[is_user][access_perms])
222 e80cfcfc bellard
                *prot |= PAGE_WRITE;
223 e8af50a3 bellard
    }
224 e8af50a3 bellard
225 e8af50a3 bellard
    /* Even if large ptes, we map only one 4KB page in the cache to
226 e8af50a3 bellard
       avoid filling it too fast */
227 e80cfcfc bellard
    *physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
228 e80cfcfc bellard
    return 0;
229 e80cfcfc bellard
}
230 e80cfcfc bellard
231 e80cfcfc bellard
/* Perform address translation */
232 af7bf89b bellard
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
233 e80cfcfc bellard
                              int is_user, int is_softmmu)
234 e80cfcfc bellard
{
235 af7bf89b bellard
    target_ulong virt_addr;
236 af7bf89b bellard
    target_phys_addr_t paddr;
237 e80cfcfc bellard
    unsigned long vaddr;
238 e80cfcfc bellard
    int error_code = 0, prot, ret = 0, access_index;
239 e8af50a3 bellard
240 e80cfcfc bellard
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user);
241 e80cfcfc bellard
    if (error_code == 0) {
242 e80cfcfc bellard
        virt_addr = address & TARGET_PAGE_MASK;
243 e80cfcfc bellard
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
244 e80cfcfc bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
245 e80cfcfc bellard
        return ret;
246 e80cfcfc bellard
    }
247 e8af50a3 bellard
248 e8af50a3 bellard
    if (env->mmuregs[3]) /* Fault status register */
249 e8af50a3 bellard
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
250 7483750d bellard
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
251 e8af50a3 bellard
    env->mmuregs[4] = address; /* Fault address register */
252 e8af50a3 bellard
253 878d3096 bellard
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
254 7483750d bellard
#if 0
255 878d3096 bellard
        // No fault
256 7483750d bellard
        vaddr = address & TARGET_PAGE_MASK;
257 7483750d bellard
        paddr = 0xfffff000;
258 7483750d bellard
        prot = PAGE_READ | PAGE_WRITE;
259 7483750d bellard
        ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
260 7483750d bellard
        return ret;
261 7483750d bellard
#else
262 7483750d bellard
        cpu_abort(env, "MMU no fault case no handled");
263 7483750d bellard
        return 0;
264 7483750d bellard
#endif
265 7483750d bellard
    } else {
266 7483750d bellard
        if (rw & 2)
267 7483750d bellard
            env->exception_index = TT_TFAULT;
268 7483750d bellard
        else
269 7483750d bellard
            env->exception_index = TT_DFAULT;
270 7483750d bellard
        return 1;
271 878d3096 bellard
    }
272 e8af50a3 bellard
}
273 9d893301 bellard
#endif
274 e8af50a3 bellard
275 af7bf89b bellard
void memcpy32(target_ulong *dst, const target_ulong *src)
276 e8af50a3 bellard
{
277 e8af50a3 bellard
    dst[0] = src[0];
278 e8af50a3 bellard
    dst[1] = src[1];
279 e8af50a3 bellard
    dst[2] = src[2];
280 e8af50a3 bellard
    dst[3] = src[3];
281 e8af50a3 bellard
    dst[4] = src[4];
282 e8af50a3 bellard
    dst[5] = src[5];
283 e8af50a3 bellard
    dst[6] = src[6];
284 e8af50a3 bellard
    dst[7] = src[7];
285 e8af50a3 bellard
}
286 e8af50a3 bellard
287 e8af50a3 bellard
void set_cwp(int new_cwp)
288 e8af50a3 bellard
{
289 e8af50a3 bellard
    /* put the modified wrap registers at their proper location */
290 e8af50a3 bellard
    if (env->cwp == (NWINDOWS - 1))
291 e8af50a3 bellard
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
292 e8af50a3 bellard
    env->cwp = new_cwp;
293 e8af50a3 bellard
    /* put the wrap registers at their temporary location */
294 e8af50a3 bellard
    if (new_cwp == (NWINDOWS - 1))
295 e8af50a3 bellard
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
296 e8af50a3 bellard
    env->regwptr = env->regbase + (new_cwp * 16);
297 e8af50a3 bellard
}
298 e8af50a3 bellard
299 0fa85d43 bellard
void cpu_set_cwp(CPUState *env1, int new_cwp)
300 0fa85d43 bellard
{
301 0fa85d43 bellard
    CPUState *saved_env;
302 0fa85d43 bellard
    saved_env = env;
303 0fa85d43 bellard
    env = env1;
304 0fa85d43 bellard
    set_cwp(new_cwp);
305 0fa85d43 bellard
    env = saved_env;
306 0fa85d43 bellard
}
307 0fa85d43 bellard
308 878d3096 bellard
void do_interrupt(int intno)
309 e8af50a3 bellard
{
310 e8af50a3 bellard
    int cwp;
311 e8af50a3 bellard
312 e8af50a3 bellard
#ifdef DEBUG_PCALL
313 e8af50a3 bellard
    if (loglevel & CPU_LOG_INT) {
314 e8af50a3 bellard
        static int count;
315 878d3096 bellard
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
316 878d3096 bellard
                count, intno,
317 9d893301 bellard
                env->pc,
318 9d893301 bellard
                env->npc, env->regwptr[6]);
319 e80cfcfc bellard
#if 1
320 7fe48483 bellard
        cpu_dump_state(env, logfile, fprintf, 0);
321 e8af50a3 bellard
        {
322 e8af50a3 bellard
            int i;
323 e8af50a3 bellard
            uint8_t *ptr;
324 e80cfcfc bellard
325 e8af50a3 bellard
            fprintf(logfile, "       code=");
326 e80cfcfc bellard
            ptr = (uint8_t *)env->pc;
327 e8af50a3 bellard
            for(i = 0; i < 16; i++) {
328 e8af50a3 bellard
                fprintf(logfile, " %02x", ldub(ptr + i));
329 e8af50a3 bellard
            }
330 e8af50a3 bellard
            fprintf(logfile, "\n");
331 e8af50a3 bellard
        }
332 e8af50a3 bellard
#endif
333 e8af50a3 bellard
        count++;
334 e8af50a3 bellard
    }
335 e8af50a3 bellard
#endif
336 e80cfcfc bellard
#if !defined(CONFIG_USER_ONLY) 
337 e80cfcfc bellard
    if (env->psret == 0) {
338 878d3096 bellard
        cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
339 e80cfcfc bellard
        return;
340 e80cfcfc bellard
    }
341 e80cfcfc bellard
#endif
342 e8af50a3 bellard
    env->psret = 0;
343 e8af50a3 bellard
    cwp = (env->cwp - 1) & (NWINDOWS - 1); 
344 e8af50a3 bellard
    set_cwp(cwp);
345 878d3096 bellard
    env->regwptr[9] = env->pc;
346 878d3096 bellard
    env->regwptr[10] = env->npc;
347 e8af50a3 bellard
    env->psrps = env->psrs;
348 e8af50a3 bellard
    env->psrs = 1;
349 e8af50a3 bellard
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
350 e8af50a3 bellard
    env->pc = env->tbr;
351 e8af50a3 bellard
    env->npc = env->pc + 4;
352 e8af50a3 bellard
    env->exception_index = 0;
353 e8af50a3 bellard
}
354 e8af50a3 bellard
355 af7bf89b bellard
target_ulong mmu_probe(target_ulong address, int mmulev)
356 e80cfcfc bellard
{
357 e80cfcfc bellard
    target_phys_addr_t pde_ptr;
358 e80cfcfc bellard
    uint32_t pde;
359 e80cfcfc bellard
360 e80cfcfc bellard
    /* Context base + context number */
361 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
362 49be8030 bellard
    pde = ldl_phys(pde_ptr);
363 49be8030 bellard
364 e80cfcfc bellard
    switch (pde & PTE_ENTRYTYPE_MASK) {
365 e80cfcfc bellard
    default:
366 e80cfcfc bellard
    case 0: /* Invalid */
367 e80cfcfc bellard
    case 2: /* PTE, maybe should not happen? */
368 e80cfcfc bellard
    case 3: /* Reserved */
369 e80cfcfc bellard
        return 0;
370 e80cfcfc bellard
    case 1: /* L1 PDE */
371 e80cfcfc bellard
        if (mmulev == 3)
372 e80cfcfc bellard
            return pde;
373 e80cfcfc bellard
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
374 49be8030 bellard
        pde = ldl_phys(pde_ptr);
375 e80cfcfc bellard
376 e80cfcfc bellard
        switch (pde & PTE_ENTRYTYPE_MASK) {
377 e80cfcfc bellard
        default:
378 e80cfcfc bellard
        case 0: /* Invalid */
379 e80cfcfc bellard
        case 3: /* Reserved */
380 e80cfcfc bellard
            return 0;
381 e80cfcfc bellard
        case 2: /* L1 PTE */
382 e80cfcfc bellard
            return pde;
383 e80cfcfc bellard
        case 1: /* L2 PDE */
384 e80cfcfc bellard
            if (mmulev == 2)
385 e80cfcfc bellard
                return pde;
386 e80cfcfc bellard
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
387 49be8030 bellard
            pde = ldl_phys(pde_ptr);
388 e80cfcfc bellard
389 e80cfcfc bellard
            switch (pde & PTE_ENTRYTYPE_MASK) {
390 e80cfcfc bellard
            default:
391 e80cfcfc bellard
            case 0: /* Invalid */
392 e80cfcfc bellard
            case 3: /* Reserved */
393 e80cfcfc bellard
                return 0;
394 e80cfcfc bellard
            case 2: /* L2 PTE */
395 e80cfcfc bellard
                return pde;
396 e80cfcfc bellard
            case 1: /* L3 PDE */
397 e80cfcfc bellard
                if (mmulev == 1)
398 e80cfcfc bellard
                    return pde;
399 e80cfcfc bellard
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
400 49be8030 bellard
                pde = ldl_phys(pde_ptr);
401 e80cfcfc bellard
402 e80cfcfc bellard
                switch (pde & PTE_ENTRYTYPE_MASK) {
403 e80cfcfc bellard
                default:
404 e80cfcfc bellard
                case 0: /* Invalid */
405 e80cfcfc bellard
                case 1: /* PDE, should not happen */
406 e80cfcfc bellard
                case 3: /* Reserved */
407 e80cfcfc bellard
                    return 0;
408 e80cfcfc bellard
                case 2: /* L3 PTE */
409 e80cfcfc bellard
                    return pde;
410 e80cfcfc bellard
                }
411 e80cfcfc bellard
            }
412 e80cfcfc bellard
        }
413 e80cfcfc bellard
    }
414 e80cfcfc bellard
    return 0;
415 e80cfcfc bellard
}
416 e80cfcfc bellard
417 55754d9e bellard
#ifdef DEBUG_MMU
418 e80cfcfc bellard
void dump_mmu(void)
419 e80cfcfc bellard
{
420 af7bf89b bellard
     target_ulong va, va1, va2;
421 af7bf89b bellard
     unsigned int n, m, o;
422 af7bf89b bellard
     target_phys_addr_t pde_ptr, pa;
423 e80cfcfc bellard
    uint32_t pde;
424 e80cfcfc bellard
425 e80cfcfc bellard
    printf("MMU dump:\n");
426 e80cfcfc bellard
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
427 49be8030 bellard
    pde = ldl_phys(pde_ptr);
428 af7bf89b bellard
    printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]);
429 e80cfcfc bellard
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
430 e80cfcfc bellard
        pde_ptr = mmu_probe(va, 2);
431 e80cfcfc bellard
        if (pde_ptr) {
432 e80cfcfc bellard
            pa = cpu_get_phys_page_debug(env, va);
433 af7bf89b bellard
             printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr);
434 e80cfcfc bellard
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
435 e80cfcfc bellard
                pde_ptr = mmu_probe(va1, 1);
436 e80cfcfc bellard
                if (pde_ptr) {
437 e80cfcfc bellard
                    pa = cpu_get_phys_page_debug(env, va1);
438 af7bf89b bellard
                     printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr);
439 e80cfcfc bellard
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
440 e80cfcfc bellard
                        pde_ptr = mmu_probe(va2, 0);
441 e80cfcfc bellard
                        if (pde_ptr) {
442 e80cfcfc bellard
                            pa = cpu_get_phys_page_debug(env, va2);
443 af7bf89b bellard
                             printf("  VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr);
444 e80cfcfc bellard
                        }
445 e80cfcfc bellard
                    }
446 e80cfcfc bellard
                }
447 e80cfcfc bellard
            }
448 e80cfcfc bellard
        }
449 e80cfcfc bellard
    }
450 e80cfcfc bellard
    printf("MMU dump ends\n");
451 e80cfcfc bellard
}
452 55754d9e bellard
#endif