Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ f9fdea6b

History | View | Annotate | Download (90.8 kB)

1 79aceca5 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 5fafdf24 ths
 *
4 76a66253 j_mayer
 *  Copyright (c) 2003-2007 Jocelyn Mayer
5 79aceca5 bellard
 *
6 79aceca5 bellard
 * This library is free software; you can redistribute it and/or
7 79aceca5 bellard
 * modify it under the terms of the GNU Lesser General Public
8 79aceca5 bellard
 * License as published by the Free Software Foundation; either
9 79aceca5 bellard
 * version 2 of the License, or (at your option) any later version.
10 79aceca5 bellard
 *
11 79aceca5 bellard
 * This library is distributed in the hope that it will be useful,
12 79aceca5 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 79aceca5 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 79aceca5 bellard
 * Lesser General Public License for more details.
15 79aceca5 bellard
 *
16 79aceca5 bellard
 * You should have received a copy of the GNU Lesser General Public
17 79aceca5 bellard
 * License along with this library; if not, write to the Free Software
18 79aceca5 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 79aceca5 bellard
 */
20 fdabc366 bellard
#include <stdarg.h>
21 fdabc366 bellard
#include <stdlib.h>
22 fdabc366 bellard
#include <stdio.h>
23 fdabc366 bellard
#include <string.h>
24 fdabc366 bellard
#include <inttypes.h>
25 fdabc366 bellard
#include <signal.h>
26 fdabc366 bellard
#include <assert.h>
27 fdabc366 bellard
28 fdabc366 bellard
#include "cpu.h"
29 fdabc366 bellard
#include "exec-all.h"
30 0411a972 j_mayer
#include "helper_regs.h"
31 9a64fbe4 bellard
32 9a64fbe4 bellard
//#define DEBUG_MMU
33 9a64fbe4 bellard
//#define DEBUG_BATS
34 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
35 0411a972 j_mayer
//#define DUMP_PAGE_TABLES
36 9a64fbe4 bellard
//#define DEBUG_EXCEPTIONS
37 fdabc366 bellard
//#define FLUSH_ALL_TLBS
38 9a64fbe4 bellard
39 9a64fbe4 bellard
/*****************************************************************************/
40 3fc6c082 bellard
/* PowerPC MMU emulation */
41 a541f297 bellard
42 d9bce9d9 j_mayer
#if defined(CONFIG_USER_ONLY)
43 e96efcfc j_mayer
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
44 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
45 24741ef3 bellard
{
46 24741ef3 bellard
    int exception, error_code;
47 d9bce9d9 j_mayer
48 24741ef3 bellard
    if (rw == 2) {
49 e1833e1f j_mayer
        exception = POWERPC_EXCP_ISI;
50 8f793433 j_mayer
        error_code = 0x40000000;
51 24741ef3 bellard
    } else {
52 e1833e1f j_mayer
        exception = POWERPC_EXCP_DSI;
53 8f793433 j_mayer
        error_code = 0x40000000;
54 24741ef3 bellard
        if (rw)
55 24741ef3 bellard
            error_code |= 0x02000000;
56 24741ef3 bellard
        env->spr[SPR_DAR] = address;
57 24741ef3 bellard
        env->spr[SPR_DSISR] = error_code;
58 24741ef3 bellard
    }
59 24741ef3 bellard
    env->exception_index = exception;
60 24741ef3 bellard
    env->error_code = error_code;
61 76a66253 j_mayer
62 24741ef3 bellard
    return 1;
63 24741ef3 bellard
}
64 76a66253 j_mayer
65 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
66 24741ef3 bellard
{
67 24741ef3 bellard
    return addr;
68 24741ef3 bellard
}
69 36081602 j_mayer
70 24741ef3 bellard
#else
71 76a66253 j_mayer
/* Common routines used by software and hardware TLBs emulation */
72 b068d6a7 j_mayer
static always_inline int pte_is_valid (target_ulong pte0)
73 76a66253 j_mayer
{
74 76a66253 j_mayer
    return pte0 & 0x80000000 ? 1 : 0;
75 76a66253 j_mayer
}
76 76a66253 j_mayer
77 b068d6a7 j_mayer
static always_inline void pte_invalidate (target_ulong *pte0)
78 76a66253 j_mayer
{
79 76a66253 j_mayer
    *pte0 &= ~0x80000000;
80 76a66253 j_mayer
}
81 76a66253 j_mayer
82 caa4039c j_mayer
#if defined(TARGET_PPC64)
83 b068d6a7 j_mayer
static always_inline int pte64_is_valid (target_ulong pte0)
84 caa4039c j_mayer
{
85 caa4039c j_mayer
    return pte0 & 0x0000000000000001ULL ? 1 : 0;
86 caa4039c j_mayer
}
87 caa4039c j_mayer
88 b068d6a7 j_mayer
static always_inline void pte64_invalidate (target_ulong *pte0)
89 caa4039c j_mayer
{
90 caa4039c j_mayer
    *pte0 &= ~0x0000000000000001ULL;
91 caa4039c j_mayer
}
92 caa4039c j_mayer
#endif
93 caa4039c j_mayer
94 76a66253 j_mayer
#define PTE_PTEM_MASK 0x7FFFFFBF
95 76a66253 j_mayer
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
96 caa4039c j_mayer
#if defined(TARGET_PPC64)
97 caa4039c j_mayer
#define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
98 caa4039c j_mayer
#define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
99 caa4039c j_mayer
#endif
100 76a66253 j_mayer
101 b227a8e9 j_mayer
static always_inline int pp_check (int key, int pp, int nx)
102 b227a8e9 j_mayer
{
103 b227a8e9 j_mayer
    int access;
104 b227a8e9 j_mayer
105 b227a8e9 j_mayer
    /* Compute access rights */
106 b227a8e9 j_mayer
    /* When pp is 3/7, the result is undefined. Set it to noaccess */
107 b227a8e9 j_mayer
    access = 0;
108 b227a8e9 j_mayer
    if (key == 0) {
109 b227a8e9 j_mayer
        switch (pp) {
110 b227a8e9 j_mayer
        case 0x0:
111 b227a8e9 j_mayer
        case 0x1:
112 b227a8e9 j_mayer
        case 0x2:
113 b227a8e9 j_mayer
            access |= PAGE_WRITE;
114 b227a8e9 j_mayer
            /* No break here */
115 b227a8e9 j_mayer
        case 0x3:
116 b227a8e9 j_mayer
        case 0x6:
117 b227a8e9 j_mayer
            access |= PAGE_READ;
118 b227a8e9 j_mayer
            break;
119 b227a8e9 j_mayer
        }
120 b227a8e9 j_mayer
    } else {
121 b227a8e9 j_mayer
        switch (pp) {
122 b227a8e9 j_mayer
        case 0x0:
123 b227a8e9 j_mayer
        case 0x6:
124 b227a8e9 j_mayer
            access = 0;
125 b227a8e9 j_mayer
            break;
126 b227a8e9 j_mayer
        case 0x1:
127 b227a8e9 j_mayer
        case 0x3:
128 b227a8e9 j_mayer
            access = PAGE_READ;
129 b227a8e9 j_mayer
            break;
130 b227a8e9 j_mayer
        case 0x2:
131 b227a8e9 j_mayer
            access = PAGE_READ | PAGE_WRITE;
132 b227a8e9 j_mayer
            break;
133 b227a8e9 j_mayer
        }
134 b227a8e9 j_mayer
    }
135 b227a8e9 j_mayer
    if (nx == 0)
136 b227a8e9 j_mayer
        access |= PAGE_EXEC;
137 b227a8e9 j_mayer
138 b227a8e9 j_mayer
    return access;
139 b227a8e9 j_mayer
}
140 b227a8e9 j_mayer
141 b227a8e9 j_mayer
static always_inline int check_prot (int prot, int rw, int access_type)
142 b227a8e9 j_mayer
{
143 b227a8e9 j_mayer
    int ret;
144 b227a8e9 j_mayer
145 b227a8e9 j_mayer
    if (access_type == ACCESS_CODE) {
146 b227a8e9 j_mayer
        if (prot & PAGE_EXEC)
147 b227a8e9 j_mayer
            ret = 0;
148 b227a8e9 j_mayer
        else
149 b227a8e9 j_mayer
            ret = -2;
150 b227a8e9 j_mayer
    } else if (rw) {
151 b227a8e9 j_mayer
        if (prot & PAGE_WRITE)
152 b227a8e9 j_mayer
            ret = 0;
153 b227a8e9 j_mayer
        else
154 b227a8e9 j_mayer
            ret = -2;
155 b227a8e9 j_mayer
    } else {
156 b227a8e9 j_mayer
        if (prot & PAGE_READ)
157 b227a8e9 j_mayer
            ret = 0;
158 b227a8e9 j_mayer
        else
159 b227a8e9 j_mayer
            ret = -2;
160 b227a8e9 j_mayer
    }
161 b227a8e9 j_mayer
162 b227a8e9 j_mayer
    return ret;
163 b227a8e9 j_mayer
}
164 b227a8e9 j_mayer
165 b068d6a7 j_mayer
static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
166 b068d6a7 j_mayer
                                     target_ulong pte0, target_ulong pte1,
167 b227a8e9 j_mayer
                                     int h, int rw, int type)
168 76a66253 j_mayer
{
169 caa4039c j_mayer
    target_ulong ptem, mmask;
170 b227a8e9 j_mayer
    int access, ret, pteh, ptev, pp;
171 76a66253 j_mayer
172 76a66253 j_mayer
    access = 0;
173 76a66253 j_mayer
    ret = -1;
174 76a66253 j_mayer
    /* Check validity and table match */
175 caa4039c j_mayer
#if defined(TARGET_PPC64)
176 caa4039c j_mayer
    if (is_64b) {
177 caa4039c j_mayer
        ptev = pte64_is_valid(pte0);
178 caa4039c j_mayer
        pteh = (pte0 >> 1) & 1;
179 caa4039c j_mayer
    } else
180 caa4039c j_mayer
#endif
181 caa4039c j_mayer
    {
182 caa4039c j_mayer
        ptev = pte_is_valid(pte0);
183 caa4039c j_mayer
        pteh = (pte0 >> 6) & 1;
184 caa4039c j_mayer
    }
185 caa4039c j_mayer
    if (ptev && h == pteh) {
186 76a66253 j_mayer
        /* Check vsid & api */
187 caa4039c j_mayer
#if defined(TARGET_PPC64)
188 caa4039c j_mayer
        if (is_64b) {
189 caa4039c j_mayer
            ptem = pte0 & PTE64_PTEM_MASK;
190 caa4039c j_mayer
            mmask = PTE64_CHECK_MASK;
191 b227a8e9 j_mayer
            pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
192 b227a8e9 j_mayer
            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
193 b227a8e9 j_mayer
            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
194 caa4039c j_mayer
        } else
195 caa4039c j_mayer
#endif
196 caa4039c j_mayer
        {
197 caa4039c j_mayer
            ptem = pte0 & PTE_PTEM_MASK;
198 caa4039c j_mayer
            mmask = PTE_CHECK_MASK;
199 b227a8e9 j_mayer
            pp = pte1 & 0x00000003;
200 caa4039c j_mayer
        }
201 caa4039c j_mayer
        if (ptem == ctx->ptem) {
202 76a66253 j_mayer
            if (ctx->raddr != (target_ulong)-1) {
203 76a66253 j_mayer
                /* all matches should have equal RPN, WIMG & PP */
204 caa4039c j_mayer
                if ((ctx->raddr & mmask) != (pte1 & mmask)) {
205 caa4039c j_mayer
                    if (loglevel != 0)
206 76a66253 j_mayer
                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
207 76a66253 j_mayer
                    return -3;
208 76a66253 j_mayer
                }
209 76a66253 j_mayer
            }
210 76a66253 j_mayer
            /* Compute access rights */
211 b227a8e9 j_mayer
            access = pp_check(ctx->key, pp, ctx->nx);
212 76a66253 j_mayer
            /* Keep the matching PTE informations */
213 76a66253 j_mayer
            ctx->raddr = pte1;
214 76a66253 j_mayer
            ctx->prot = access;
215 b227a8e9 j_mayer
            ret = check_prot(ctx->prot, rw, type);
216 b227a8e9 j_mayer
            if (ret == 0) {
217 76a66253 j_mayer
                /* Access granted */
218 76a66253 j_mayer
#if defined (DEBUG_MMU)
219 4a057712 j_mayer
                if (loglevel != 0)
220 76a66253 j_mayer
                    fprintf(logfile, "PTE access granted !\n");
221 76a66253 j_mayer
#endif
222 76a66253 j_mayer
            } else {
223 76a66253 j_mayer
                /* Access right violation */
224 76a66253 j_mayer
#if defined (DEBUG_MMU)
225 4a057712 j_mayer
                if (loglevel != 0)
226 76a66253 j_mayer
                    fprintf(logfile, "PTE access rejected\n");
227 76a66253 j_mayer
#endif
228 76a66253 j_mayer
            }
229 76a66253 j_mayer
        }
230 76a66253 j_mayer
    }
231 76a66253 j_mayer
232 76a66253 j_mayer
    return ret;
233 76a66253 j_mayer
}
234 76a66253 j_mayer
235 b227a8e9 j_mayer
static int pte32_check (mmu_ctx_t *ctx, target_ulong pte0, target_ulong pte1,
236 b227a8e9 j_mayer
                        int h, int rw, int type)
237 caa4039c j_mayer
{
238 b227a8e9 j_mayer
    return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
239 caa4039c j_mayer
}
240 caa4039c j_mayer
241 caa4039c j_mayer
#if defined(TARGET_PPC64)
242 b227a8e9 j_mayer
static int pte64_check (mmu_ctx_t *ctx, target_ulong pte0, target_ulong pte1,
243 b227a8e9 j_mayer
                        int h, int rw, int type)
244 caa4039c j_mayer
{
245 b227a8e9 j_mayer
    return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
246 caa4039c j_mayer
}
247 caa4039c j_mayer
#endif
248 caa4039c j_mayer
249 76a66253 j_mayer
static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
250 76a66253 j_mayer
                             int ret, int rw)
251 76a66253 j_mayer
{
252 76a66253 j_mayer
    int store = 0;
253 76a66253 j_mayer
254 76a66253 j_mayer
    /* Update page flags */
255 76a66253 j_mayer
    if (!(*pte1p & 0x00000100)) {
256 76a66253 j_mayer
        /* Update accessed flag */
257 76a66253 j_mayer
        *pte1p |= 0x00000100;
258 76a66253 j_mayer
        store = 1;
259 76a66253 j_mayer
    }
260 76a66253 j_mayer
    if (!(*pte1p & 0x00000080)) {
261 76a66253 j_mayer
        if (rw == 1 && ret == 0) {
262 76a66253 j_mayer
            /* Update changed flag */
263 76a66253 j_mayer
            *pte1p |= 0x00000080;
264 76a66253 j_mayer
            store = 1;
265 76a66253 j_mayer
        } else {
266 76a66253 j_mayer
            /* Force page fault for first write access */
267 76a66253 j_mayer
            ctx->prot &= ~PAGE_WRITE;
268 76a66253 j_mayer
        }
269 76a66253 j_mayer
    }
270 76a66253 j_mayer
271 76a66253 j_mayer
    return store;
272 76a66253 j_mayer
}
273 76a66253 j_mayer
274 76a66253 j_mayer
/* Software driven TLB helpers */
275 76a66253 j_mayer
static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
276 76a66253 j_mayer
                              int way, int is_code)
277 76a66253 j_mayer
{
278 76a66253 j_mayer
    int nr;
279 76a66253 j_mayer
280 76a66253 j_mayer
    /* Select TLB num in a way from address */
281 76a66253 j_mayer
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
282 76a66253 j_mayer
    /* Select TLB way */
283 76a66253 j_mayer
    nr += env->tlb_per_way * way;
284 76a66253 j_mayer
    /* 6xx have separate TLBs for instructions and data */
285 76a66253 j_mayer
    if (is_code && env->id_tlbs == 1)
286 76a66253 j_mayer
        nr += env->nb_tlb;
287 76a66253 j_mayer
288 76a66253 j_mayer
    return nr;
289 76a66253 j_mayer
}
290 76a66253 j_mayer
291 daf4f96e j_mayer
static void ppc6xx_tlb_invalidate_all (CPUState *env)
292 76a66253 j_mayer
{
293 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
294 76a66253 j_mayer
    int nr, max;
295 76a66253 j_mayer
296 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB) && 0
297 76a66253 j_mayer
    if (loglevel != 0) {
298 76a66253 j_mayer
        fprintf(logfile, "Invalidate all TLBs\n");
299 76a66253 j_mayer
    }
300 76a66253 j_mayer
#endif
301 76a66253 j_mayer
    /* Invalidate all defined software TLB */
302 76a66253 j_mayer
    max = env->nb_tlb;
303 76a66253 j_mayer
    if (env->id_tlbs == 1)
304 76a66253 j_mayer
        max *= 2;
305 76a66253 j_mayer
    for (nr = 0; nr < max; nr++) {
306 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
307 76a66253 j_mayer
        pte_invalidate(&tlb->pte0);
308 76a66253 j_mayer
    }
309 76a66253 j_mayer
    tlb_flush(env, 1);
310 76a66253 j_mayer
}
311 76a66253 j_mayer
312 b068d6a7 j_mayer
static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
313 b068d6a7 j_mayer
                                                        target_ulong eaddr,
314 b068d6a7 j_mayer
                                                        int is_code,
315 b068d6a7 j_mayer
                                                        int match_epn)
316 76a66253 j_mayer
{
317 4a057712 j_mayer
#if !defined(FLUSH_ALL_TLBS)
318 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
319 76a66253 j_mayer
    int way, nr;
320 76a66253 j_mayer
321 76a66253 j_mayer
    /* Invalidate ITLB + DTLB, all ways */
322 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
323 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
324 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
325 76a66253 j_mayer
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
326 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
327 76a66253 j_mayer
            if (loglevel != 0) {
328 1b9eb036 j_mayer
                fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
329 76a66253 j_mayer
                        nr, env->nb_tlb, eaddr);
330 76a66253 j_mayer
            }
331 76a66253 j_mayer
#endif
332 76a66253 j_mayer
            pte_invalidate(&tlb->pte0);
333 76a66253 j_mayer
            tlb_flush_page(env, tlb->EPN);
334 76a66253 j_mayer
        }
335 76a66253 j_mayer
    }
336 76a66253 j_mayer
#else
337 76a66253 j_mayer
    /* XXX: PowerPC specification say this is valid as well */
338 76a66253 j_mayer
    ppc6xx_tlb_invalidate_all(env);
339 76a66253 j_mayer
#endif
340 76a66253 j_mayer
}
341 76a66253 j_mayer
342 daf4f96e j_mayer
static void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
343 daf4f96e j_mayer
                                        int is_code)
344 76a66253 j_mayer
{
345 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
346 76a66253 j_mayer
}
347 76a66253 j_mayer
348 76a66253 j_mayer
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
349 76a66253 j_mayer
                       target_ulong pte0, target_ulong pte1)
350 76a66253 j_mayer
{
351 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
352 76a66253 j_mayer
    int nr;
353 76a66253 j_mayer
354 76a66253 j_mayer
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
355 1d0a48fb j_mayer
    tlb = &env->tlb[nr].tlb6;
356 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
357 76a66253 j_mayer
    if (loglevel != 0) {
358 5fafdf24 ths
        fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
359 1b9eb036 j_mayer
                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
360 76a66253 j_mayer
    }
361 76a66253 j_mayer
#endif
362 76a66253 j_mayer
    /* Invalidate any pending reference in Qemu for this virtual address */
363 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
364 76a66253 j_mayer
    tlb->pte0 = pte0;
365 76a66253 j_mayer
    tlb->pte1 = pte1;
366 76a66253 j_mayer
    tlb->EPN = EPN;
367 76a66253 j_mayer
    /* Store last way for LRU mechanism */
368 76a66253 j_mayer
    env->last_way = way;
369 76a66253 j_mayer
}
370 76a66253 j_mayer
371 76a66253 j_mayer
static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
372 76a66253 j_mayer
                             target_ulong eaddr, int rw, int access_type)
373 76a66253 j_mayer
{
374 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
375 76a66253 j_mayer
    int nr, best, way;
376 76a66253 j_mayer
    int ret;
377 d9bce9d9 j_mayer
378 76a66253 j_mayer
    best = -1;
379 76a66253 j_mayer
    ret = -1; /* No TLB found */
380 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
381 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
382 76a66253 j_mayer
                               access_type == ACCESS_CODE ? 1 : 0);
383 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
384 76a66253 j_mayer
        /* This test "emulates" the PTE index match for hardware TLBs */
385 76a66253 j_mayer
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
386 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
387 76a66253 j_mayer
            if (loglevel != 0) {
388 1b9eb036 j_mayer
                fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
389 1b9eb036 j_mayer
                        "] <> " ADDRX "\n",
390 76a66253 j_mayer
                        nr, env->nb_tlb,
391 76a66253 j_mayer
                        pte_is_valid(tlb->pte0) ? "valid" : "inval",
392 76a66253 j_mayer
                        tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
393 76a66253 j_mayer
            }
394 76a66253 j_mayer
#endif
395 76a66253 j_mayer
            continue;
396 76a66253 j_mayer
        }
397 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
398 76a66253 j_mayer
        if (loglevel != 0) {
399 1b9eb036 j_mayer
            fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
400 1b9eb036 j_mayer
                    " %c %c\n",
401 76a66253 j_mayer
                    nr, env->nb_tlb,
402 76a66253 j_mayer
                    pte_is_valid(tlb->pte0) ? "valid" : "inval",
403 76a66253 j_mayer
                    tlb->EPN, eaddr, tlb->pte1,
404 76a66253 j_mayer
                    rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
405 76a66253 j_mayer
        }
406 76a66253 j_mayer
#endif
407 b227a8e9 j_mayer
        switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
408 76a66253 j_mayer
        case -3:
409 76a66253 j_mayer
            /* TLB inconsistency */
410 76a66253 j_mayer
            return -1;
411 76a66253 j_mayer
        case -2:
412 76a66253 j_mayer
            /* Access violation */
413 76a66253 j_mayer
            ret = -2;
414 76a66253 j_mayer
            best = nr;
415 76a66253 j_mayer
            break;
416 76a66253 j_mayer
        case -1:
417 76a66253 j_mayer
        default:
418 76a66253 j_mayer
            /* No match */
419 76a66253 j_mayer
            break;
420 76a66253 j_mayer
        case 0:
421 76a66253 j_mayer
            /* access granted */
422 76a66253 j_mayer
            /* XXX: we should go on looping to check all TLBs consistency
423 76a66253 j_mayer
             *      but we can speed-up the whole thing as the
424 76a66253 j_mayer
             *      result would be undefined if TLBs are not consistent.
425 76a66253 j_mayer
             */
426 76a66253 j_mayer
            ret = 0;
427 76a66253 j_mayer
            best = nr;
428 76a66253 j_mayer
            goto done;
429 76a66253 j_mayer
        }
430 76a66253 j_mayer
    }
431 76a66253 j_mayer
    if (best != -1) {
432 76a66253 j_mayer
    done:
433 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
434 4a057712 j_mayer
        if (loglevel != 0) {
435 76a66253 j_mayer
            fprintf(logfile, "found TLB at addr 0x%08lx prot=0x%01x ret=%d\n",
436 76a66253 j_mayer
                    ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
437 76a66253 j_mayer
        }
438 76a66253 j_mayer
#endif
439 76a66253 j_mayer
        /* Update page flags */
440 1d0a48fb j_mayer
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
441 76a66253 j_mayer
    }
442 76a66253 j_mayer
443 76a66253 j_mayer
    return ret;
444 76a66253 j_mayer
}
445 76a66253 j_mayer
446 9a64fbe4 bellard
/* Perform BAT hit & translation */
447 76a66253 j_mayer
static int get_bat (CPUState *env, mmu_ctx_t *ctx,
448 76a66253 j_mayer
                    target_ulong virtual, int rw, int type)
449 9a64fbe4 bellard
{
450 76a66253 j_mayer
    target_ulong *BATlt, *BATut, *BATu, *BATl;
451 76a66253 j_mayer
    target_ulong base, BEPIl, BEPIu, bl;
452 0411a972 j_mayer
    int i, pp, pr;
453 9a64fbe4 bellard
    int ret = -1;
454 9a64fbe4 bellard
455 9a64fbe4 bellard
#if defined (DEBUG_BATS)
456 4a057712 j_mayer
    if (loglevel != 0) {
457 1b9eb036 j_mayer
        fprintf(logfile, "%s: %cBAT v 0x" ADDRX "\n", __func__,
458 76a66253 j_mayer
                type == ACCESS_CODE ? 'I' : 'D', virtual);
459 9a64fbe4 bellard
    }
460 9a64fbe4 bellard
#endif
461 0411a972 j_mayer
    pr = msr_pr;
462 9a64fbe4 bellard
    switch (type) {
463 9a64fbe4 bellard
    case ACCESS_CODE:
464 9a64fbe4 bellard
        BATlt = env->IBAT[1];
465 9a64fbe4 bellard
        BATut = env->IBAT[0];
466 9a64fbe4 bellard
        break;
467 9a64fbe4 bellard
    default:
468 9a64fbe4 bellard
        BATlt = env->DBAT[1];
469 9a64fbe4 bellard
        BATut = env->DBAT[0];
470 9a64fbe4 bellard
        break;
471 9a64fbe4 bellard
    }
472 9a64fbe4 bellard
#if defined (DEBUG_BATS)
473 4a057712 j_mayer
    if (loglevel != 0) {
474 1b9eb036 j_mayer
        fprintf(logfile, "%s...: %cBAT v 0x" ADDRX "\n", __func__,
475 76a66253 j_mayer
                type == ACCESS_CODE ? 'I' : 'D', virtual);
476 9a64fbe4 bellard
    }
477 9a64fbe4 bellard
#endif
478 9a64fbe4 bellard
    base = virtual & 0xFFFC0000;
479 9a64fbe4 bellard
    for (i = 0; i < 4; i++) {
480 9a64fbe4 bellard
        BATu = &BATut[i];
481 9a64fbe4 bellard
        BATl = &BATlt[i];
482 9a64fbe4 bellard
        BEPIu = *BATu & 0xF0000000;
483 9a64fbe4 bellard
        BEPIl = *BATu & 0x0FFE0000;
484 9a64fbe4 bellard
        bl = (*BATu & 0x00001FFC) << 15;
485 9a64fbe4 bellard
#if defined (DEBUG_BATS)
486 4a057712 j_mayer
        if (loglevel != 0) {
487 5fafdf24 ths
            fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
488 1b9eb036 j_mayer
                    " BATl 0x" ADDRX "\n",
489 9a64fbe4 bellard
                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
490 9a64fbe4 bellard
                    *BATu, *BATl);
491 9a64fbe4 bellard
        }
492 9a64fbe4 bellard
#endif
493 9a64fbe4 bellard
        if ((virtual & 0xF0000000) == BEPIu &&
494 9a64fbe4 bellard
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
495 9a64fbe4 bellard
            /* BAT matches */
496 0411a972 j_mayer
            if (((pr == 0) && (*BATu & 0x00000002)) ||
497 0411a972 j_mayer
                ((pr != 0) && (*BATu & 0x00000001))) {
498 9a64fbe4 bellard
                /* Get physical address */
499 76a66253 j_mayer
                ctx->raddr = (*BATl & 0xF0000000) |
500 9a64fbe4 bellard
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
501 a541f297 bellard
                    (virtual & 0x0001F000);
502 b227a8e9 j_mayer
                /* Compute access rights */
503 b227a8e9 j_mayer
                pp = *BATl & 0x00000003;
504 b227a8e9 j_mayer
                ctx->prot = 0;
505 b227a8e9 j_mayer
                if (pp != 0) {
506 b227a8e9 j_mayer
                    ctx->prot = PAGE_READ | PAGE_EXEC;
507 b227a8e9 j_mayer
                    if (pp == 0x2)
508 b227a8e9 j_mayer
                        ctx->prot |= PAGE_WRITE;
509 b227a8e9 j_mayer
                }
510 b227a8e9 j_mayer
                ret = check_prot(ctx->prot, rw, type);
511 9a64fbe4 bellard
#if defined (DEBUG_BATS)
512 b227a8e9 j_mayer
                if (ret == 0 && loglevel != 0) {
513 4a057712 j_mayer
                    fprintf(logfile, "BAT %d match: r 0x" PADDRX
514 1b9eb036 j_mayer
                            " prot=%c%c\n",
515 76a66253 j_mayer
                            i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
516 76a66253 j_mayer
                            ctx->prot & PAGE_WRITE ? 'W' : '-');
517 9a64fbe4 bellard
                }
518 9a64fbe4 bellard
#endif
519 9a64fbe4 bellard
                break;
520 9a64fbe4 bellard
            }
521 9a64fbe4 bellard
        }
522 9a64fbe4 bellard
    }
523 9a64fbe4 bellard
    if (ret < 0) {
524 9a64fbe4 bellard
#if defined (DEBUG_BATS)
525 4a057712 j_mayer
        if (loglevel != 0) {
526 4a057712 j_mayer
            fprintf(logfile, "no BAT match for 0x" ADDRX ":\n", virtual);
527 4a057712 j_mayer
            for (i = 0; i < 4; i++) {
528 4a057712 j_mayer
                BATu = &BATut[i];
529 4a057712 j_mayer
                BATl = &BATlt[i];
530 4a057712 j_mayer
                BEPIu = *BATu & 0xF0000000;
531 4a057712 j_mayer
                BEPIl = *BATu & 0x0FFE0000;
532 4a057712 j_mayer
                bl = (*BATu & 0x00001FFC) << 15;
533 4a057712 j_mayer
                fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
534 4a057712 j_mayer
                        " BATl 0x" ADDRX " \n\t"
535 4a057712 j_mayer
                        "0x" ADDRX " 0x" ADDRX " 0x" ADDRX "\n",
536 4a057712 j_mayer
                        __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
537 4a057712 j_mayer
                        *BATu, *BATl, BEPIu, BEPIl, bl);
538 4a057712 j_mayer
            }
539 9a64fbe4 bellard
        }
540 9a64fbe4 bellard
#endif
541 9a64fbe4 bellard
    }
542 b227a8e9 j_mayer
543 9a64fbe4 bellard
    /* No hit */
544 9a64fbe4 bellard
    return ret;
545 9a64fbe4 bellard
}
546 9a64fbe4 bellard
547 9a64fbe4 bellard
/* PTE table lookup */
548 b227a8e9 j_mayer
static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
549 b227a8e9 j_mayer
                                    int rw, int type)
550 9a64fbe4 bellard
{
551 76a66253 j_mayer
    target_ulong base, pte0, pte1;
552 76a66253 j_mayer
    int i, good = -1;
553 caa4039c j_mayer
    int ret, r;
554 9a64fbe4 bellard
555 76a66253 j_mayer
    ret = -1; /* No entry found */
556 76a66253 j_mayer
    base = ctx->pg_addr[h];
557 9a64fbe4 bellard
    for (i = 0; i < 8; i++) {
558 caa4039c j_mayer
#if defined(TARGET_PPC64)
559 caa4039c j_mayer
        if (is_64b) {
560 caa4039c j_mayer
            pte0 = ldq_phys(base + (i * 16));
561 caa4039c j_mayer
            pte1 =  ldq_phys(base + (i * 16) + 8);
562 b227a8e9 j_mayer
            r = pte64_check(ctx, pte0, pte1, h, rw, type);
563 12de9a39 j_mayer
#if defined (DEBUG_MMU)
564 12de9a39 j_mayer
            if (loglevel != 0) {
565 12de9a39 j_mayer
                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
566 12de9a39 j_mayer
                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
567 12de9a39 j_mayer
                        base + (i * 16), pte0, pte1,
568 12de9a39 j_mayer
                        (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
569 12de9a39 j_mayer
                        ctx->ptem);
570 12de9a39 j_mayer
            }
571 12de9a39 j_mayer
#endif
572 caa4039c j_mayer
        } else
573 caa4039c j_mayer
#endif
574 caa4039c j_mayer
        {
575 caa4039c j_mayer
            pte0 = ldl_phys(base + (i * 8));
576 caa4039c j_mayer
            pte1 =  ldl_phys(base + (i * 8) + 4);
577 b227a8e9 j_mayer
            r = pte32_check(ctx, pte0, pte1, h, rw, type);
578 9a64fbe4 bellard
#if defined (DEBUG_MMU)
579 12de9a39 j_mayer
            if (loglevel != 0) {
580 12de9a39 j_mayer
                fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX
581 12de9a39 j_mayer
                        " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
582 12de9a39 j_mayer
                        base + (i * 8), pte0, pte1,
583 12de9a39 j_mayer
                        (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
584 12de9a39 j_mayer
                        ctx->ptem);
585 12de9a39 j_mayer
            }
586 9a64fbe4 bellard
#endif
587 12de9a39 j_mayer
        }
588 caa4039c j_mayer
        switch (r) {
589 76a66253 j_mayer
        case -3:
590 76a66253 j_mayer
            /* PTE inconsistency */
591 76a66253 j_mayer
            return -1;
592 76a66253 j_mayer
        case -2:
593 76a66253 j_mayer
            /* Access violation */
594 76a66253 j_mayer
            ret = -2;
595 76a66253 j_mayer
            good = i;
596 76a66253 j_mayer
            break;
597 76a66253 j_mayer
        case -1:
598 76a66253 j_mayer
        default:
599 76a66253 j_mayer
            /* No PTE match */
600 76a66253 j_mayer
            break;
601 76a66253 j_mayer
        case 0:
602 76a66253 j_mayer
            /* access granted */
603 76a66253 j_mayer
            /* XXX: we should go on looping to check all PTEs consistency
604 76a66253 j_mayer
             *      but if we can speed-up the whole thing as the
605 76a66253 j_mayer
             *      result would be undefined if PTEs are not consistent.
606 76a66253 j_mayer
             */
607 76a66253 j_mayer
            ret = 0;
608 76a66253 j_mayer
            good = i;
609 76a66253 j_mayer
            goto done;
610 9a64fbe4 bellard
        }
611 9a64fbe4 bellard
    }
612 9a64fbe4 bellard
    if (good != -1) {
613 76a66253 j_mayer
    done:
614 9a64fbe4 bellard
#if defined (DEBUG_MMU)
615 4a057712 j_mayer
        if (loglevel != 0) {
616 4a057712 j_mayer
            fprintf(logfile, "found PTE at addr 0x" PADDRX " prot=0x%01x "
617 1b9eb036 j_mayer
                    "ret=%d\n",
618 76a66253 j_mayer
                    ctx->raddr, ctx->prot, ret);
619 76a66253 j_mayer
        }
620 9a64fbe4 bellard
#endif
621 9a64fbe4 bellard
        /* Update page flags */
622 76a66253 j_mayer
        pte1 = ctx->raddr;
623 caa4039c j_mayer
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
624 caa4039c j_mayer
#if defined(TARGET_PPC64)
625 caa4039c j_mayer
            if (is_64b) {
626 caa4039c j_mayer
                stq_phys_notdirty(base + (good * 16) + 8, pte1);
627 caa4039c j_mayer
            } else
628 caa4039c j_mayer
#endif
629 caa4039c j_mayer
            {
630 caa4039c j_mayer
                stl_phys_notdirty(base + (good * 8) + 4, pte1);
631 caa4039c j_mayer
            }
632 caa4039c j_mayer
        }
633 9a64fbe4 bellard
    }
634 9a64fbe4 bellard
635 9a64fbe4 bellard
    return ret;
636 79aceca5 bellard
}
637 79aceca5 bellard
638 b227a8e9 j_mayer
static int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
639 caa4039c j_mayer
{
640 b227a8e9 j_mayer
    return _find_pte(ctx, 0, h, rw, type);
641 caa4039c j_mayer
}
642 caa4039c j_mayer
643 caa4039c j_mayer
#if defined(TARGET_PPC64)
644 b227a8e9 j_mayer
static int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
645 caa4039c j_mayer
{
646 b227a8e9 j_mayer
    return _find_pte(ctx, 1, h, rw, type);
647 caa4039c j_mayer
}
648 caa4039c j_mayer
#endif
649 caa4039c j_mayer
650 b068d6a7 j_mayer
static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
651 b227a8e9 j_mayer
                                   int h, int rw, int type)
652 caa4039c j_mayer
{
653 caa4039c j_mayer
#if defined(TARGET_PPC64)
654 12de9a39 j_mayer
    if (env->mmu_model == POWERPC_MMU_64B)
655 b227a8e9 j_mayer
        return find_pte64(ctx, h, rw, type);
656 caa4039c j_mayer
#endif
657 caa4039c j_mayer
658 b227a8e9 j_mayer
    return find_pte32(ctx, h, rw, type);
659 caa4039c j_mayer
}
660 caa4039c j_mayer
661 caa4039c j_mayer
#if defined(TARGET_PPC64)
662 eacc3249 j_mayer
static inline int slb_is_valid (uint64_t slb64)
663 eacc3249 j_mayer
{
664 eacc3249 j_mayer
    return slb64 & 0x0000000008000000ULL ? 1 : 0;
665 eacc3249 j_mayer
}
666 eacc3249 j_mayer
667 eacc3249 j_mayer
static inline void slb_invalidate (uint64_t *slb64)
668 eacc3249 j_mayer
{
669 eacc3249 j_mayer
    *slb64 &= ~0x0000000008000000ULL;
670 eacc3249 j_mayer
}
671 eacc3249 j_mayer
672 12de9a39 j_mayer
static int slb_lookup (CPUPPCState *env, target_ulong eaddr,
673 caa4039c j_mayer
                       target_ulong *vsid, target_ulong *page_mask, int *attr)
674 caa4039c j_mayer
{
675 caa4039c j_mayer
    target_phys_addr_t sr_base;
676 caa4039c j_mayer
    target_ulong mask;
677 caa4039c j_mayer
    uint64_t tmp64;
678 caa4039c j_mayer
    uint32_t tmp;
679 caa4039c j_mayer
    int n, ret;
680 caa4039c j_mayer
681 caa4039c j_mayer
    ret = -5;
682 caa4039c j_mayer
    sr_base = env->spr[SPR_ASR];
683 12de9a39 j_mayer
#if defined(DEBUG_SLB)
684 12de9a39 j_mayer
    if (loglevel != 0) {
685 12de9a39 j_mayer
        fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
686 12de9a39 j_mayer
                __func__, eaddr, sr_base);
687 12de9a39 j_mayer
    }
688 12de9a39 j_mayer
#endif
689 caa4039c j_mayer
    mask = 0x0000000000000000ULL; /* Avoid gcc warning */
690 eacc3249 j_mayer
    for (n = 0; n < env->slb_nr; n++) {
691 caa4039c j_mayer
        tmp64 = ldq_phys(sr_base);
692 12de9a39 j_mayer
        tmp = ldl_phys(sr_base + 8);
693 12de9a39 j_mayer
#if defined(DEBUG_SLB)
694 12de9a39 j_mayer
        if (loglevel != 0) {
695 b33c17e1 j_mayer
            fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
696 b33c17e1 j_mayer
                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
697 12de9a39 j_mayer
        }
698 12de9a39 j_mayer
#endif
699 eacc3249 j_mayer
        if (slb_is_valid(tmp64)) {
700 caa4039c j_mayer
            /* SLB entry is valid */
701 caa4039c j_mayer
            switch (tmp64 & 0x0000000006000000ULL) {
702 caa4039c j_mayer
            case 0x0000000000000000ULL:
703 caa4039c j_mayer
                /* 256 MB segment */
704 caa4039c j_mayer
                mask = 0xFFFFFFFFF0000000ULL;
705 caa4039c j_mayer
                break;
706 caa4039c j_mayer
            case 0x0000000002000000ULL:
707 caa4039c j_mayer
                /* 1 TB segment */
708 caa4039c j_mayer
                mask = 0xFFFF000000000000ULL;
709 caa4039c j_mayer
                break;
710 caa4039c j_mayer
            case 0x0000000004000000ULL:
711 caa4039c j_mayer
            case 0x0000000006000000ULL:
712 caa4039c j_mayer
                /* Reserved => segment is invalid */
713 caa4039c j_mayer
                continue;
714 caa4039c j_mayer
            }
715 caa4039c j_mayer
            if ((eaddr & mask) == (tmp64 & mask)) {
716 caa4039c j_mayer
                /* SLB match */
717 caa4039c j_mayer
                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
718 caa4039c j_mayer
                *page_mask = ~mask;
719 caa4039c j_mayer
                *attr = tmp & 0xFF;
720 eacc3249 j_mayer
                ret = n;
721 caa4039c j_mayer
                break;
722 caa4039c j_mayer
            }
723 caa4039c j_mayer
        }
724 caa4039c j_mayer
        sr_base += 12;
725 caa4039c j_mayer
    }
726 caa4039c j_mayer
727 caa4039c j_mayer
    return ret;
728 79aceca5 bellard
}
729 12de9a39 j_mayer
730 eacc3249 j_mayer
void ppc_slb_invalidate_all (CPUPPCState *env)
731 eacc3249 j_mayer
{
732 eacc3249 j_mayer
    target_phys_addr_t sr_base;
733 eacc3249 j_mayer
    uint64_t tmp64;
734 eacc3249 j_mayer
    int n, do_invalidate;
735 eacc3249 j_mayer
736 eacc3249 j_mayer
    do_invalidate = 0;
737 eacc3249 j_mayer
    sr_base = env->spr[SPR_ASR];
738 2c1ee068 j_mayer
    /* XXX: Warning: slbia never invalidates the first segment */
739 2c1ee068 j_mayer
    for (n = 1; n < env->slb_nr; n++) {
740 eacc3249 j_mayer
        tmp64 = ldq_phys(sr_base);
741 eacc3249 j_mayer
        if (slb_is_valid(tmp64)) {
742 eacc3249 j_mayer
            slb_invalidate(&tmp64);
743 eacc3249 j_mayer
            stq_phys(sr_base, tmp64);
744 eacc3249 j_mayer
            /* XXX: given the fact that segment size is 256 MB or 1TB,
745 eacc3249 j_mayer
             *      and we still don't have a tlb_flush_mask(env, n, mask)
746 eacc3249 j_mayer
             *      in Qemu, we just invalidate all TLBs
747 eacc3249 j_mayer
             */
748 eacc3249 j_mayer
            do_invalidate = 1;
749 eacc3249 j_mayer
        }
750 eacc3249 j_mayer
        sr_base += 12;
751 eacc3249 j_mayer
    }
752 eacc3249 j_mayer
    if (do_invalidate)
753 eacc3249 j_mayer
        tlb_flush(env, 1);
754 eacc3249 j_mayer
}
755 eacc3249 j_mayer
756 eacc3249 j_mayer
void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
757 eacc3249 j_mayer
{
758 eacc3249 j_mayer
    target_phys_addr_t sr_base;
759 eacc3249 j_mayer
    target_ulong vsid, page_mask;
760 eacc3249 j_mayer
    uint64_t tmp64;
761 eacc3249 j_mayer
    int attr;
762 eacc3249 j_mayer
    int n;
763 eacc3249 j_mayer
764 eacc3249 j_mayer
    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
765 eacc3249 j_mayer
    if (n >= 0) {
766 eacc3249 j_mayer
        sr_base = env->spr[SPR_ASR];
767 eacc3249 j_mayer
        sr_base += 12 * n;
768 eacc3249 j_mayer
        tmp64 = ldq_phys(sr_base);
769 eacc3249 j_mayer
        if (slb_is_valid(tmp64)) {
770 eacc3249 j_mayer
            slb_invalidate(&tmp64);
771 eacc3249 j_mayer
            stq_phys(sr_base, tmp64);
772 eacc3249 j_mayer
            /* XXX: given the fact that segment size is 256 MB or 1TB,
773 eacc3249 j_mayer
             *      and we still don't have a tlb_flush_mask(env, n, mask)
774 eacc3249 j_mayer
             *      in Qemu, we just invalidate all TLBs
775 eacc3249 j_mayer
             */
776 eacc3249 j_mayer
            tlb_flush(env, 1);
777 eacc3249 j_mayer
        }
778 eacc3249 j_mayer
    }
779 eacc3249 j_mayer
}
780 eacc3249 j_mayer
781 12de9a39 j_mayer
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
782 12de9a39 j_mayer
{
783 12de9a39 j_mayer
    target_phys_addr_t sr_base;
784 12de9a39 j_mayer
    target_ulong rt;
785 12de9a39 j_mayer
    uint64_t tmp64;
786 12de9a39 j_mayer
    uint32_t tmp;
787 12de9a39 j_mayer
788 12de9a39 j_mayer
    sr_base = env->spr[SPR_ASR];
789 12de9a39 j_mayer
    sr_base += 12 * slb_nr;
790 12de9a39 j_mayer
    tmp64 = ldq_phys(sr_base);
791 12de9a39 j_mayer
    tmp = ldl_phys(sr_base + 8);
792 12de9a39 j_mayer
    if (tmp64 & 0x0000000008000000ULL) {
793 12de9a39 j_mayer
        /* SLB entry is valid */
794 12de9a39 j_mayer
        /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
795 12de9a39 j_mayer
        rt = tmp >> 8;             /* 65:88 => 40:63 */
796 12de9a39 j_mayer
        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
797 12de9a39 j_mayer
        /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
798 12de9a39 j_mayer
        rt |= ((tmp >> 4) & 0xF) << 27;
799 12de9a39 j_mayer
    } else {
800 12de9a39 j_mayer
        rt = 0;
801 12de9a39 j_mayer
    }
802 12de9a39 j_mayer
#if defined(DEBUG_SLB)
803 12de9a39 j_mayer
    if (loglevel != 0) {
804 12de9a39 j_mayer
        fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
805 12de9a39 j_mayer
                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
806 12de9a39 j_mayer
    }
807 12de9a39 j_mayer
#endif
808 12de9a39 j_mayer
809 12de9a39 j_mayer
    return rt;
810 12de9a39 j_mayer
}
811 12de9a39 j_mayer
812 12de9a39 j_mayer
void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
813 12de9a39 j_mayer
{
814 12de9a39 j_mayer
    target_phys_addr_t sr_base;
815 12de9a39 j_mayer
    uint64_t tmp64;
816 12de9a39 j_mayer
    uint32_t tmp;
817 12de9a39 j_mayer
818 12de9a39 j_mayer
    sr_base = env->spr[SPR_ASR];
819 12de9a39 j_mayer
    sr_base += 12 * slb_nr;
820 12de9a39 j_mayer
    /* Copy Rs bits 37:63 to SLB 62:88 */
821 12de9a39 j_mayer
    tmp = rs << 8;
822 12de9a39 j_mayer
    tmp64 = (rs >> 24) & 0x7;
823 12de9a39 j_mayer
    /* Copy Rs bits 33:36 to SLB 89:92 */
824 12de9a39 j_mayer
    tmp |= ((rs >> 27) & 0xF) << 4;
825 12de9a39 j_mayer
    /* Set the valid bit */
826 12de9a39 j_mayer
    tmp64 |= 1 << 27;
827 12de9a39 j_mayer
    /* Set ESID */
828 12de9a39 j_mayer
    tmp64 |= (uint32_t)slb_nr << 28;
829 12de9a39 j_mayer
#if defined(DEBUG_SLB)
830 12de9a39 j_mayer
    if (loglevel != 0) {
831 12de9a39 j_mayer
        fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64 " %08"
832 12de9a39 j_mayer
                PRIx32 "\n", __func__, slb_nr, rs, sr_base, tmp64, tmp);
833 12de9a39 j_mayer
    }
834 12de9a39 j_mayer
#endif
835 12de9a39 j_mayer
    /* Write SLB entry to memory */
836 12de9a39 j_mayer
    stq_phys(sr_base, tmp64);
837 12de9a39 j_mayer
    stl_phys(sr_base + 8, tmp);
838 12de9a39 j_mayer
}
839 caa4039c j_mayer
#endif /* defined(TARGET_PPC64) */
840 79aceca5 bellard
841 9a64fbe4 bellard
/* Perform segment based translation */
842 b068d6a7 j_mayer
static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
843 b068d6a7 j_mayer
                                                    int sdr_sh,
844 b068d6a7 j_mayer
                                                    target_phys_addr_t hash,
845 b068d6a7 j_mayer
                                                    target_phys_addr_t mask)
846 12de9a39 j_mayer
{
847 12de9a39 j_mayer
    return (sdr1 & ((target_ulong)(-1ULL) << sdr_sh)) | (hash & mask);
848 12de9a39 j_mayer
}
849 12de9a39 j_mayer
850 76a66253 j_mayer
static int get_segment (CPUState *env, mmu_ctx_t *ctx,
851 76a66253 j_mayer
                        target_ulong eaddr, int rw, int type)
852 79aceca5 bellard
{
853 12de9a39 j_mayer
    target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
854 caa4039c j_mayer
    target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
855 caa4039c j_mayer
#if defined(TARGET_PPC64)
856 caa4039c j_mayer
    int attr;
857 9a64fbe4 bellard
#endif
858 0411a972 j_mayer
    int ds, vsid_sh, sdr_sh, pr;
859 caa4039c j_mayer
    int ret, ret2;
860 caa4039c j_mayer
861 0411a972 j_mayer
    pr = msr_pr;
862 caa4039c j_mayer
#if defined(TARGET_PPC64)
863 12de9a39 j_mayer
    if (env->mmu_model == POWERPC_MMU_64B) {
864 12de9a39 j_mayer
#if defined (DEBUG_MMU)
865 12de9a39 j_mayer
        if (loglevel != 0) {
866 12de9a39 j_mayer
            fprintf(logfile, "Check SLBs\n");
867 12de9a39 j_mayer
        }
868 12de9a39 j_mayer
#endif
869 caa4039c j_mayer
        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
870 caa4039c j_mayer
        if (ret < 0)
871 caa4039c j_mayer
            return ret;
872 0411a972 j_mayer
        ctx->key = ((attr & 0x40) && (pr != 0)) ||
873 0411a972 j_mayer
            ((attr & 0x80) && (pr == 0)) ? 1 : 0;
874 caa4039c j_mayer
        ds = 0;
875 b227a8e9 j_mayer
        ctx->nx = attr & 0x20 ? 1 : 0;
876 caa4039c j_mayer
        vsid_mask = 0x00003FFFFFFFFF80ULL;
877 caa4039c j_mayer
        vsid_sh = 7;
878 caa4039c j_mayer
        sdr_sh = 18;
879 caa4039c j_mayer
        sdr_mask = 0x3FF80;
880 caa4039c j_mayer
    } else
881 caa4039c j_mayer
#endif /* defined(TARGET_PPC64) */
882 caa4039c j_mayer
    {
883 caa4039c j_mayer
        sr = env->sr[eaddr >> 28];
884 caa4039c j_mayer
        page_mask = 0x0FFFFFFF;
885 0411a972 j_mayer
        ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
886 0411a972 j_mayer
                    ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
887 caa4039c j_mayer
        ds = sr & 0x80000000 ? 1 : 0;
888 b227a8e9 j_mayer
        ctx->nx = sr & 0x10000000 ? 1 : 0;
889 caa4039c j_mayer
        vsid = sr & 0x00FFFFFF;
890 caa4039c j_mayer
        vsid_mask = 0x01FFFFC0;
891 caa4039c j_mayer
        vsid_sh = 6;
892 caa4039c j_mayer
        sdr_sh = 16;
893 caa4039c j_mayer
        sdr_mask = 0xFFC0;
894 9a64fbe4 bellard
#if defined (DEBUG_MMU)
895 caa4039c j_mayer
        if (loglevel != 0) {
896 caa4039c j_mayer
            fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX
897 caa4039c j_mayer
                    " nip=0x" ADDRX " lr=0x" ADDRX
898 caa4039c j_mayer
                    " ir=%d dr=%d pr=%d %d t=%d\n",
899 caa4039c j_mayer
                    eaddr, (int)(eaddr >> 28), sr, env->nip,
900 0411a972 j_mayer
                    env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,
901 0411a972 j_mayer
                    rw, type);
902 caa4039c j_mayer
        }
903 9a64fbe4 bellard
#endif
904 caa4039c j_mayer
    }
905 12de9a39 j_mayer
#if defined (DEBUG_MMU)
906 12de9a39 j_mayer
    if (loglevel != 0) {
907 12de9a39 j_mayer
        fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
908 b227a8e9 j_mayer
                ctx->key, ds, ctx->nx, vsid);
909 12de9a39 j_mayer
    }
910 12de9a39 j_mayer
#endif
911 caa4039c j_mayer
    ret = -1;
912 caa4039c j_mayer
    if (!ds) {
913 9a64fbe4 bellard
        /* Check if instruction fetch is allowed, if needed */
914 b227a8e9 j_mayer
        if (type != ACCESS_CODE || ctx->nx == 0) {
915 9a64fbe4 bellard
            /* Page address translation */
916 76a66253 j_mayer
            /* Primary table address */
917 76a66253 j_mayer
            sdr = env->sdr1;
918 12de9a39 j_mayer
            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
919 12de9a39 j_mayer
#if defined(TARGET_PPC64)
920 12de9a39 j_mayer
            if (env->mmu_model == POWERPC_MMU_64B) {
921 12de9a39 j_mayer
                htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
922 12de9a39 j_mayer
                /* XXX: this is false for 1 TB segments */
923 12de9a39 j_mayer
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
924 12de9a39 j_mayer
            } else
925 12de9a39 j_mayer
#endif
926 12de9a39 j_mayer
            {
927 12de9a39 j_mayer
                htab_mask = sdr & 0x000001FF;
928 12de9a39 j_mayer
                hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
929 12de9a39 j_mayer
            }
930 12de9a39 j_mayer
            mask = (htab_mask << sdr_sh) | sdr_mask;
931 12de9a39 j_mayer
#if defined (DEBUG_MMU)
932 12de9a39 j_mayer
            if (loglevel != 0) {
933 12de9a39 j_mayer
                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
934 12de9a39 j_mayer
                        PADDRX " " ADDRX "\n", sdr, sdr_sh, hash, mask,
935 12de9a39 j_mayer
                        page_mask);
936 12de9a39 j_mayer
            }
937 12de9a39 j_mayer
#endif
938 caa4039c j_mayer
            ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
939 76a66253 j_mayer
            /* Secondary table address */
940 caa4039c j_mayer
            hash = (~hash) & vsid_mask;
941 12de9a39 j_mayer
#if defined (DEBUG_MMU)
942 12de9a39 j_mayer
            if (loglevel != 0) {
943 12de9a39 j_mayer
                fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX " mask "
944 12de9a39 j_mayer
                        PADDRX "\n", sdr, sdr_sh, hash, mask);
945 12de9a39 j_mayer
            }
946 12de9a39 j_mayer
#endif
947 caa4039c j_mayer
            ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
948 caa4039c j_mayer
#if defined(TARGET_PPC64)
949 12de9a39 j_mayer
            if (env->mmu_model == POWERPC_MMU_64B) {
950 caa4039c j_mayer
                /* Only 5 bits of the page index are used in the AVPN */
951 caa4039c j_mayer
                ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
952 caa4039c j_mayer
            } else
953 caa4039c j_mayer
#endif
954 caa4039c j_mayer
            {
955 caa4039c j_mayer
                ctx->ptem = (vsid << 7) | (pgidx >> 10);
956 caa4039c j_mayer
            }
957 76a66253 j_mayer
            /* Initialize real address with an invalid value */
958 76a66253 j_mayer
            ctx->raddr = (target_ulong)-1;
959 7dbe11ac j_mayer
            if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
960 7dbe11ac j_mayer
                         env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
961 76a66253 j_mayer
                /* Software TLB search */
962 76a66253 j_mayer
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
963 76a66253 j_mayer
            } else {
964 9a64fbe4 bellard
#if defined (DEBUG_MMU)
965 4a057712 j_mayer
                if (loglevel != 0) {
966 4a057712 j_mayer
                    fprintf(logfile, "0 sdr1=0x" PADDRX " vsid=0x%06x "
967 4a057712 j_mayer
                            "api=0x%04x hash=0x%07x pg_addr=0x" PADDRX "\n",
968 4a057712 j_mayer
                            sdr, (uint32_t)vsid, (uint32_t)pgidx,
969 4a057712 j_mayer
                            (uint32_t)hash, ctx->pg_addr[0]);
970 76a66253 j_mayer
                }
971 9a64fbe4 bellard
#endif
972 76a66253 j_mayer
                /* Primary table lookup */
973 b227a8e9 j_mayer
                ret = find_pte(env, ctx, 0, rw, type);
974 76a66253 j_mayer
                if (ret < 0) {
975 76a66253 j_mayer
                    /* Secondary table lookup */
976 9a64fbe4 bellard
#if defined (DEBUG_MMU)
977 4a057712 j_mayer
                    if (eaddr != 0xEFFFFFFF && loglevel != 0) {
978 76a66253 j_mayer
                        fprintf(logfile,
979 4a057712 j_mayer
                                "1 sdr1=0x" PADDRX " vsid=0x%06x api=0x%04x "
980 4a057712 j_mayer
                                "hash=0x%05x pg_addr=0x" PADDRX "\n",
981 4a057712 j_mayer
                                sdr, (uint32_t)vsid, (uint32_t)pgidx,
982 4a057712 j_mayer
                                (uint32_t)hash, ctx->pg_addr[1]);
983 76a66253 j_mayer
                    }
984 9a64fbe4 bellard
#endif
985 b227a8e9 j_mayer
                    ret2 = find_pte(env, ctx, 1, rw, type);
986 76a66253 j_mayer
                    if (ret2 != -1)
987 76a66253 j_mayer
                        ret = ret2;
988 76a66253 j_mayer
                }
989 9a64fbe4 bellard
            }
990 0411a972 j_mayer
#if defined (DUMP_PAGE_TABLES)
991 b33c17e1 j_mayer
            if (loglevel != 0) {
992 b33c17e1 j_mayer
                target_phys_addr_t curaddr;
993 b33c17e1 j_mayer
                uint32_t a0, a1, a2, a3;
994 b33c17e1 j_mayer
                fprintf(logfile,
995 b33c17e1 j_mayer
                        "Page table: " PADDRX " len " PADDRX "\n",
996 b33c17e1 j_mayer
                        sdr, mask + 0x80);
997 b33c17e1 j_mayer
                for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
998 b33c17e1 j_mayer
                     curaddr += 16) {
999 b33c17e1 j_mayer
                    a0 = ldl_phys(curaddr);
1000 b33c17e1 j_mayer
                    a1 = ldl_phys(curaddr + 4);
1001 b33c17e1 j_mayer
                    a2 = ldl_phys(curaddr + 8);
1002 b33c17e1 j_mayer
                    a3 = ldl_phys(curaddr + 12);
1003 b33c17e1 j_mayer
                    if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
1004 12de9a39 j_mayer
                        fprintf(logfile,
1005 b33c17e1 j_mayer
                                PADDRX ": %08x %08x %08x %08x\n",
1006 b33c17e1 j_mayer
                                curaddr, a0, a1, a2, a3);
1007 12de9a39 j_mayer
                    }
1008 b33c17e1 j_mayer
                }
1009 b33c17e1 j_mayer
            }
1010 12de9a39 j_mayer
#endif
1011 9a64fbe4 bellard
        } else {
1012 9a64fbe4 bellard
#if defined (DEBUG_MMU)
1013 4a057712 j_mayer
            if (loglevel != 0)
1014 76a66253 j_mayer
                fprintf(logfile, "No access allowed\n");
1015 9a64fbe4 bellard
#endif
1016 76a66253 j_mayer
            ret = -3;
1017 9a64fbe4 bellard
        }
1018 9a64fbe4 bellard
    } else {
1019 9a64fbe4 bellard
#if defined (DEBUG_MMU)
1020 4a057712 j_mayer
        if (loglevel != 0)
1021 76a66253 j_mayer
            fprintf(logfile, "direct store...\n");
1022 9a64fbe4 bellard
#endif
1023 9a64fbe4 bellard
        /* Direct-store segment : absolutely *BUGGY* for now */
1024 9a64fbe4 bellard
        switch (type) {
1025 9a64fbe4 bellard
        case ACCESS_INT:
1026 9a64fbe4 bellard
            /* Integer load/store : only access allowed */
1027 9a64fbe4 bellard
            break;
1028 9a64fbe4 bellard
        case ACCESS_CODE:
1029 9a64fbe4 bellard
            /* No code fetch is allowed in direct-store areas */
1030 9a64fbe4 bellard
            return -4;
1031 9a64fbe4 bellard
        case ACCESS_FLOAT:
1032 9a64fbe4 bellard
            /* Floating point load/store */
1033 9a64fbe4 bellard
            return -4;
1034 9a64fbe4 bellard
        case ACCESS_RES:
1035 9a64fbe4 bellard
            /* lwarx, ldarx or srwcx. */
1036 9a64fbe4 bellard
            return -4;
1037 9a64fbe4 bellard
        case ACCESS_CACHE:
1038 9a64fbe4 bellard
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1039 9a64fbe4 bellard
            /* Should make the instruction do no-op.
1040 9a64fbe4 bellard
             * As it already do no-op, it's quite easy :-)
1041 9a64fbe4 bellard
             */
1042 76a66253 j_mayer
            ctx->raddr = eaddr;
1043 9a64fbe4 bellard
            return 0;
1044 9a64fbe4 bellard
        case ACCESS_EXT:
1045 9a64fbe4 bellard
            /* eciwx or ecowx */
1046 9a64fbe4 bellard
            return -4;
1047 9a64fbe4 bellard
        default:
1048 9a64fbe4 bellard
            if (logfile) {
1049 9a64fbe4 bellard
                fprintf(logfile, "ERROR: instruction should not need "
1050 9a64fbe4 bellard
                        "address translation\n");
1051 9a64fbe4 bellard
            }
1052 9a64fbe4 bellard
            return -4;
1053 9a64fbe4 bellard
        }
1054 76a66253 j_mayer
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1055 76a66253 j_mayer
            ctx->raddr = eaddr;
1056 9a64fbe4 bellard
            ret = 2;
1057 9a64fbe4 bellard
        } else {
1058 9a64fbe4 bellard
            ret = -2;
1059 9a64fbe4 bellard
        }
1060 79aceca5 bellard
    }
1061 9a64fbe4 bellard
1062 9a64fbe4 bellard
    return ret;
1063 79aceca5 bellard
}
1064 79aceca5 bellard
1065 c294fc58 j_mayer
/* Generic TLB check function for embedded PowerPC implementations */
1066 c294fc58 j_mayer
static int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
1067 c294fc58 j_mayer
                             target_phys_addr_t *raddrp,
1068 36081602 j_mayer
                             target_ulong address,
1069 36081602 j_mayer
                             uint32_t pid, int ext, int i)
1070 c294fc58 j_mayer
{
1071 c294fc58 j_mayer
    target_ulong mask;
1072 c294fc58 j_mayer
1073 c294fc58 j_mayer
    /* Check valid flag */
1074 c294fc58 j_mayer
    if (!(tlb->prot & PAGE_VALID)) {
1075 c294fc58 j_mayer
        if (loglevel != 0)
1076 c294fc58 j_mayer
            fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
1077 c294fc58 j_mayer
        return -1;
1078 c294fc58 j_mayer
    }
1079 c294fc58 j_mayer
    mask = ~(tlb->size - 1);
1080 daf4f96e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
1081 c294fc58 j_mayer
    if (loglevel != 0) {
1082 c294fc58 j_mayer
        fprintf(logfile, "%s: TLB %d address " ADDRX " PID %d <=> "
1083 c294fc58 j_mayer
                ADDRX " " ADDRX " %d\n",
1084 36081602 j_mayer
                __func__, i, address, pid, tlb->EPN, mask, (int)tlb->PID);
1085 c294fc58 j_mayer
    }
1086 daf4f96e j_mayer
#endif
1087 c294fc58 j_mayer
    /* Check PID */
1088 36081602 j_mayer
    if (tlb->PID != 0 && tlb->PID != pid)
1089 c294fc58 j_mayer
        return -1;
1090 c294fc58 j_mayer
    /* Check effective address */
1091 c294fc58 j_mayer
    if ((address & mask) != tlb->EPN)
1092 c294fc58 j_mayer
        return -1;
1093 c294fc58 j_mayer
    *raddrp = (tlb->RPN & mask) | (address & ~mask);
1094 9706285b j_mayer
#if (TARGET_PHYS_ADDR_BITS >= 36)
1095 36081602 j_mayer
    if (ext) {
1096 36081602 j_mayer
        /* Extend the physical address to 36 bits */
1097 36081602 j_mayer
        *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1098 36081602 j_mayer
    }
1099 9706285b j_mayer
#endif
1100 c294fc58 j_mayer
1101 c294fc58 j_mayer
    return 0;
1102 c294fc58 j_mayer
}
1103 c294fc58 j_mayer
1104 c294fc58 j_mayer
/* Generic TLB search function for PowerPC embedded implementations */
1105 36081602 j_mayer
int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1106 c294fc58 j_mayer
{
1107 c294fc58 j_mayer
    ppcemb_tlb_t *tlb;
1108 c294fc58 j_mayer
    target_phys_addr_t raddr;
1109 c294fc58 j_mayer
    int i, ret;
1110 c294fc58 j_mayer
1111 c294fc58 j_mayer
    /* Default return value is no match */
1112 c294fc58 j_mayer
    ret = -1;
1113 a750fc0b j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1114 c294fc58 j_mayer
        tlb = &env->tlb[i].tlbe;
1115 36081602 j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1116 c294fc58 j_mayer
            ret = i;
1117 c294fc58 j_mayer
            break;
1118 c294fc58 j_mayer
        }
1119 c294fc58 j_mayer
    }
1120 c294fc58 j_mayer
1121 c294fc58 j_mayer
    return ret;
1122 c294fc58 j_mayer
}
1123 c294fc58 j_mayer
1124 daf4f96e j_mayer
/* Helpers specific to PowerPC 40x implementations */
1125 daf4f96e j_mayer
static void ppc4xx_tlb_invalidate_all (CPUState *env)
1126 a750fc0b j_mayer
{
1127 a750fc0b j_mayer
    ppcemb_tlb_t *tlb;
1128 a750fc0b j_mayer
    int i;
1129 a750fc0b j_mayer
1130 a750fc0b j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1131 a750fc0b j_mayer
        tlb = &env->tlb[i].tlbe;
1132 daf4f96e j_mayer
        tlb->prot &= ~PAGE_VALID;
1133 a750fc0b j_mayer
    }
1134 daf4f96e j_mayer
    tlb_flush(env, 1);
1135 a750fc0b j_mayer
}
1136 a750fc0b j_mayer
1137 daf4f96e j_mayer
static void ppc4xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
1138 daf4f96e j_mayer
                                        uint32_t pid)
1139 0a032cbe j_mayer
{
1140 daf4f96e j_mayer
#if !defined(FLUSH_ALL_TLBS)
1141 0a032cbe j_mayer
    ppcemb_tlb_t *tlb;
1142 daf4f96e j_mayer
    target_phys_addr_t raddr;
1143 daf4f96e j_mayer
    target_ulong page, end;
1144 0a032cbe j_mayer
    int i;
1145 0a032cbe j_mayer
1146 0a032cbe j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1147 0a032cbe j_mayer
        tlb = &env->tlb[i].tlbe;
1148 daf4f96e j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1149 0a032cbe j_mayer
            end = tlb->EPN + tlb->size;
1150 0a032cbe j_mayer
            for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1151 0a032cbe j_mayer
                tlb_flush_page(env, page);
1152 0a032cbe j_mayer
            tlb->prot &= ~PAGE_VALID;
1153 daf4f96e j_mayer
            break;
1154 0a032cbe j_mayer
        }
1155 0a032cbe j_mayer
    }
1156 daf4f96e j_mayer
#else
1157 daf4f96e j_mayer
    ppc4xx_tlb_invalidate_all(env);
1158 daf4f96e j_mayer
#endif
1159 0a032cbe j_mayer
}
1160 0a032cbe j_mayer
1161 36081602 j_mayer
int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1162 e96efcfc j_mayer
                                 target_ulong address, int rw, int access_type)
1163 a8dea12f j_mayer
{
1164 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
1165 a8dea12f j_mayer
    target_phys_addr_t raddr;
1166 0411a972 j_mayer
    int i, ret, zsel, zpr, pr;
1167 3b46e624 ths
1168 c55e9aef j_mayer
    ret = -1;
1169 c55e9aef j_mayer
    raddr = -1;
1170 0411a972 j_mayer
    pr = msr_pr;
1171 a8dea12f j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1172 a8dea12f j_mayer
        tlb = &env->tlb[i].tlbe;
1173 36081602 j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1174 36081602 j_mayer
                             env->spr[SPR_40x_PID], 0, i) < 0)
1175 a8dea12f j_mayer
            continue;
1176 a8dea12f j_mayer
        zsel = (tlb->attr >> 4) & 0xF;
1177 a8dea12f j_mayer
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
1178 daf4f96e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
1179 4a057712 j_mayer
        if (loglevel != 0) {
1180 a8dea12f j_mayer
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1181 a8dea12f j_mayer
                    __func__, i, zsel, zpr, rw, tlb->attr);
1182 a8dea12f j_mayer
        }
1183 daf4f96e j_mayer
#endif
1184 b227a8e9 j_mayer
        /* Check execute enable bit */
1185 b227a8e9 j_mayer
        switch (zpr) {
1186 b227a8e9 j_mayer
        case 0x2:
1187 0411a972 j_mayer
            if (pr != 0)
1188 b227a8e9 j_mayer
                goto check_perms;
1189 b227a8e9 j_mayer
            /* No break here */
1190 b227a8e9 j_mayer
        case 0x3:
1191 b227a8e9 j_mayer
            /* All accesses granted */
1192 b227a8e9 j_mayer
            ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1193 b227a8e9 j_mayer
            ret = 0;
1194 b227a8e9 j_mayer
            break;
1195 b227a8e9 j_mayer
        case 0x0:
1196 0411a972 j_mayer
            if (pr != 0) {
1197 b227a8e9 j_mayer
                ctx->prot = 0;
1198 b227a8e9 j_mayer
                ret = -2;
1199 a8dea12f j_mayer
                break;
1200 a8dea12f j_mayer
            }
1201 b227a8e9 j_mayer
            /* No break here */
1202 b227a8e9 j_mayer
        case 0x1:
1203 b227a8e9 j_mayer
        check_perms:
1204 b227a8e9 j_mayer
            /* Check from TLB entry */
1205 b227a8e9 j_mayer
            /* XXX: there is a problem here or in the TLB fill code... */
1206 b227a8e9 j_mayer
            ctx->prot = tlb->prot;
1207 b227a8e9 j_mayer
            ctx->prot |= PAGE_EXEC;
1208 b227a8e9 j_mayer
            ret = check_prot(ctx->prot, rw, access_type);
1209 b227a8e9 j_mayer
            break;
1210 a8dea12f j_mayer
        }
1211 a8dea12f j_mayer
        if (ret >= 0) {
1212 a8dea12f j_mayer
            ctx->raddr = raddr;
1213 daf4f96e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
1214 4a057712 j_mayer
            if (loglevel != 0) {
1215 a8dea12f j_mayer
                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
1216 c55e9aef j_mayer
                        " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1217 c55e9aef j_mayer
                        ret);
1218 a8dea12f j_mayer
            }
1219 daf4f96e j_mayer
#endif
1220 c55e9aef j_mayer
            return 0;
1221 a8dea12f j_mayer
        }
1222 a8dea12f j_mayer
    }
1223 daf4f96e j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
1224 4a057712 j_mayer
    if (loglevel != 0) {
1225 c55e9aef j_mayer
        fprintf(logfile, "%s: access refused " ADDRX " => " REGX
1226 c55e9aef j_mayer
                " %d %d\n", __func__, address, raddr, ctx->prot,
1227 c55e9aef j_mayer
                ret);
1228 c55e9aef j_mayer
    }
1229 daf4f96e j_mayer
#endif
1230 3b46e624 ths
1231 a8dea12f j_mayer
    return ret;
1232 a8dea12f j_mayer
}
1233 a8dea12f j_mayer
1234 c294fc58 j_mayer
void store_40x_sler (CPUPPCState *env, uint32_t val)
1235 c294fc58 j_mayer
{
1236 c294fc58 j_mayer
    /* XXX: TO BE FIXED */
1237 c294fc58 j_mayer
    if (val != 0x00000000) {
1238 c294fc58 j_mayer
        cpu_abort(env, "Little-endian regions are not supported by now\n");
1239 c294fc58 j_mayer
    }
1240 c294fc58 j_mayer
    env->spr[SPR_405_SLER] = val;
1241 c294fc58 j_mayer
}
1242 c294fc58 j_mayer
1243 5eb7995e j_mayer
int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1244 5eb7995e j_mayer
                                   target_ulong address, int rw,
1245 5eb7995e j_mayer
                                   int access_type)
1246 5eb7995e j_mayer
{
1247 5eb7995e j_mayer
    ppcemb_tlb_t *tlb;
1248 5eb7995e j_mayer
    target_phys_addr_t raddr;
1249 5eb7995e j_mayer
    int i, prot, ret;
1250 5eb7995e j_mayer
1251 5eb7995e j_mayer
    ret = -1;
1252 5eb7995e j_mayer
    raddr = -1;
1253 5eb7995e j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
1254 5eb7995e j_mayer
        tlb = &env->tlb[i].tlbe;
1255 5eb7995e j_mayer
        if (ppcemb_tlb_check(env, tlb, &raddr, address,
1256 5eb7995e j_mayer
                             env->spr[SPR_BOOKE_PID], 1, i) < 0)
1257 5eb7995e j_mayer
            continue;
1258 0411a972 j_mayer
        if (msr_pr != 0)
1259 5eb7995e j_mayer
            prot = tlb->prot & 0xF;
1260 5eb7995e j_mayer
        else
1261 5eb7995e j_mayer
            prot = (tlb->prot >> 4) & 0xF;
1262 5eb7995e j_mayer
        /* Check the address space */
1263 5eb7995e j_mayer
        if (access_type == ACCESS_CODE) {
1264 d26bfc9a j_mayer
            if (msr_ir != (tlb->attr & 1))
1265 5eb7995e j_mayer
                continue;
1266 5eb7995e j_mayer
            ctx->prot = prot;
1267 5eb7995e j_mayer
            if (prot & PAGE_EXEC) {
1268 5eb7995e j_mayer
                ret = 0;
1269 5eb7995e j_mayer
                break;
1270 5eb7995e j_mayer
            }
1271 5eb7995e j_mayer
            ret = -3;
1272 5eb7995e j_mayer
        } else {
1273 d26bfc9a j_mayer
            if (msr_dr != (tlb->attr & 1))
1274 5eb7995e j_mayer
                continue;
1275 5eb7995e j_mayer
            ctx->prot = prot;
1276 5eb7995e j_mayer
            if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1277 5eb7995e j_mayer
                ret = 0;
1278 5eb7995e j_mayer
                break;
1279 5eb7995e j_mayer
            }
1280 5eb7995e j_mayer
            ret = -2;
1281 5eb7995e j_mayer
        }
1282 5eb7995e j_mayer
    }
1283 5eb7995e j_mayer
    if (ret >= 0)
1284 5eb7995e j_mayer
        ctx->raddr = raddr;
1285 5eb7995e j_mayer
1286 5eb7995e j_mayer
    return ret;
1287 5eb7995e j_mayer
}
1288 5eb7995e j_mayer
1289 76a66253 j_mayer
static int check_physical (CPUState *env, mmu_ctx_t *ctx,
1290 76a66253 j_mayer
                           target_ulong eaddr, int rw)
1291 76a66253 j_mayer
{
1292 76a66253 j_mayer
    int in_plb, ret;
1293 3b46e624 ths
1294 76a66253 j_mayer
    ctx->raddr = eaddr;
1295 b227a8e9 j_mayer
    ctx->prot = PAGE_READ | PAGE_EXEC;
1296 76a66253 j_mayer
    ret = 0;
1297 a750fc0b j_mayer
    switch (env->mmu_model) {
1298 a750fc0b j_mayer
    case POWERPC_MMU_32B:
1299 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_6xx:
1300 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1301 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_4xx:
1302 a750fc0b j_mayer
    case POWERPC_MMU_REAL_4xx:
1303 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1304 caa4039c j_mayer
        ctx->prot |= PAGE_WRITE;
1305 caa4039c j_mayer
        break;
1306 caa4039c j_mayer
#if defined(TARGET_PPC64)
1307 a750fc0b j_mayer
    case POWERPC_MMU_64B:
1308 caa4039c j_mayer
        /* Real address are 60 bits long */
1309 a750fc0b j_mayer
        ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1310 caa4039c j_mayer
        ctx->prot |= PAGE_WRITE;
1311 caa4039c j_mayer
        break;
1312 9706285b j_mayer
#endif
1313 a750fc0b j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1314 caa4039c j_mayer
        if (unlikely(msr_pe != 0)) {
1315 caa4039c j_mayer
            /* 403 family add some particular protections,
1316 caa4039c j_mayer
             * using PBL/PBU registers for accesses with no translation.
1317 caa4039c j_mayer
             */
1318 caa4039c j_mayer
            in_plb =
1319 caa4039c j_mayer
                /* Check PLB validity */
1320 caa4039c j_mayer
                (env->pb[0] < env->pb[1] &&
1321 caa4039c j_mayer
                 /* and address in plb area */
1322 caa4039c j_mayer
                 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1323 caa4039c j_mayer
                (env->pb[2] < env->pb[3] &&
1324 caa4039c j_mayer
                 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1325 caa4039c j_mayer
            if (in_plb ^ msr_px) {
1326 caa4039c j_mayer
                /* Access in protected area */
1327 caa4039c j_mayer
                if (rw == 1) {
1328 caa4039c j_mayer
                    /* Access is not allowed */
1329 caa4039c j_mayer
                    ret = -2;
1330 caa4039c j_mayer
                }
1331 caa4039c j_mayer
            } else {
1332 caa4039c j_mayer
                /* Read-write access is allowed */
1333 caa4039c j_mayer
                ctx->prot |= PAGE_WRITE;
1334 76a66253 j_mayer
            }
1335 76a66253 j_mayer
        }
1336 e1833e1f j_mayer
        break;
1337 a750fc0b j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1338 caa4039c j_mayer
        /* XXX: TODO */
1339 caa4039c j_mayer
        cpu_abort(env, "BookE FSL MMU model not implemented\n");
1340 caa4039c j_mayer
        break;
1341 caa4039c j_mayer
    default:
1342 caa4039c j_mayer
        cpu_abort(env, "Unknown or invalid MMU model\n");
1343 caa4039c j_mayer
        return -1;
1344 76a66253 j_mayer
    }
1345 76a66253 j_mayer
1346 76a66253 j_mayer
    return ret;
1347 76a66253 j_mayer
}
1348 76a66253 j_mayer
1349 76a66253 j_mayer
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1350 76a66253 j_mayer
                          int rw, int access_type, int check_BATs)
1351 9a64fbe4 bellard
{
1352 9a64fbe4 bellard
    int ret;
1353 0411a972 j_mayer
1354 514fb8c1 bellard
#if 0
1355 4a057712 j_mayer
    if (loglevel != 0) {
1356 9a64fbe4 bellard
        fprintf(logfile, "%s\n", __func__);
1357 9a64fbe4 bellard
    }
1358 d9bce9d9 j_mayer
#endif
1359 4b3686fa bellard
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1360 4b3686fa bellard
        (access_type != ACCESS_CODE && msr_dr == 0)) {
1361 9a64fbe4 bellard
        /* No address translation */
1362 76a66253 j_mayer
        ret = check_physical(env, ctx, eaddr, rw);
1363 9a64fbe4 bellard
    } else {
1364 c55e9aef j_mayer
        ret = -1;
1365 a750fc0b j_mayer
        switch (env->mmu_model) {
1366 a750fc0b j_mayer
        case POWERPC_MMU_32B:
1367 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_6xx:
1368 7dbe11ac j_mayer
        case POWERPC_MMU_SOFT_74xx:
1369 a8dea12f j_mayer
            /* Try to find a BAT */
1370 a8dea12f j_mayer
            if (check_BATs)
1371 a8dea12f j_mayer
                ret = get_bat(env, ctx, eaddr, rw, access_type);
1372 c55e9aef j_mayer
            /* No break here */
1373 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1374 a750fc0b j_mayer
        case POWERPC_MMU_64B:
1375 c55e9aef j_mayer
#endif
1376 a8dea12f j_mayer
            if (ret < 0) {
1377 c55e9aef j_mayer
                /* We didn't match any BAT entry or don't have BATs */
1378 a8dea12f j_mayer
                ret = get_segment(env, ctx, eaddr, rw, access_type);
1379 a8dea12f j_mayer
            }
1380 a8dea12f j_mayer
            break;
1381 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_4xx:
1382 a750fc0b j_mayer
        case POWERPC_MMU_SOFT_4xx_Z:
1383 36081602 j_mayer
            ret = mmu40x_get_physical_address(env, ctx, eaddr,
1384 a8dea12f j_mayer
                                              rw, access_type);
1385 a8dea12f j_mayer
            break;
1386 a750fc0b j_mayer
        case POWERPC_MMU_BOOKE:
1387 5eb7995e j_mayer
            ret = mmubooke_get_physical_address(env, ctx, eaddr,
1388 5eb7995e j_mayer
                                                rw, access_type);
1389 5eb7995e j_mayer
            break;
1390 a750fc0b j_mayer
        case POWERPC_MMU_BOOKE_FSL:
1391 c55e9aef j_mayer
            /* XXX: TODO */
1392 c55e9aef j_mayer
            cpu_abort(env, "BookE FSL MMU model not implemented\n");
1393 c55e9aef j_mayer
            return -1;
1394 a750fc0b j_mayer
        case POWERPC_MMU_REAL_4xx:
1395 2662a059 j_mayer
            cpu_abort(env, "PowerPC 401 does not do any translation\n");
1396 2662a059 j_mayer
            return -1;
1397 c55e9aef j_mayer
        default:
1398 c55e9aef j_mayer
            cpu_abort(env, "Unknown or invalid MMU model\n");
1399 a8dea12f j_mayer
            return -1;
1400 9a64fbe4 bellard
        }
1401 9a64fbe4 bellard
    }
1402 514fb8c1 bellard
#if 0
1403 4a057712 j_mayer
    if (loglevel != 0) {
1404 4a057712 j_mayer
        fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
1405 c55e9aef j_mayer
                __func__, eaddr, ret, ctx->raddr);
1406 a541f297 bellard
    }
1407 76a66253 j_mayer
#endif
1408 d9bce9d9 j_mayer
1409 9a64fbe4 bellard
    return ret;
1410 9a64fbe4 bellard
}
1411 9a64fbe4 bellard
1412 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1413 a6b025d3 bellard
{
1414 76a66253 j_mayer
    mmu_ctx_t ctx;
1415 a6b025d3 bellard
1416 76a66253 j_mayer
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
1417 a6b025d3 bellard
        return -1;
1418 76a66253 j_mayer
1419 76a66253 j_mayer
    return ctx.raddr & TARGET_PAGE_MASK;
1420 a6b025d3 bellard
}
1421 9a64fbe4 bellard
1422 9a64fbe4 bellard
/* Perform address translation */
1423 e96efcfc j_mayer
int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1424 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
1425 9a64fbe4 bellard
{
1426 76a66253 j_mayer
    mmu_ctx_t ctx;
1427 a541f297 bellard
    int access_type;
1428 9a64fbe4 bellard
    int ret = 0;
1429 d9bce9d9 j_mayer
1430 b769d8fe bellard
    if (rw == 2) {
1431 b769d8fe bellard
        /* code access */
1432 b769d8fe bellard
        rw = 0;
1433 b769d8fe bellard
        access_type = ACCESS_CODE;
1434 b769d8fe bellard
    } else {
1435 b769d8fe bellard
        /* data access */
1436 b769d8fe bellard
        /* XXX: put correct access by using cpu_restore_state()
1437 b769d8fe bellard
           correctly */
1438 b769d8fe bellard
        access_type = ACCESS_INT;
1439 b769d8fe bellard
        //        access_type = env->access_type;
1440 b769d8fe bellard
    }
1441 76a66253 j_mayer
    ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
1442 9a64fbe4 bellard
    if (ret == 0) {
1443 b227a8e9 j_mayer
        ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
1444 b227a8e9 j_mayer
                                ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1445 b227a8e9 j_mayer
                                mmu_idx, is_softmmu);
1446 9a64fbe4 bellard
    } else if (ret < 0) {
1447 9a64fbe4 bellard
#if defined (DEBUG_MMU)
1448 4a057712 j_mayer
        if (loglevel != 0)
1449 76a66253 j_mayer
            cpu_dump_state(env, logfile, fprintf, 0);
1450 9a64fbe4 bellard
#endif
1451 9a64fbe4 bellard
        if (access_type == ACCESS_CODE) {
1452 9a64fbe4 bellard
            switch (ret) {
1453 9a64fbe4 bellard
            case -1:
1454 76a66253 j_mayer
                /* No matches in page tables or TLB */
1455 a750fc0b j_mayer
                switch (env->mmu_model) {
1456 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_6xx:
1457 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_IFTLB;
1458 8f793433 j_mayer
                    env->error_code = 1 << 18;
1459 76a66253 j_mayer
                    env->spr[SPR_IMISS] = address;
1460 76a66253 j_mayer
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1461 76a66253 j_mayer
                    goto tlb_miss;
1462 7dbe11ac j_mayer
                case POWERPC_MMU_SOFT_74xx:
1463 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_IFTLB;
1464 7dbe11ac j_mayer
                    goto tlb_miss_74xx;
1465 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx:
1466 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx_Z:
1467 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ITLB;
1468 8f793433 j_mayer
                    env->error_code = 0;
1469 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
1470 a8dea12f j_mayer
                    env->spr[SPR_40x_ESR] = 0x00000000;
1471 c55e9aef j_mayer
                    break;
1472 a750fc0b j_mayer
                case POWERPC_MMU_32B:
1473 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1474 a750fc0b j_mayer
                case POWERPC_MMU_64B:
1475 c55e9aef j_mayer
#endif
1476 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ISI;
1477 8f793433 j_mayer
                    env->error_code = 0x40000000;
1478 8f793433 j_mayer
                    break;
1479 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE:
1480 c55e9aef j_mayer
                    /* XXX: TODO */
1481 c55e9aef j_mayer
                    cpu_abort(env, "MMU model not implemented\n");
1482 c55e9aef j_mayer
                    return -1;
1483 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE_FSL:
1484 c55e9aef j_mayer
                    /* XXX: TODO */
1485 c55e9aef j_mayer
                    cpu_abort(env, "MMU model not implemented\n");
1486 c55e9aef j_mayer
                    return -1;
1487 a750fc0b j_mayer
                case POWERPC_MMU_REAL_4xx:
1488 2662a059 j_mayer
                    cpu_abort(env, "PowerPC 401 should never raise any MMU "
1489 2662a059 j_mayer
                              "exceptions\n");
1490 2662a059 j_mayer
                    return -1;
1491 c55e9aef j_mayer
                default:
1492 c55e9aef j_mayer
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1493 c55e9aef j_mayer
                    return -1;
1494 76a66253 j_mayer
                }
1495 9a64fbe4 bellard
                break;
1496 9a64fbe4 bellard
            case -2:
1497 9a64fbe4 bellard
                /* Access rights violation */
1498 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1499 8f793433 j_mayer
                env->error_code = 0x08000000;
1500 9a64fbe4 bellard
                break;
1501 9a64fbe4 bellard
            case -3:
1502 76a66253 j_mayer
                /* No execute protection violation */
1503 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1504 8f793433 j_mayer
                env->error_code = 0x10000000;
1505 9a64fbe4 bellard
                break;
1506 9a64fbe4 bellard
            case -4:
1507 9a64fbe4 bellard
                /* Direct store exception */
1508 9a64fbe4 bellard
                /* No code fetch is allowed in direct-store areas */
1509 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISI;
1510 8f793433 j_mayer
                env->error_code = 0x10000000;
1511 2be0071f bellard
                break;
1512 e1833e1f j_mayer
#if defined(TARGET_PPC64)
1513 2be0071f bellard
            case -5:
1514 2be0071f bellard
                /* No match in segment table */
1515 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_ISEG;
1516 8f793433 j_mayer
                env->error_code = 0;
1517 9a64fbe4 bellard
                break;
1518 e1833e1f j_mayer
#endif
1519 9a64fbe4 bellard
            }
1520 9a64fbe4 bellard
        } else {
1521 9a64fbe4 bellard
            switch (ret) {
1522 9a64fbe4 bellard
            case -1:
1523 76a66253 j_mayer
                /* No matches in page tables or TLB */
1524 a750fc0b j_mayer
                switch (env->mmu_model) {
1525 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_6xx:
1526 76a66253 j_mayer
                    if (rw == 1) {
1527 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DSTLB;
1528 8f793433 j_mayer
                        env->error_code = 1 << 16;
1529 76a66253 j_mayer
                    } else {
1530 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DLTLB;
1531 8f793433 j_mayer
                        env->error_code = 0;
1532 76a66253 j_mayer
                    }
1533 76a66253 j_mayer
                    env->spr[SPR_DMISS] = address;
1534 76a66253 j_mayer
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1535 76a66253 j_mayer
                tlb_miss:
1536 8f793433 j_mayer
                    env->error_code |= ctx.key << 19;
1537 76a66253 j_mayer
                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
1538 76a66253 j_mayer
                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
1539 8f793433 j_mayer
                    break;
1540 7dbe11ac j_mayer
                case POWERPC_MMU_SOFT_74xx:
1541 7dbe11ac j_mayer
                    if (rw == 1) {
1542 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DSTLB;
1543 7dbe11ac j_mayer
                    } else {
1544 8f793433 j_mayer
                        env->exception_index = POWERPC_EXCP_DLTLB;
1545 7dbe11ac j_mayer
                    }
1546 7dbe11ac j_mayer
                tlb_miss_74xx:
1547 7dbe11ac j_mayer
                    /* Implement LRU algorithm */
1548 8f793433 j_mayer
                    env->error_code = ctx.key << 19;
1549 7dbe11ac j_mayer
                    env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1550 7dbe11ac j_mayer
                        ((env->last_way + 1) & (env->nb_ways - 1));
1551 7dbe11ac j_mayer
                    env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1552 7dbe11ac j_mayer
                    break;
1553 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx:
1554 a750fc0b j_mayer
                case POWERPC_MMU_SOFT_4xx_Z:
1555 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DTLB;
1556 8f793433 j_mayer
                    env->error_code = 0;
1557 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
1558 a8dea12f j_mayer
                    if (rw)
1559 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00800000;
1560 a8dea12f j_mayer
                    else
1561 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00000000;
1562 c55e9aef j_mayer
                    break;
1563 a750fc0b j_mayer
                case POWERPC_MMU_32B:
1564 c55e9aef j_mayer
#if defined(TARGET_PPC64)
1565 a750fc0b j_mayer
                case POWERPC_MMU_64B:
1566 c55e9aef j_mayer
#endif
1567 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1568 8f793433 j_mayer
                    env->error_code = 0;
1569 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1570 8f793433 j_mayer
                    if (rw == 1)
1571 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x42000000;
1572 8f793433 j_mayer
                    else
1573 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x40000000;
1574 8f793433 j_mayer
                    break;
1575 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE:
1576 c55e9aef j_mayer
                    /* XXX: TODO */
1577 c55e9aef j_mayer
                    cpu_abort(env, "MMU model not implemented\n");
1578 c55e9aef j_mayer
                    return -1;
1579 a750fc0b j_mayer
                case POWERPC_MMU_BOOKE_FSL:
1580 c55e9aef j_mayer
                    /* XXX: TODO */
1581 c55e9aef j_mayer
                    cpu_abort(env, "MMU model not implemented\n");
1582 c55e9aef j_mayer
                    return -1;
1583 a750fc0b j_mayer
                case POWERPC_MMU_REAL_4xx:
1584 2662a059 j_mayer
                    cpu_abort(env, "PowerPC 401 should never raise any MMU "
1585 2662a059 j_mayer
                              "exceptions\n");
1586 2662a059 j_mayer
                    return -1;
1587 c55e9aef j_mayer
                default:
1588 c55e9aef j_mayer
                    cpu_abort(env, "Unknown or invalid MMU model\n");
1589 c55e9aef j_mayer
                    return -1;
1590 76a66253 j_mayer
                }
1591 9a64fbe4 bellard
                break;
1592 9a64fbe4 bellard
            case -2:
1593 9a64fbe4 bellard
                /* Access rights violation */
1594 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_DSI;
1595 8f793433 j_mayer
                env->error_code = 0;
1596 8f793433 j_mayer
                env->spr[SPR_DAR] = address;
1597 8f793433 j_mayer
                if (rw == 1)
1598 8f793433 j_mayer
                    env->spr[SPR_DSISR] = 0x0A000000;
1599 8f793433 j_mayer
                else
1600 8f793433 j_mayer
                    env->spr[SPR_DSISR] = 0x08000000;
1601 9a64fbe4 bellard
                break;
1602 9a64fbe4 bellard
            case -4:
1603 9a64fbe4 bellard
                /* Direct store exception */
1604 9a64fbe4 bellard
                switch (access_type) {
1605 9a64fbe4 bellard
                case ACCESS_FLOAT:
1606 9a64fbe4 bellard
                    /* Floating point load/store */
1607 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_ALIGN;
1608 8f793433 j_mayer
                    env->error_code = POWERPC_EXCP_ALIGN_FP;
1609 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1610 9a64fbe4 bellard
                    break;
1611 9a64fbe4 bellard
                case ACCESS_RES:
1612 8f793433 j_mayer
                    /* lwarx, ldarx or stwcx. */
1613 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1614 8f793433 j_mayer
                    env->error_code = 0;
1615 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1616 8f793433 j_mayer
                    if (rw == 1)
1617 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x06000000;
1618 8f793433 j_mayer
                    else
1619 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x04000000;
1620 9a64fbe4 bellard
                    break;
1621 9a64fbe4 bellard
                case ACCESS_EXT:
1622 9a64fbe4 bellard
                    /* eciwx or ecowx */
1623 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_DSI;
1624 8f793433 j_mayer
                    env->error_code = 0;
1625 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1626 8f793433 j_mayer
                    if (rw == 1)
1627 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x06100000;
1628 8f793433 j_mayer
                    else
1629 8f793433 j_mayer
                        env->spr[SPR_DSISR] = 0x04100000;
1630 9a64fbe4 bellard
                    break;
1631 9a64fbe4 bellard
                default:
1632 76a66253 j_mayer
                    printf("DSI: invalid exception (%d)\n", ret);
1633 8f793433 j_mayer
                    env->exception_index = POWERPC_EXCP_PROGRAM;
1634 8f793433 j_mayer
                    env->error_code =
1635 8f793433 j_mayer
                        POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1636 8f793433 j_mayer
                    env->spr[SPR_DAR] = address;
1637 9a64fbe4 bellard
                    break;
1638 9a64fbe4 bellard
                }
1639 fdabc366 bellard
                break;
1640 e1833e1f j_mayer
#if defined(TARGET_PPC64)
1641 2be0071f bellard
            case -5:
1642 2be0071f bellard
                /* No match in segment table */
1643 8f793433 j_mayer
                env->exception_index = POWERPC_EXCP_DSEG;
1644 8f793433 j_mayer
                env->error_code = 0;
1645 8f793433 j_mayer
                env->spr[SPR_DAR] = address;
1646 2be0071f bellard
                break;
1647 e1833e1f j_mayer
#endif
1648 9a64fbe4 bellard
            }
1649 9a64fbe4 bellard
        }
1650 9a64fbe4 bellard
#if 0
1651 8f793433 j_mayer
        printf("%s: set exception to %d %02x\n", __func__,
1652 8f793433 j_mayer
               env->exception, env->error_code);
1653 9a64fbe4 bellard
#endif
1654 9a64fbe4 bellard
        ret = 1;
1655 9a64fbe4 bellard
    }
1656 76a66253 j_mayer
1657 9a64fbe4 bellard
    return ret;
1658 9a64fbe4 bellard
}
1659 9a64fbe4 bellard
1660 3fc6c082 bellard
/*****************************************************************************/
1661 3fc6c082 bellard
/* BATs management */
1662 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1663 b068d6a7 j_mayer
static always_inline void do_invalidate_BAT (CPUPPCState *env,
1664 b068d6a7 j_mayer
                                             target_ulong BATu,
1665 b068d6a7 j_mayer
                                             target_ulong mask)
1666 3fc6c082 bellard
{
1667 3fc6c082 bellard
    target_ulong base, end, page;
1668 76a66253 j_mayer
1669 3fc6c082 bellard
    base = BATu & ~0x0001FFFF;
1670 3fc6c082 bellard
    end = base + mask + 0x00020000;
1671 3fc6c082 bellard
#if defined (DEBUG_BATS)
1672 76a66253 j_mayer
    if (loglevel != 0) {
1673 1b9eb036 j_mayer
        fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1674 76a66253 j_mayer
                base, end, mask);
1675 76a66253 j_mayer
    }
1676 3fc6c082 bellard
#endif
1677 3fc6c082 bellard
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1678 3fc6c082 bellard
        tlb_flush_page(env, page);
1679 3fc6c082 bellard
#if defined (DEBUG_BATS)
1680 3fc6c082 bellard
    if (loglevel != 0)
1681 3fc6c082 bellard
        fprintf(logfile, "Flush done\n");
1682 3fc6c082 bellard
#endif
1683 3fc6c082 bellard
}
1684 3fc6c082 bellard
#endif
1685 3fc6c082 bellard
1686 b068d6a7 j_mayer
static always_inline void dump_store_bat (CPUPPCState *env, char ID,
1687 b068d6a7 j_mayer
                                          int ul, int nr, target_ulong value)
1688 3fc6c082 bellard
{
1689 3fc6c082 bellard
#if defined (DEBUG_BATS)
1690 3fc6c082 bellard
    if (loglevel != 0) {
1691 1b9eb036 j_mayer
        fprintf(logfile, "Set %cBAT%d%c to 0x" ADDRX " (0x" ADDRX ")\n",
1692 1b9eb036 j_mayer
                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1693 3fc6c082 bellard
    }
1694 3fc6c082 bellard
#endif
1695 3fc6c082 bellard
}
1696 3fc6c082 bellard
1697 3fc6c082 bellard
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1698 3fc6c082 bellard
{
1699 3fc6c082 bellard
    return env->IBAT[0][nr];
1700 3fc6c082 bellard
}
1701 3fc6c082 bellard
1702 3fc6c082 bellard
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1703 3fc6c082 bellard
{
1704 3fc6c082 bellard
    return env->IBAT[1][nr];
1705 3fc6c082 bellard
}
1706 3fc6c082 bellard
1707 3fc6c082 bellard
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1708 3fc6c082 bellard
{
1709 3fc6c082 bellard
    target_ulong mask;
1710 3fc6c082 bellard
1711 3fc6c082 bellard
    dump_store_bat(env, 'I', 0, nr, value);
1712 3fc6c082 bellard
    if (env->IBAT[0][nr] != value) {
1713 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1714 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1715 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1716 3fc6c082 bellard
#endif
1717 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1718 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1719 3fc6c082 bellard
         */
1720 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1721 3fc6c082 bellard
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1722 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1723 3fc6c082 bellard
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1724 3fc6c082 bellard
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1725 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1726 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1727 76a66253 j_mayer
#else
1728 3fc6c082 bellard
        tlb_flush(env, 1);
1729 3fc6c082 bellard
#endif
1730 3fc6c082 bellard
    }
1731 3fc6c082 bellard
}
1732 3fc6c082 bellard
1733 3fc6c082 bellard
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1734 3fc6c082 bellard
{
1735 3fc6c082 bellard
    dump_store_bat(env, 'I', 1, nr, value);
1736 3fc6c082 bellard
    env->IBAT[1][nr] = value;
1737 3fc6c082 bellard
}
1738 3fc6c082 bellard
1739 3fc6c082 bellard
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1740 3fc6c082 bellard
{
1741 3fc6c082 bellard
    return env->DBAT[0][nr];
1742 3fc6c082 bellard
}
1743 3fc6c082 bellard
1744 3fc6c082 bellard
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1745 3fc6c082 bellard
{
1746 3fc6c082 bellard
    return env->DBAT[1][nr];
1747 3fc6c082 bellard
}
1748 3fc6c082 bellard
1749 3fc6c082 bellard
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1750 3fc6c082 bellard
{
1751 3fc6c082 bellard
    target_ulong mask;
1752 3fc6c082 bellard
1753 3fc6c082 bellard
    dump_store_bat(env, 'D', 0, nr, value);
1754 3fc6c082 bellard
    if (env->DBAT[0][nr] != value) {
1755 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1756 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1757 3fc6c082 bellard
         */
1758 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1759 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1760 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1761 3fc6c082 bellard
#endif
1762 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1763 3fc6c082 bellard
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1764 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1765 3fc6c082 bellard
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1766 3fc6c082 bellard
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1767 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1768 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1769 3fc6c082 bellard
#else
1770 3fc6c082 bellard
        tlb_flush(env, 1);
1771 3fc6c082 bellard
#endif
1772 3fc6c082 bellard
    }
1773 3fc6c082 bellard
}
1774 3fc6c082 bellard
1775 3fc6c082 bellard
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1776 3fc6c082 bellard
{
1777 3fc6c082 bellard
    dump_store_bat(env, 'D', 1, nr, value);
1778 3fc6c082 bellard
    env->DBAT[1][nr] = value;
1779 3fc6c082 bellard
}
1780 3fc6c082 bellard
1781 0a032cbe j_mayer
/*****************************************************************************/
1782 0a032cbe j_mayer
/* TLB management */
1783 0a032cbe j_mayer
void ppc_tlb_invalidate_all (CPUPPCState *env)
1784 0a032cbe j_mayer
{
1785 daf4f96e j_mayer
    switch (env->mmu_model) {
1786 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_6xx:
1787 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1788 0a032cbe j_mayer
        ppc6xx_tlb_invalidate_all(env);
1789 daf4f96e j_mayer
        break;
1790 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx:
1791 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1792 0a032cbe j_mayer
        ppc4xx_tlb_invalidate_all(env);
1793 daf4f96e j_mayer
        break;
1794 7dbe11ac j_mayer
    case POWERPC_MMU_REAL_4xx:
1795 7dbe11ac j_mayer
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1796 7dbe11ac j_mayer
        break;
1797 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1798 7dbe11ac j_mayer
        /* XXX: TODO */
1799 7dbe11ac j_mayer
        cpu_abort(env, "MMU model not implemented\n");
1800 7dbe11ac j_mayer
        break;
1801 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1802 7dbe11ac j_mayer
        /* XXX: TODO */
1803 7dbe11ac j_mayer
        cpu_abort(env, "MMU model not implemented\n");
1804 7dbe11ac j_mayer
        break;
1805 7dbe11ac j_mayer
    case POWERPC_MMU_32B:
1806 00af685f j_mayer
#if defined(TARGET_PPC64)
1807 7dbe11ac j_mayer
    case POWERPC_MMU_64B:
1808 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
1809 0a032cbe j_mayer
        tlb_flush(env, 1);
1810 daf4f96e j_mayer
        break;
1811 00af685f j_mayer
    default:
1812 00af685f j_mayer
        /* XXX: TODO */
1813 12de9a39 j_mayer
        cpu_abort(env, "Unknown MMU model\n");
1814 00af685f j_mayer
        break;
1815 0a032cbe j_mayer
    }
1816 0a032cbe j_mayer
}
1817 0a032cbe j_mayer
1818 daf4f96e j_mayer
void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1819 daf4f96e j_mayer
{
1820 daf4f96e j_mayer
#if !defined(FLUSH_ALL_TLBS)
1821 daf4f96e j_mayer
    addr &= TARGET_PAGE_MASK;
1822 daf4f96e j_mayer
    switch (env->mmu_model) {
1823 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_6xx:
1824 7dbe11ac j_mayer
    case POWERPC_MMU_SOFT_74xx:
1825 daf4f96e j_mayer
        ppc6xx_tlb_invalidate_virt(env, addr, 0);
1826 daf4f96e j_mayer
        if (env->id_tlbs == 1)
1827 daf4f96e j_mayer
            ppc6xx_tlb_invalidate_virt(env, addr, 1);
1828 daf4f96e j_mayer
        break;
1829 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx:
1830 daf4f96e j_mayer
    case POWERPC_MMU_SOFT_4xx_Z:
1831 daf4f96e j_mayer
        ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1832 daf4f96e j_mayer
        break;
1833 7dbe11ac j_mayer
    case POWERPC_MMU_REAL_4xx:
1834 7dbe11ac j_mayer
        cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1835 7dbe11ac j_mayer
        break;
1836 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE:
1837 7dbe11ac j_mayer
        /* XXX: TODO */
1838 7dbe11ac j_mayer
        cpu_abort(env, "MMU model not implemented\n");
1839 7dbe11ac j_mayer
        break;
1840 7dbe11ac j_mayer
    case POWERPC_MMU_BOOKE_FSL:
1841 7dbe11ac j_mayer
        /* XXX: TODO */
1842 7dbe11ac j_mayer
        cpu_abort(env, "MMU model not implemented\n");
1843 7dbe11ac j_mayer
        break;
1844 7dbe11ac j_mayer
    case POWERPC_MMU_32B:
1845 daf4f96e j_mayer
        /* tlbie invalidate TLBs for all segments */
1846 daf4f96e j_mayer
        addr &= ~((target_ulong)-1 << 28);
1847 daf4f96e j_mayer
        /* XXX: this case should be optimized,
1848 daf4f96e j_mayer
         * giving a mask to tlb_flush_page
1849 daf4f96e j_mayer
         */
1850 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x0 << 28));
1851 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x1 << 28));
1852 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x2 << 28));
1853 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x3 << 28));
1854 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x4 << 28));
1855 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x5 << 28));
1856 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x6 << 28));
1857 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x7 << 28));
1858 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x8 << 28));
1859 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0x9 << 28));
1860 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xA << 28));
1861 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xB << 28));
1862 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xC << 28));
1863 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xD << 28));
1864 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xE << 28));
1865 daf4f96e j_mayer
        tlb_flush_page(env, addr | (0xF << 28));
1866 7dbe11ac j_mayer
        break;
1867 00af685f j_mayer
#if defined(TARGET_PPC64)
1868 7dbe11ac j_mayer
    case POWERPC_MMU_64B:
1869 7dbe11ac j_mayer
        /* tlbie invalidate TLBs for all segments */
1870 7dbe11ac j_mayer
        /* XXX: given the fact that there are too many segments to invalidate,
1871 00af685f j_mayer
         *      and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1872 7dbe11ac j_mayer
         *      we just invalidate all TLBs
1873 7dbe11ac j_mayer
         */
1874 7dbe11ac j_mayer
        tlb_flush(env, 1);
1875 7dbe11ac j_mayer
        break;
1876 00af685f j_mayer
#endif /* defined(TARGET_PPC64) */
1877 00af685f j_mayer
    default:
1878 00af685f j_mayer
        /* XXX: TODO */
1879 12de9a39 j_mayer
        cpu_abort(env, "Unknown MMU model\n");
1880 00af685f j_mayer
        break;
1881 daf4f96e j_mayer
    }
1882 daf4f96e j_mayer
#else
1883 daf4f96e j_mayer
    ppc_tlb_invalidate_all(env);
1884 daf4f96e j_mayer
#endif
1885 daf4f96e j_mayer
}
1886 daf4f96e j_mayer
1887 3fc6c082 bellard
/*****************************************************************************/
1888 3fc6c082 bellard
/* Special registers manipulation */
1889 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1890 d9bce9d9 j_mayer
target_ulong ppc_load_asr (CPUPPCState *env)
1891 d9bce9d9 j_mayer
{
1892 d9bce9d9 j_mayer
    return env->asr;
1893 d9bce9d9 j_mayer
}
1894 d9bce9d9 j_mayer
1895 d9bce9d9 j_mayer
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1896 d9bce9d9 j_mayer
{
1897 d9bce9d9 j_mayer
    if (env->asr != value) {
1898 d9bce9d9 j_mayer
        env->asr = value;
1899 d9bce9d9 j_mayer
        tlb_flush(env, 1);
1900 d9bce9d9 j_mayer
    }
1901 d9bce9d9 j_mayer
}
1902 d9bce9d9 j_mayer
#endif
1903 d9bce9d9 j_mayer
1904 3fc6c082 bellard
target_ulong do_load_sdr1 (CPUPPCState *env)
1905 3fc6c082 bellard
{
1906 3fc6c082 bellard
    return env->sdr1;
1907 3fc6c082 bellard
}
1908 3fc6c082 bellard
1909 3fc6c082 bellard
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
1910 3fc6c082 bellard
{
1911 3fc6c082 bellard
#if defined (DEBUG_MMU)
1912 3fc6c082 bellard
    if (loglevel != 0) {
1913 1b9eb036 j_mayer
        fprintf(logfile, "%s: 0x" ADDRX "\n", __func__, value);
1914 3fc6c082 bellard
    }
1915 3fc6c082 bellard
#endif
1916 3fc6c082 bellard
    if (env->sdr1 != value) {
1917 12de9a39 j_mayer
        /* XXX: for PowerPC 64, should check that the HTABSIZE value
1918 12de9a39 j_mayer
         *      is <= 28
1919 12de9a39 j_mayer
         */
1920 3fc6c082 bellard
        env->sdr1 = value;
1921 76a66253 j_mayer
        tlb_flush(env, 1);
1922 3fc6c082 bellard
    }
1923 3fc6c082 bellard
}
1924 3fc6c082 bellard
1925 12de9a39 j_mayer
#if 0 // Unused
1926 3fc6c082 bellard
target_ulong do_load_sr (CPUPPCState *env, int srnum)
1927 3fc6c082 bellard
{
1928 3fc6c082 bellard
    return env->sr[srnum];
1929 3fc6c082 bellard
}
1930 12de9a39 j_mayer
#endif
1931 3fc6c082 bellard
1932 3fc6c082 bellard
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1933 3fc6c082 bellard
{
1934 3fc6c082 bellard
#if defined (DEBUG_MMU)
1935 3fc6c082 bellard
    if (loglevel != 0) {
1936 1b9eb036 j_mayer
        fprintf(logfile, "%s: reg=%d 0x" ADDRX " " ADDRX "\n",
1937 1b9eb036 j_mayer
                __func__, srnum, value, env->sr[srnum]);
1938 3fc6c082 bellard
    }
1939 3fc6c082 bellard
#endif
1940 3fc6c082 bellard
    if (env->sr[srnum] != value) {
1941 3fc6c082 bellard
        env->sr[srnum] = value;
1942 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS) && 0
1943 3fc6c082 bellard
        {
1944 3fc6c082 bellard
            target_ulong page, end;
1945 3fc6c082 bellard
            /* Invalidate 256 MB of virtual memory */
1946 3fc6c082 bellard
            page = (16 << 20) * srnum;
1947 3fc6c082 bellard
            end = page + (16 << 20);
1948 3fc6c082 bellard
            for (; page != end; page += TARGET_PAGE_SIZE)
1949 3fc6c082 bellard
                tlb_flush_page(env, page);
1950 3fc6c082 bellard
        }
1951 3fc6c082 bellard
#else
1952 76a66253 j_mayer
        tlb_flush(env, 1);
1953 3fc6c082 bellard
#endif
1954 3fc6c082 bellard
    }
1955 3fc6c082 bellard
}
1956 76a66253 j_mayer
#endif /* !defined (CONFIG_USER_ONLY) */
1957 3fc6c082 bellard
1958 bfa1e5cf j_mayer
target_ulong ppc_load_xer (CPUPPCState *env)
1959 79aceca5 bellard
{
1960 0411a972 j_mayer
    return hreg_load_xer(env);
1961 79aceca5 bellard
}
1962 79aceca5 bellard
1963 bfa1e5cf j_mayer
void ppc_store_xer (CPUPPCState *env, target_ulong value)
1964 79aceca5 bellard
{
1965 0411a972 j_mayer
    hreg_store_xer(env, value);
1966 79aceca5 bellard
}
1967 79aceca5 bellard
1968 76a66253 j_mayer
/* GDBstub can read and write MSR... */
1969 0411a972 j_mayer
void ppc_store_msr (CPUPPCState *env, target_ulong value)
1970 3fc6c082 bellard
{
1971 0411a972 j_mayer
    hreg_store_msr(env, value);
1972 3fc6c082 bellard
}
1973 3fc6c082 bellard
1974 3fc6c082 bellard
/*****************************************************************************/
1975 3fc6c082 bellard
/* Exception processing */
1976 18fba28c bellard
#if defined (CONFIG_USER_ONLY)
1977 9a64fbe4 bellard
void do_interrupt (CPUState *env)
1978 79aceca5 bellard
{
1979 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
1980 e1833e1f j_mayer
    env->error_code = 0;
1981 18fba28c bellard
}
1982 47103572 j_mayer
1983 e9df014c j_mayer
void ppc_hw_interrupt (CPUState *env)
1984 47103572 j_mayer
{
1985 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
1986 e1833e1f j_mayer
    env->error_code = 0;
1987 47103572 j_mayer
}
1988 76a66253 j_mayer
#else /* defined (CONFIG_USER_ONLY) */
1989 36081602 j_mayer
static void dump_syscall (CPUState *env)
1990 d094807b bellard
{
1991 d9bce9d9 j_mayer
    fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
1992 1b9eb036 j_mayer
            " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
1993 d094807b bellard
            env->gpr[0], env->gpr[3], env->gpr[4],
1994 d094807b bellard
            env->gpr[5], env->gpr[6], env->nip);
1995 d094807b bellard
}
1996 d094807b bellard
1997 e1833e1f j_mayer
/* Note that this function should be greatly optimized
1998 e1833e1f j_mayer
 * when called with a constant excp, from ppc_hw_interrupt
1999 e1833e1f j_mayer
 */
2000 e1833e1f j_mayer
static always_inline void powerpc_excp (CPUState *env,
2001 e1833e1f j_mayer
                                        int excp_model, int excp)
2002 18fba28c bellard
{
2003 0411a972 j_mayer
    target_ulong msr, new_msr, vector;
2004 e1833e1f j_mayer
    int srr0, srr1, asrr0, asrr1;
2005 f9fdea6b j_mayer
#if defined(TARGET_PPC64H)
2006 f9fdea6b j_mayer
    int lpes0, lpes1, lev;
2007 f9fdea6b j_mayer
2008 f9fdea6b j_mayer
    lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2009 f9fdea6b j_mayer
    lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2010 f9fdea6b j_mayer
#endif
2011 79aceca5 bellard
2012 b769d8fe bellard
    if (loglevel & CPU_LOG_INT) {
2013 1b9eb036 j_mayer
        fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
2014 1b9eb036 j_mayer
                env->nip, excp, env->error_code);
2015 b769d8fe bellard
    }
2016 0411a972 j_mayer
    msr = env->msr;
2017 0411a972 j_mayer
    new_msr = msr;
2018 e1833e1f j_mayer
    srr0 = SPR_SRR0;
2019 e1833e1f j_mayer
    srr1 = SPR_SRR1;
2020 e1833e1f j_mayer
    asrr0 = -1;
2021 e1833e1f j_mayer
    asrr1 = -1;
2022 e1833e1f j_mayer
    msr &= ~((target_ulong)0x783F0000);
2023 9a64fbe4 bellard
    switch (excp) {
2024 e1833e1f j_mayer
    case POWERPC_EXCP_NONE:
2025 e1833e1f j_mayer
        /* Should never happen */
2026 e1833e1f j_mayer
        return;
2027 e1833e1f j_mayer
    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
2028 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2029 e1833e1f j_mayer
        switch (excp_model) {
2030 a750fc0b j_mayer
        case POWERPC_EXCP_40x:
2031 e1833e1f j_mayer
            srr0 = SPR_40x_SRR2;
2032 e1833e1f j_mayer
            srr1 = SPR_40x_SRR3;
2033 c62db105 j_mayer
            break;
2034 a750fc0b j_mayer
        case POWERPC_EXCP_BOOKE:
2035 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2036 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2037 c62db105 j_mayer
            break;
2038 e1833e1f j_mayer
        case POWERPC_EXCP_G2:
2039 c62db105 j_mayer
            break;
2040 e1833e1f j_mayer
        default:
2041 e1833e1f j_mayer
            goto excp_invalid;
2042 2be0071f bellard
        }
2043 9a64fbe4 bellard
        goto store_next;
2044 e1833e1f j_mayer
    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
2045 e1833e1f j_mayer
        if (msr_me == 0) {
2046 e63ecc6f j_mayer
            /* Machine check exception is not enabled.
2047 e63ecc6f j_mayer
             * Enter checkstop state.
2048 e63ecc6f j_mayer
             */
2049 e63ecc6f j_mayer
            if (loglevel != 0) {
2050 e63ecc6f j_mayer
                fprintf(logfile, "Machine check while not allowed. "
2051 e63ecc6f j_mayer
                        "Entering checkstop state\n");
2052 e63ecc6f j_mayer
            } else {
2053 e63ecc6f j_mayer
                fprintf(stderr, "Machine check while not allowed. "
2054 e63ecc6f j_mayer
                        "Entering checkstop state\n");
2055 e63ecc6f j_mayer
            }
2056 e63ecc6f j_mayer
            env->halted = 1;
2057 e63ecc6f j_mayer
            env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2058 e1833e1f j_mayer
        }
2059 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2060 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_ME);
2061 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2062 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2063 e1833e1f j_mayer
#endif
2064 e1833e1f j_mayer
        /* XXX: should also have something loaded in DAR / DSISR */
2065 e1833e1f j_mayer
        switch (excp_model) {
2066 a750fc0b j_mayer
        case POWERPC_EXCP_40x:
2067 e1833e1f j_mayer
            srr0 = SPR_40x_SRR2;
2068 e1833e1f j_mayer
            srr1 = SPR_40x_SRR3;
2069 c62db105 j_mayer
            break;
2070 a750fc0b j_mayer
        case POWERPC_EXCP_BOOKE:
2071 e1833e1f j_mayer
            srr0 = SPR_BOOKE_MCSRR0;
2072 e1833e1f j_mayer
            srr1 = SPR_BOOKE_MCSRR1;
2073 e1833e1f j_mayer
            asrr0 = SPR_BOOKE_CSRR0;
2074 e1833e1f j_mayer
            asrr1 = SPR_BOOKE_CSRR1;
2075 c62db105 j_mayer
            break;
2076 c62db105 j_mayer
        default:
2077 c62db105 j_mayer
            break;
2078 2be0071f bellard
        }
2079 e1833e1f j_mayer
        goto store_next;
2080 e1833e1f j_mayer
    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
2081 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
2082 4a057712 j_mayer
        if (loglevel != 0) {
2083 1b9eb036 j_mayer
            fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
2084 1b9eb036 j_mayer
                    "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2085 76a66253 j_mayer
        }
2086 a541f297 bellard
#endif
2087 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2088 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2089 e1833e1f j_mayer
        if (lpes1 == 0)
2090 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2091 e1833e1f j_mayer
#endif
2092 a541f297 bellard
        goto store_next;
2093 e1833e1f j_mayer
    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
2094 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
2095 76a66253 j_mayer
        if (loglevel != 0) {
2096 1b9eb036 j_mayer
            fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
2097 1b9eb036 j_mayer
                    "\n", msr, env->nip);
2098 76a66253 j_mayer
        }
2099 a541f297 bellard
#endif
2100 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2101 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2102 e1833e1f j_mayer
        if (lpes1 == 0)
2103 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2104 e1833e1f j_mayer
#endif
2105 e1833e1f j_mayer
        msr |= env->error_code;
2106 9a64fbe4 bellard
        goto store_next;
2107 e1833e1f j_mayer
    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
2108 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2109 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2110 e1833e1f j_mayer
        if (lpes0 == 1)
2111 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2112 e1833e1f j_mayer
#endif
2113 9a64fbe4 bellard
        goto store_next;
2114 e1833e1f j_mayer
    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
2115 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2116 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2117 e1833e1f j_mayer
        if (lpes1 == 0)
2118 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2119 e1833e1f j_mayer
#endif
2120 e1833e1f j_mayer
        /* XXX: this is false */
2121 e1833e1f j_mayer
        /* Get rS/rD and rA from faulting opcode */
2122 e1833e1f j_mayer
        env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2123 9a64fbe4 bellard
        goto store_current;
2124 e1833e1f j_mayer
    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
2125 9a64fbe4 bellard
        switch (env->error_code & ~0xF) {
2126 e1833e1f j_mayer
        case POWERPC_EXCP_FP:
2127 e1833e1f j_mayer
            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2128 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
2129 4a057712 j_mayer
                if (loglevel != 0) {
2130 a496775f j_mayer
                    fprintf(logfile, "Ignore floating point exception\n");
2131 a496775f j_mayer
                }
2132 9a64fbe4 bellard
#endif
2133 9a64fbe4 bellard
                return;
2134 76a66253 j_mayer
            }
2135 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_RI);
2136 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2137 e1833e1f j_mayer
            if (lpes1 == 0)
2138 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_HV;
2139 e1833e1f j_mayer
#endif
2140 9a64fbe4 bellard
            msr |= 0x00100000;
2141 9a64fbe4 bellard
            /* Set FX */
2142 9a64fbe4 bellard
            env->fpscr[7] |= 0x8;
2143 9a64fbe4 bellard
            /* Finally, update FEX */
2144 9a64fbe4 bellard
            if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
2145 9a64fbe4 bellard
                ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
2146 9a64fbe4 bellard
                env->fpscr[7] |= 0x4;
2147 e1833e1f j_mayer
            if (msr_fe0 != msr_fe1) {
2148 e1833e1f j_mayer
                msr |= 0x00010000;
2149 e1833e1f j_mayer
                goto store_current;
2150 e1833e1f j_mayer
            }
2151 76a66253 j_mayer
            break;
2152 e1833e1f j_mayer
        case POWERPC_EXCP_INVAL:
2153 a496775f j_mayer
#if defined (DEBUG_EXCEPTIONS)
2154 4a057712 j_mayer
            if (loglevel != 0) {
2155 a496775f j_mayer
                fprintf(logfile, "Invalid instruction at 0x" ADDRX "\n",
2156 a496775f j_mayer
                        env->nip);
2157 a496775f j_mayer
            }
2158 a496775f j_mayer
#endif
2159 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_RI);
2160 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2161 e1833e1f j_mayer
            if (lpes1 == 0)
2162 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_HV;
2163 e1833e1f j_mayer
#endif
2164 9a64fbe4 bellard
            msr |= 0x00080000;
2165 76a66253 j_mayer
            break;
2166 e1833e1f j_mayer
        case POWERPC_EXCP_PRIV:
2167 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_RI);
2168 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2169 e1833e1f j_mayer
            if (lpes1 == 0)
2170 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_HV;
2171 e1833e1f j_mayer
#endif
2172 9a64fbe4 bellard
            msr |= 0x00040000;
2173 76a66253 j_mayer
            break;
2174 e1833e1f j_mayer
        case POWERPC_EXCP_TRAP:
2175 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_RI);
2176 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2177 e1833e1f j_mayer
            if (lpes1 == 0)
2178 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_HV;
2179 e1833e1f j_mayer
#endif
2180 9a64fbe4 bellard
            msr |= 0x00020000;
2181 9a64fbe4 bellard
            break;
2182 9a64fbe4 bellard
        default:
2183 9a64fbe4 bellard
            /* Should never occur */
2184 e1833e1f j_mayer
            cpu_abort(env, "Invalid program exception %d. Aborting\n",
2185 e1833e1f j_mayer
                      env->error_code);
2186 76a66253 j_mayer
            break;
2187 76a66253 j_mayer
        }
2188 9a64fbe4 bellard
        goto store_next;
2189 e1833e1f j_mayer
    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
2190 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2191 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2192 e1833e1f j_mayer
        if (lpes1 == 0)
2193 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2194 e1833e1f j_mayer
#endif
2195 e1833e1f j_mayer
        goto store_current;
2196 e1833e1f j_mayer
    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
2197 d094807b bellard
        /* NOTE: this is a temporary hack to support graphics OSI
2198 d094807b bellard
           calls from the MOL driver */
2199 e1833e1f j_mayer
        /* XXX: To be removed */
2200 d094807b bellard
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2201 d094807b bellard
            env->osi_call) {
2202 d094807b bellard
            if (env->osi_call(env) != 0)
2203 d094807b bellard
                return;
2204 d094807b bellard
        }
2205 b769d8fe bellard
        if (loglevel & CPU_LOG_INT) {
2206 d094807b bellard
            dump_syscall(env);
2207 b769d8fe bellard
        }
2208 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2209 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2210 f9fdea6b j_mayer
        lev = env->error_code;
2211 e1833e1f j_mayer
        if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2212 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2213 e1833e1f j_mayer
#endif
2214 e1833e1f j_mayer
        goto store_next;
2215 e1833e1f j_mayer
    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
2216 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2217 e1833e1f j_mayer
        goto store_current;
2218 e1833e1f j_mayer
    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
2219 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2220 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2221 e1833e1f j_mayer
        if (lpes1 == 0)
2222 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2223 e1833e1f j_mayer
#endif
2224 e1833e1f j_mayer
        goto store_next;
2225 e1833e1f j_mayer
    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
2226 e1833e1f j_mayer
        /* FIT on 4xx */
2227 e1833e1f j_mayer
#if defined (DEBUG_EXCEPTIONS)
2228 e1833e1f j_mayer
        if (loglevel != 0)
2229 e1833e1f j_mayer
            fprintf(logfile, "FIT exception\n");
2230 e1833e1f j_mayer
#endif
2231 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2232 9a64fbe4 bellard
        goto store_next;
2233 e1833e1f j_mayer
    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
2234 e1833e1f j_mayer
#if defined (DEBUG_EXCEPTIONS)
2235 e1833e1f j_mayer
        if (loglevel != 0)
2236 e1833e1f j_mayer
            fprintf(logfile, "WDT exception\n");
2237 e1833e1f j_mayer
#endif
2238 e1833e1f j_mayer
        switch (excp_model) {
2239 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2240 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2241 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2242 e1833e1f j_mayer
            break;
2243 e1833e1f j_mayer
        default:
2244 e1833e1f j_mayer
            break;
2245 e1833e1f j_mayer
        }
2246 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2247 2be0071f bellard
        goto store_next;
2248 e1833e1f j_mayer
    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
2249 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2250 e1833e1f j_mayer
        goto store_next;
2251 e1833e1f j_mayer
    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
2252 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2253 e1833e1f j_mayer
        goto store_next;
2254 e1833e1f j_mayer
    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
2255 e1833e1f j_mayer
        switch (excp_model) {
2256 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2257 e1833e1f j_mayer
            srr0 = SPR_BOOKE_DSRR0;
2258 e1833e1f j_mayer
            srr1 = SPR_BOOKE_DSRR1;
2259 e1833e1f j_mayer
            asrr0 = SPR_BOOKE_CSRR0;
2260 e1833e1f j_mayer
            asrr1 = SPR_BOOKE_CSRR1;
2261 e1833e1f j_mayer
            break;
2262 e1833e1f j_mayer
        default:
2263 e1833e1f j_mayer
            break;
2264 e1833e1f j_mayer
        }
2265 2be0071f bellard
        /* XXX: TODO */
2266 e1833e1f j_mayer
        cpu_abort(env, "Debug exception is not implemented yet !\n");
2267 2be0071f bellard
        goto store_next;
2268 e1833e1f j_mayer
#if defined(TARGET_PPCEMB)
2269 e1833e1f j_mayer
    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
2270 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2271 e1833e1f j_mayer
        goto store_current;
2272 e1833e1f j_mayer
    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
2273 2be0071f bellard
        /* XXX: TODO */
2274 e1833e1f j_mayer
        cpu_abort(env, "Embedded floating point data exception "
2275 2be0071f bellard
                  "is not implemented yet !\n");
2276 2be0071f bellard
        goto store_next;
2277 e1833e1f j_mayer
    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
2278 2be0071f bellard
        /* XXX: TODO */
2279 e1833e1f j_mayer
        cpu_abort(env, "Embedded floating point round exception "
2280 e1833e1f j_mayer
                  "is not implemented yet !\n");
2281 9a64fbe4 bellard
        goto store_next;
2282 e1833e1f j_mayer
    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
2283 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2284 2be0071f bellard
        /* XXX: TODO */
2285 2be0071f bellard
        cpu_abort(env,
2286 e1833e1f j_mayer
                  "Performance counter exception is not implemented yet !\n");
2287 9a64fbe4 bellard
        goto store_next;
2288 e1833e1f j_mayer
    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
2289 76a66253 j_mayer
        /* XXX: TODO */
2290 e1833e1f j_mayer
        cpu_abort(env,
2291 e1833e1f j_mayer
                  "Embedded doorbell interrupt is not implemented yet !\n");
2292 2be0071f bellard
        goto store_next;
2293 e1833e1f j_mayer
    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
2294 e1833e1f j_mayer
        switch (excp_model) {
2295 e1833e1f j_mayer
        case POWERPC_EXCP_BOOKE:
2296 e1833e1f j_mayer
            srr0 = SPR_BOOKE_CSRR0;
2297 e1833e1f j_mayer
            srr1 = SPR_BOOKE_CSRR1;
2298 a750fc0b j_mayer
            break;
2299 2be0071f bellard
        default:
2300 2be0071f bellard
            break;
2301 2be0071f bellard
        }
2302 e1833e1f j_mayer
        /* XXX: TODO */
2303 e1833e1f j_mayer
        cpu_abort(env, "Embedded doorbell critical interrupt "
2304 e1833e1f j_mayer
                  "is not implemented yet !\n");
2305 e1833e1f j_mayer
        goto store_next;
2306 e1833e1f j_mayer
#endif /* defined(TARGET_PPCEMB) */
2307 e1833e1f j_mayer
    case POWERPC_EXCP_RESET:     /* System reset exception                   */
2308 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2309 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2310 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2311 e1833e1f j_mayer
#endif
2312 e1833e1f j_mayer
        goto store_next;
2313 e1833e1f j_mayer
#if defined(TARGET_PPC64)
2314 e1833e1f j_mayer
    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
2315 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2316 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2317 e1833e1f j_mayer
        if (lpes1 == 0)
2318 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2319 e1833e1f j_mayer
#endif
2320 e1833e1f j_mayer
        goto store_next;
2321 e1833e1f j_mayer
    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
2322 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2323 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2324 e1833e1f j_mayer
        if (lpes1 == 0)
2325 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2326 e1833e1f j_mayer
#endif
2327 e1833e1f j_mayer
        goto store_next;
2328 e1833e1f j_mayer
#endif /* defined(TARGET_PPC64) */
2329 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2330 e1833e1f j_mayer
    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
2331 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2332 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2333 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2334 e1833e1f j_mayer
        goto store_next;
2335 e1833e1f j_mayer
#endif
2336 e1833e1f j_mayer
    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
2337 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2338 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2339 e1833e1f j_mayer
        if (lpes1 == 0)
2340 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2341 e1833e1f j_mayer
#endif
2342 e1833e1f j_mayer
        goto store_next;
2343 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2344 e1833e1f j_mayer
    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
2345 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2346 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2347 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2348 e1833e1f j_mayer
        goto store_next;
2349 e1833e1f j_mayer
    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
2350 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2351 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2352 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2353 e1833e1f j_mayer
        goto store_next;
2354 e1833e1f j_mayer
    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
2355 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2356 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2357 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2358 e1833e1f j_mayer
        goto store_next;
2359 e1833e1f j_mayer
    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
2360 e1833e1f j_mayer
        srr0 = SPR_HSRR0;
2361 f9fdea6b j_mayer
        srr1 = SPR_HSRR1;
2362 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_HV;
2363 e1833e1f j_mayer
        goto store_next;
2364 e1833e1f j_mayer
#endif /* defined(TARGET_PPC64H) */
2365 e1833e1f j_mayer
    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
2366 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2367 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2368 e1833e1f j_mayer
        if (lpes1 == 0)
2369 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2370 e1833e1f j_mayer
#endif
2371 e1833e1f j_mayer
        goto store_current;
2372 e1833e1f j_mayer
    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
2373 a496775f j_mayer
#if defined (DEBUG_EXCEPTIONS)
2374 e1833e1f j_mayer
        if (loglevel != 0)
2375 e1833e1f j_mayer
            fprintf(logfile, "PIT exception\n");
2376 e1833e1f j_mayer
#endif
2377 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2378 e1833e1f j_mayer
        goto store_next;
2379 e1833e1f j_mayer
    case POWERPC_EXCP_IO:        /* IO error exception                       */
2380 e1833e1f j_mayer
        /* XXX: TODO */
2381 e1833e1f j_mayer
        cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2382 e1833e1f j_mayer
        goto store_next;
2383 e1833e1f j_mayer
    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
2384 e1833e1f j_mayer
        /* XXX: TODO */
2385 e1833e1f j_mayer
        cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2386 e1833e1f j_mayer
        goto store_next;
2387 e1833e1f j_mayer
    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
2388 e1833e1f j_mayer
        /* XXX: TODO */
2389 e1833e1f j_mayer
        cpu_abort(env, "602 emulation trap exception "
2390 e1833e1f j_mayer
                  "is not implemented yet !\n");
2391 e1833e1f j_mayer
        goto store_next;
2392 e1833e1f j_mayer
    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
2393 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2394 e1833e1f j_mayer
#if defined(TARGET_PPC64H) /* XXX: check this */
2395 e1833e1f j_mayer
        if (lpes1 == 0)
2396 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2397 a496775f j_mayer
#endif
2398 e1833e1f j_mayer
        switch (excp_model) {
2399 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2400 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2401 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2402 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2403 e1833e1f j_mayer
            goto tlb_miss_tgpr;
2404 a750fc0b j_mayer
        case POWERPC_EXCP_7x5:
2405 76a66253 j_mayer
            goto tlb_miss;
2406 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2407 7dbe11ac j_mayer
            goto tlb_miss_74xx;
2408 2be0071f bellard
        default:
2409 e1833e1f j_mayer
            cpu_abort(env, "Invalid instruction TLB miss exception\n");
2410 2be0071f bellard
            break;
2411 2be0071f bellard
        }
2412 e1833e1f j_mayer
        break;
2413 e1833e1f j_mayer
    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
2414 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2415 e1833e1f j_mayer
#if defined(TARGET_PPC64H) /* XXX: check this */
2416 e1833e1f j_mayer
        if (lpes1 == 0)
2417 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2418 a496775f j_mayer
#endif
2419 e1833e1f j_mayer
        switch (excp_model) {
2420 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2421 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2422 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2423 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2424 e1833e1f j_mayer
            goto tlb_miss_tgpr;
2425 a750fc0b j_mayer
        case POWERPC_EXCP_7x5:
2426 76a66253 j_mayer
            goto tlb_miss;
2427 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2428 7dbe11ac j_mayer
            goto tlb_miss_74xx;
2429 2be0071f bellard
        default:
2430 e1833e1f j_mayer
            cpu_abort(env, "Invalid data load TLB miss exception\n");
2431 2be0071f bellard
            break;
2432 2be0071f bellard
        }
2433 e1833e1f j_mayer
        break;
2434 e1833e1f j_mayer
    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
2435 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2436 e1833e1f j_mayer
#if defined(TARGET_PPC64H) /* XXX: check this */
2437 e1833e1f j_mayer
        if (lpes1 == 0)
2438 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2439 e1833e1f j_mayer
#endif
2440 e1833e1f j_mayer
        switch (excp_model) {
2441 a750fc0b j_mayer
        case POWERPC_EXCP_602:
2442 a750fc0b j_mayer
        case POWERPC_EXCP_603:
2443 a750fc0b j_mayer
        case POWERPC_EXCP_603E:
2444 a750fc0b j_mayer
        case POWERPC_EXCP_G2:
2445 e1833e1f j_mayer
        tlb_miss_tgpr:
2446 76a66253 j_mayer
            /* Swap temporary saved registers with GPRs */
2447 0411a972 j_mayer
            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2448 0411a972 j_mayer
                new_msr |= (target_ulong)1 << MSR_TGPR;
2449 0411a972 j_mayer
                hreg_swap_gpr_tgpr(env);
2450 0411a972 j_mayer
            }
2451 e1833e1f j_mayer
            goto tlb_miss;
2452 e1833e1f j_mayer
        case POWERPC_EXCP_7x5:
2453 e1833e1f j_mayer
        tlb_miss:
2454 2be0071f bellard
#if defined (DEBUG_SOFTWARE_TLB)
2455 2be0071f bellard
            if (loglevel != 0) {
2456 76a66253 j_mayer
                const unsigned char *es;
2457 76a66253 j_mayer
                target_ulong *miss, *cmp;
2458 76a66253 j_mayer
                int en;
2459 1e6784f9 j_mayer
                if (excp == POWERPC_EXCP_IFTLB) {
2460 76a66253 j_mayer
                    es = "I";
2461 76a66253 j_mayer
                    en = 'I';
2462 76a66253 j_mayer
                    miss = &env->spr[SPR_IMISS];
2463 76a66253 j_mayer
                    cmp = &env->spr[SPR_ICMP];
2464 76a66253 j_mayer
                } else {
2465 1e6784f9 j_mayer
                    if (excp == POWERPC_EXCP_DLTLB)
2466 76a66253 j_mayer
                        es = "DL";
2467 76a66253 j_mayer
                    else
2468 76a66253 j_mayer
                        es = "DS";
2469 76a66253 j_mayer
                    en = 'D';
2470 76a66253 j_mayer
                    miss = &env->spr[SPR_DMISS];
2471 76a66253 j_mayer
                    cmp = &env->spr[SPR_DCMP];
2472 76a66253 j_mayer
                }
2473 1b9eb036 j_mayer
                fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2474 4a057712 j_mayer
                        " H1 " ADDRX " H2 " ADDRX " %08x\n",
2475 1b9eb036 j_mayer
                        es, en, *miss, en, *cmp,
2476 76a66253 j_mayer
                        env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2477 2be0071f bellard
                        env->error_code);
2478 2be0071f bellard
            }
2479 9a64fbe4 bellard
#endif
2480 2be0071f bellard
            msr |= env->crf[0] << 28;
2481 2be0071f bellard
            msr |= env->error_code; /* key, D/I, S/L bits */
2482 2be0071f bellard
            /* Set way using a LRU mechanism */
2483 76a66253 j_mayer
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2484 c62db105 j_mayer
            break;
2485 7dbe11ac j_mayer
        case POWERPC_EXCP_74xx:
2486 7dbe11ac j_mayer
        tlb_miss_74xx:
2487 7dbe11ac j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
2488 7dbe11ac j_mayer
            if (loglevel != 0) {
2489 7dbe11ac j_mayer
                const unsigned char *es;
2490 7dbe11ac j_mayer
                target_ulong *miss, *cmp;
2491 7dbe11ac j_mayer
                int en;
2492 7dbe11ac j_mayer
                if (excp == POWERPC_EXCP_IFTLB) {
2493 7dbe11ac j_mayer
                    es = "I";
2494 7dbe11ac j_mayer
                    en = 'I';
2495 0411a972 j_mayer
                    miss = &env->spr[SPR_TLBMISS];
2496 0411a972 j_mayer
                    cmp = &env->spr[SPR_PTEHI];
2497 7dbe11ac j_mayer
                } else {
2498 7dbe11ac j_mayer
                    if (excp == POWERPC_EXCP_DLTLB)
2499 7dbe11ac j_mayer
                        es = "DL";
2500 7dbe11ac j_mayer
                    else
2501 7dbe11ac j_mayer
                        es = "DS";
2502 7dbe11ac j_mayer
                    en = 'D';
2503 7dbe11ac j_mayer
                    miss = &env->spr[SPR_TLBMISS];
2504 7dbe11ac j_mayer
                    cmp = &env->spr[SPR_PTEHI];
2505 7dbe11ac j_mayer
                }
2506 7dbe11ac j_mayer
                fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2507 7dbe11ac j_mayer
                        " %08x\n",
2508 7dbe11ac j_mayer
                        es, en, *miss, en, *cmp, env->error_code);
2509 7dbe11ac j_mayer
            }
2510 7dbe11ac j_mayer
#endif
2511 7dbe11ac j_mayer
            msr |= env->error_code; /* key bit */
2512 7dbe11ac j_mayer
            break;
2513 2be0071f bellard
        default:
2514 e1833e1f j_mayer
            cpu_abort(env, "Invalid data store TLB miss exception\n");
2515 2be0071f bellard
            break;
2516 2be0071f bellard
        }
2517 e1833e1f j_mayer
        goto store_next;
2518 e1833e1f j_mayer
    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
2519 e1833e1f j_mayer
        /* XXX: TODO */
2520 e1833e1f j_mayer
        cpu_abort(env, "Floating point assist exception "
2521 e1833e1f j_mayer
                  "is not implemented yet !\n");
2522 e1833e1f j_mayer
        goto store_next;
2523 e1833e1f j_mayer
    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
2524 e1833e1f j_mayer
        /* XXX: TODO */
2525 e1833e1f j_mayer
        cpu_abort(env, "IABR exception is not implemented yet !\n");
2526 e1833e1f j_mayer
        goto store_next;
2527 e1833e1f j_mayer
    case POWERPC_EXCP_SMI:       /* System management interrupt              */
2528 e1833e1f j_mayer
        /* XXX: TODO */
2529 e1833e1f j_mayer
        cpu_abort(env, "SMI exception is not implemented yet !\n");
2530 e1833e1f j_mayer
        goto store_next;
2531 e1833e1f j_mayer
    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
2532 e1833e1f j_mayer
        /* XXX: TODO */
2533 e1833e1f j_mayer
        cpu_abort(env, "Thermal management exception "
2534 e1833e1f j_mayer
                  "is not implemented yet !\n");
2535 e1833e1f j_mayer
        goto store_next;
2536 e1833e1f j_mayer
    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
2537 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_RI);
2538 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2539 e1833e1f j_mayer
        if (lpes1 == 0)
2540 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_HV;
2541 e1833e1f j_mayer
#endif
2542 e1833e1f j_mayer
        /* XXX: TODO */
2543 e1833e1f j_mayer
        cpu_abort(env,
2544 e1833e1f j_mayer
                  "Performance counter exception is not implemented yet !\n");
2545 e1833e1f j_mayer
        goto store_next;
2546 e1833e1f j_mayer
    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
2547 e1833e1f j_mayer
        /* XXX: TODO */
2548 e1833e1f j_mayer
        cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2549 e1833e1f j_mayer
        goto store_next;
2550 e1833e1f j_mayer
    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
2551 e1833e1f j_mayer
        /* XXX: TODO */
2552 e1833e1f j_mayer
        cpu_abort(env,
2553 e1833e1f j_mayer
                  "970 soft-patch exception is not implemented yet !\n");
2554 e1833e1f j_mayer
        goto store_next;
2555 e1833e1f j_mayer
    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
2556 e1833e1f j_mayer
        /* XXX: TODO */
2557 e1833e1f j_mayer
        cpu_abort(env,
2558 e1833e1f j_mayer
                  "970 maintenance exception is not implemented yet !\n");
2559 e1833e1f j_mayer
        goto store_next;
2560 2be0071f bellard
    default:
2561 e1833e1f j_mayer
    excp_invalid:
2562 e1833e1f j_mayer
        cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2563 e1833e1f j_mayer
        break;
2564 9a64fbe4 bellard
    store_current:
2565 2be0071f bellard
        /* save current instruction location */
2566 e1833e1f j_mayer
        env->spr[srr0] = env->nip - 4;
2567 9a64fbe4 bellard
        break;
2568 9a64fbe4 bellard
    store_next:
2569 2be0071f bellard
        /* save next instruction location */
2570 e1833e1f j_mayer
        env->spr[srr0] = env->nip;
2571 9a64fbe4 bellard
        break;
2572 9a64fbe4 bellard
    }
2573 e1833e1f j_mayer
    /* Save MSR */
2574 e1833e1f j_mayer
    env->spr[srr1] = msr;
2575 e1833e1f j_mayer
    /* If any alternate SRR register are defined, duplicate saved values */
2576 e1833e1f j_mayer
    if (asrr0 != -1)
2577 e1833e1f j_mayer
        env->spr[asrr0] = env->spr[srr0];
2578 e1833e1f j_mayer
    if (asrr1 != -1)
2579 e1833e1f j_mayer
        env->spr[asrr1] = env->spr[srr1];
2580 2be0071f bellard
    /* If we disactivated any translation, flush TLBs */
2581 0411a972 j_mayer
    if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2582 2be0071f bellard
        tlb_flush(env, 1);
2583 9a64fbe4 bellard
    /* reload MSR with correct bits */
2584 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_EE);
2585 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_PR);
2586 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_FP);
2587 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_FE0);
2588 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_SE);
2589 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_BE);
2590 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_FE1);
2591 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_IR);
2592 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_DR);
2593 e1833e1f j_mayer
#if 0 /* Fix this: not on all targets */
2594 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_PMM);
2595 e1833e1f j_mayer
#endif
2596 0411a972 j_mayer
    new_msr &= ~((target_ulong)1 << MSR_LE);
2597 0411a972 j_mayer
    if (msr_ile)
2598 0411a972 j_mayer
        new_msr |= (target_ulong)1 << MSR_LE;
2599 0411a972 j_mayer
    else
2600 0411a972 j_mayer
        new_msr &= ~((target_ulong)1 << MSR_LE);
2601 e1833e1f j_mayer
    /* Jump to handler */
2602 e1833e1f j_mayer
    vector = env->excp_vectors[excp];
2603 e1833e1f j_mayer
    if (vector == (target_ulong)-1) {
2604 e1833e1f j_mayer
        cpu_abort(env, "Raised an exception without defined vector %d\n",
2605 e1833e1f j_mayer
                  excp);
2606 e1833e1f j_mayer
    }
2607 e1833e1f j_mayer
    vector |= env->excp_prefix;
2608 c62db105 j_mayer
#if defined(TARGET_PPC64)
2609 e1833e1f j_mayer
    if (excp_model == POWERPC_EXCP_BOOKE) {
2610 0411a972 j_mayer
        if (!msr_icm) {
2611 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_CM);
2612 e1833e1f j_mayer
            vector = (uint32_t)vector;
2613 0411a972 j_mayer
        } else {
2614 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_CM;
2615 0411a972 j_mayer
        }
2616 c62db105 j_mayer
    } else {
2617 0411a972 j_mayer
        if (!msr_isf) {
2618 0411a972 j_mayer
            new_msr &= ~((target_ulong)1 << MSR_SF);
2619 e1833e1f j_mayer
            vector = (uint32_t)vector;
2620 0411a972 j_mayer
        } else {
2621 0411a972 j_mayer
            new_msr |= (target_ulong)1 << MSR_SF;
2622 0411a972 j_mayer
        }
2623 c62db105 j_mayer
    }
2624 e1833e1f j_mayer
#endif
2625 0411a972 j_mayer
    /* XXX: we don't use hreg_store_msr here as already have treated
2626 0411a972 j_mayer
     *      any special case that could occur. Just store MSR and update hflags
2627 0411a972 j_mayer
     */
2628 0411a972 j_mayer
    env->msr = new_msr;
2629 0411a972 j_mayer
    hreg_compute_hflags(env);
2630 e1833e1f j_mayer
    env->nip = vector;
2631 e1833e1f j_mayer
    /* Reset exception state */
2632 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2633 e1833e1f j_mayer
    env->error_code = 0;
2634 fb0eaffc bellard
}
2635 47103572 j_mayer
2636 e1833e1f j_mayer
void do_interrupt (CPUState *env)
2637 47103572 j_mayer
{
2638 e1833e1f j_mayer
    powerpc_excp(env, env->excp_model, env->exception_index);
2639 e1833e1f j_mayer
}
2640 47103572 j_mayer
2641 e1833e1f j_mayer
void ppc_hw_interrupt (CPUPPCState *env)
2642 e1833e1f j_mayer
{
2643 f9fdea6b j_mayer
#if defined(TARGET_PPC64H)
2644 f9fdea6b j_mayer
    int hdice;
2645 f9fdea6b j_mayer
#endif
2646 f9fdea6b j_mayer
2647 0411a972 j_mayer
#if 0
2648 a496775f j_mayer
    if (loglevel & CPU_LOG_INT) {
2649 a496775f j_mayer
        fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
2650 a496775f j_mayer
                __func__, env, env->pending_interrupts,
2651 0411a972 j_mayer
                env->interrupt_request, (int)msr_me, (int)msr_ee);
2652 a496775f j_mayer
    }
2653 47103572 j_mayer
#endif
2654 e1833e1f j_mayer
    /* External reset */
2655 47103572 j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2656 47103572 j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2657 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2658 e1833e1f j_mayer
        return;
2659 e1833e1f j_mayer
    }
2660 e1833e1f j_mayer
    /* Machine check exception */
2661 e1833e1f j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2662 e1833e1f j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2663 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2664 e1833e1f j_mayer
        return;
2665 47103572 j_mayer
    }
2666 e1833e1f j_mayer
#if 0 /* TODO */
2667 e1833e1f j_mayer
    /* External debug exception */
2668 e1833e1f j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2669 e1833e1f j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2670 e1833e1f j_mayer
        powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2671 e1833e1f j_mayer
        return;
2672 e1833e1f j_mayer
    }
2673 e1833e1f j_mayer
#endif
2674 e1833e1f j_mayer
#if defined(TARGET_PPC64H)
2675 f9fdea6b j_mayer
    hdice = env->spr[SPR_LPCR] & 1;
2676 f9fdea6b j_mayer
    if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2677 47103572 j_mayer
        /* Hypervisor decrementer exception */
2678 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2679 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2680 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2681 e1833e1f j_mayer
            return;
2682 e1833e1f j_mayer
        }
2683 e1833e1f j_mayer
    }
2684 e1833e1f j_mayer
#endif
2685 e1833e1f j_mayer
    if (msr_ce != 0) {
2686 e1833e1f j_mayer
        /* External critical interrupt */
2687 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2688 e1833e1f j_mayer
            /* Taking a critical external interrupt does not clear the external
2689 e1833e1f j_mayer
             * critical interrupt status
2690 e1833e1f j_mayer
             */
2691 e1833e1f j_mayer
#if 0
2692 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2693 47103572 j_mayer
#endif
2694 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2695 e1833e1f j_mayer
            return;
2696 e1833e1f j_mayer
        }
2697 e1833e1f j_mayer
    }
2698 e1833e1f j_mayer
    if (msr_ee != 0) {
2699 e1833e1f j_mayer
        /* Watchdog timer on embedded PowerPC */
2700 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2701 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2702 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2703 e1833e1f j_mayer
            return;
2704 e1833e1f j_mayer
        }
2705 e1833e1f j_mayer
#if defined(TARGET_PPCEMB)
2706 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2707 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2708 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2709 e1833e1f j_mayer
            return;
2710 e1833e1f j_mayer
        }
2711 e1833e1f j_mayer
#endif
2712 e1833e1f j_mayer
#if defined(TARGET_PPCEMB)
2713 e1833e1f j_mayer
        /* External interrupt */
2714 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2715 e1833e1f j_mayer
            /* Taking an external interrupt does not clear the external
2716 e1833e1f j_mayer
             * interrupt status
2717 e1833e1f j_mayer
             */
2718 e1833e1f j_mayer
#if 0
2719 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2720 e1833e1f j_mayer
#endif
2721 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2722 e1833e1f j_mayer
            return;
2723 e1833e1f j_mayer
        }
2724 e1833e1f j_mayer
#endif
2725 e1833e1f j_mayer
        /* Fixed interval timer on embedded PowerPC */
2726 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2727 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2728 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2729 e1833e1f j_mayer
            return;
2730 e1833e1f j_mayer
        }
2731 e1833e1f j_mayer
        /* Programmable interval timer on embedded PowerPC */
2732 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2733 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2734 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2735 e1833e1f j_mayer
            return;
2736 e1833e1f j_mayer
        }
2737 47103572 j_mayer
        /* Decrementer exception */
2738 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2739 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2740 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2741 e1833e1f j_mayer
            return;
2742 e1833e1f j_mayer
        }
2743 e1833e1f j_mayer
#if !defined(TARGET_PPCEMB)
2744 47103572 j_mayer
        /* External interrupt */
2745 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2746 e9df014c j_mayer
            /* Taking an external interrupt does not clear the external
2747 e9df014c j_mayer
             * interrupt status
2748 e9df014c j_mayer
             */
2749 e9df014c j_mayer
#if 0
2750 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2751 e9df014c j_mayer
#endif
2752 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2753 e1833e1f j_mayer
            return;
2754 e1833e1f j_mayer
        }
2755 d0dfae6e j_mayer
#endif
2756 e1833e1f j_mayer
#if defined(TARGET_PPCEMB)
2757 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2758 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2759 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2760 e1833e1f j_mayer
            return;
2761 47103572 j_mayer
        }
2762 47103572 j_mayer
#endif
2763 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2764 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2765 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2766 e1833e1f j_mayer
            return;
2767 e1833e1f j_mayer
        }
2768 e1833e1f j_mayer
        /* Thermal interrupt */
2769 e1833e1f j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2770 e1833e1f j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2771 e1833e1f j_mayer
            powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2772 e1833e1f j_mayer
            return;
2773 e1833e1f j_mayer
        }
2774 47103572 j_mayer
    }
2775 47103572 j_mayer
}
2776 18fba28c bellard
#endif /* !CONFIG_USER_ONLY */
2777 a496775f j_mayer
2778 a496775f j_mayer
void cpu_dump_EA (target_ulong EA)
2779 a496775f j_mayer
{
2780 a496775f j_mayer
    FILE *f;
2781 a496775f j_mayer
2782 a496775f j_mayer
    if (logfile) {
2783 a496775f j_mayer
        f = logfile;
2784 a496775f j_mayer
    } else {
2785 a496775f j_mayer
        f = stdout;
2786 a496775f j_mayer
        return;
2787 a496775f j_mayer
    }
2788 4a057712 j_mayer
    fprintf(f, "Memory access at address " ADDRX "\n", EA);
2789 4a057712 j_mayer
}
2790 4a057712 j_mayer
2791 4a057712 j_mayer
void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2792 4a057712 j_mayer
{
2793 4a057712 j_mayer
    FILE *f;
2794 4a057712 j_mayer
2795 4a057712 j_mayer
    if (logfile) {
2796 4a057712 j_mayer
        f = logfile;
2797 4a057712 j_mayer
    } else {
2798 4a057712 j_mayer
        f = stdout;
2799 4a057712 j_mayer
        return;
2800 4a057712 j_mayer
    }
2801 4a057712 j_mayer
    fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
2802 4a057712 j_mayer
            RA, msr);
2803 a496775f j_mayer
}
2804 a496775f j_mayer
2805 0a032cbe j_mayer
void cpu_ppc_reset (void *opaque)
2806 0a032cbe j_mayer
{
2807 0a032cbe j_mayer
    CPUPPCState *env;
2808 0411a972 j_mayer
    target_ulong msr;
2809 0a032cbe j_mayer
2810 0a032cbe j_mayer
    env = opaque;
2811 0411a972 j_mayer
    msr = (target_ulong)0;
2812 5eb7995e j_mayer
#if defined(TARGET_PPC64)
2813 0411a972 j_mayer
    msr |= (target_ulong)0 << MSR_HV; /* Should be 1... */
2814 5eb7995e j_mayer
#endif
2815 0411a972 j_mayer
    msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2816 0411a972 j_mayer
    msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2817 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_EP;
2818 0a032cbe j_mayer
#if defined (DO_SINGLE_STEP) && 0
2819 0a032cbe j_mayer
    /* Single step trace mode */
2820 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_SE;
2821 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_BE;
2822 0a032cbe j_mayer
#endif
2823 0a032cbe j_mayer
#if defined(CONFIG_USER_ONLY)
2824 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2825 0411a972 j_mayer
    msr |= (target_ulong)1 << MSR_PR;
2826 0a032cbe j_mayer
#else
2827 1c27f8fb j_mayer
    env->nip = env->hreset_vector | env->excp_prefix;
2828 141c8ae2 j_mayer
    if (env->mmu_model != POWERPC_MMU_REAL_4xx)
2829 141c8ae2 j_mayer
        ppc_tlb_invalidate_all(env);
2830 0a032cbe j_mayer
#endif
2831 0411a972 j_mayer
    env->msr = msr;
2832 0411a972 j_mayer
    hreg_compute_hflags(env);
2833 0a032cbe j_mayer
    env->reserve = -1;
2834 5eb7995e j_mayer
    /* Be sure no exception or interrupt is pending */
2835 5eb7995e j_mayer
    env->pending_interrupts = 0;
2836 e1833e1f j_mayer
    env->exception_index = POWERPC_EXCP_NONE;
2837 e1833e1f j_mayer
    env->error_code = 0;
2838 5eb7995e j_mayer
    /* Flush all TLBs */
2839 5eb7995e j_mayer
    tlb_flush(env, 1);
2840 0a032cbe j_mayer
}
2841 0a032cbe j_mayer
2842 0a032cbe j_mayer
CPUPPCState *cpu_ppc_init (void)
2843 0a032cbe j_mayer
{
2844 0a032cbe j_mayer
    CPUPPCState *env;
2845 0a032cbe j_mayer
2846 0a032cbe j_mayer
    env = qemu_mallocz(sizeof(CPUPPCState));
2847 0a032cbe j_mayer
    if (!env)
2848 0a032cbe j_mayer
        return NULL;
2849 0a032cbe j_mayer
    cpu_exec_init(env);
2850 0a032cbe j_mayer
2851 0a032cbe j_mayer
    return env;
2852 0a032cbe j_mayer
}
2853 0a032cbe j_mayer
2854 0a032cbe j_mayer
void cpu_ppc_close (CPUPPCState *env)
2855 0a032cbe j_mayer
{
2856 0a032cbe j_mayer
    /* Should also remove all opcode tables... */
2857 0a032cbe j_mayer
    free(env);
2858 0a032cbe j_mayer
}