Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ e9df014c

History | View | Annotate | Download (62.9 kB)

1 79aceca5 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 79aceca5 bellard
 * 
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 9a64fbe4 bellard
31 9a64fbe4 bellard
//#define DEBUG_MMU
32 9a64fbe4 bellard
//#define DEBUG_BATS
33 76a66253 j_mayer
//#define DEBUG_SOFTWARE_TLB
34 9a64fbe4 bellard
//#define DEBUG_EXCEPTIONS
35 fdabc366 bellard
//#define FLUSH_ALL_TLBS
36 9a64fbe4 bellard
37 9a64fbe4 bellard
/*****************************************************************************/
38 3fc6c082 bellard
/* PowerPC MMU emulation */
39 a541f297 bellard
40 d9bce9d9 j_mayer
#if defined(CONFIG_USER_ONLY)
41 24741ef3 bellard
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
42 24741ef3 bellard
                              int is_user, int is_softmmu)
43 24741ef3 bellard
{
44 24741ef3 bellard
    int exception, error_code;
45 d9bce9d9 j_mayer
46 24741ef3 bellard
    if (rw == 2) {
47 24741ef3 bellard
        exception = EXCP_ISI;
48 24741ef3 bellard
        error_code = 0;
49 24741ef3 bellard
    } else {
50 24741ef3 bellard
        exception = EXCP_DSI;
51 24741ef3 bellard
        error_code = 0;
52 24741ef3 bellard
        if (rw)
53 24741ef3 bellard
            error_code |= 0x02000000;
54 24741ef3 bellard
        env->spr[SPR_DAR] = address;
55 24741ef3 bellard
        env->spr[SPR_DSISR] = error_code;
56 24741ef3 bellard
    }
57 24741ef3 bellard
    env->exception_index = exception;
58 24741ef3 bellard
    env->error_code = error_code;
59 76a66253 j_mayer
60 24741ef3 bellard
    return 1;
61 24741ef3 bellard
}
62 76a66253 j_mayer
63 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
64 24741ef3 bellard
{
65 24741ef3 bellard
    return addr;
66 24741ef3 bellard
}
67 24741ef3 bellard
#else
68 76a66253 j_mayer
/* Common routines used by software and hardware TLBs emulation */
69 76a66253 j_mayer
static inline int pte_is_valid (target_ulong pte0)
70 76a66253 j_mayer
{
71 76a66253 j_mayer
    return pte0 & 0x80000000 ? 1 : 0;
72 76a66253 j_mayer
}
73 76a66253 j_mayer
74 76a66253 j_mayer
static inline void pte_invalidate (target_ulong *pte0)
75 76a66253 j_mayer
{
76 76a66253 j_mayer
    *pte0 &= ~0x80000000;
77 76a66253 j_mayer
}
78 76a66253 j_mayer
79 76a66253 j_mayer
#define PTE_PTEM_MASK 0x7FFFFFBF
80 76a66253 j_mayer
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
81 76a66253 j_mayer
82 76a66253 j_mayer
static int pte_check (mmu_ctx_t *ctx,
83 76a66253 j_mayer
                      target_ulong pte0, target_ulong pte1, int h, int rw)
84 76a66253 j_mayer
{
85 76a66253 j_mayer
    int access, ret;
86 76a66253 j_mayer
87 76a66253 j_mayer
    access = 0;
88 76a66253 j_mayer
    ret = -1;
89 76a66253 j_mayer
    /* Check validity and table match */
90 76a66253 j_mayer
    if (pte_is_valid(pte0) && (h == ((pte0 >> 6) & 1))) {
91 76a66253 j_mayer
        /* Check vsid & api */
92 76a66253 j_mayer
        if ((pte0 & PTE_PTEM_MASK) == ctx->ptem) {
93 76a66253 j_mayer
            if (ctx->raddr != (target_ulong)-1) {
94 76a66253 j_mayer
                /* all matches should have equal RPN, WIMG & PP */
95 76a66253 j_mayer
                if ((ctx->raddr & PTE_CHECK_MASK) != (pte1 & PTE_CHECK_MASK)) {
96 76a66253 j_mayer
                    if (loglevel > 0)
97 76a66253 j_mayer
                        fprintf(logfile, "Bad RPN/WIMG/PP\n");
98 76a66253 j_mayer
                    return -3;
99 76a66253 j_mayer
                }
100 76a66253 j_mayer
            }
101 76a66253 j_mayer
            /* Compute access rights */
102 76a66253 j_mayer
            if (ctx->key == 0) {
103 76a66253 j_mayer
                access = PAGE_READ;
104 76a66253 j_mayer
                if ((pte1 & 0x00000003) != 0x3)
105 76a66253 j_mayer
                    access |= PAGE_WRITE;
106 76a66253 j_mayer
            } else {
107 76a66253 j_mayer
                switch (pte1 & 0x00000003) {
108 76a66253 j_mayer
                case 0x0:
109 76a66253 j_mayer
                    access = 0;
110 76a66253 j_mayer
                    break;
111 76a66253 j_mayer
                case 0x1:
112 76a66253 j_mayer
                case 0x3:
113 76a66253 j_mayer
                    access = PAGE_READ;
114 76a66253 j_mayer
                    break;
115 76a66253 j_mayer
                case 0x2:
116 76a66253 j_mayer
                    access = PAGE_READ | PAGE_WRITE;
117 76a66253 j_mayer
                    break;
118 76a66253 j_mayer
                }
119 76a66253 j_mayer
            }
120 76a66253 j_mayer
            /* Keep the matching PTE informations */
121 76a66253 j_mayer
            ctx->raddr = pte1;
122 76a66253 j_mayer
            ctx->prot = access;
123 76a66253 j_mayer
            if ((rw == 0 && (access & PAGE_READ)) ||
124 76a66253 j_mayer
                (rw == 1 && (access & PAGE_WRITE))) {
125 76a66253 j_mayer
                /* Access granted */
126 76a66253 j_mayer
#if defined (DEBUG_MMU)
127 76a66253 j_mayer
                if (loglevel > 0)
128 76a66253 j_mayer
                    fprintf(logfile, "PTE access granted !\n");
129 76a66253 j_mayer
#endif
130 76a66253 j_mayer
                ret = 0;
131 76a66253 j_mayer
            } else {
132 76a66253 j_mayer
                /* Access right violation */
133 76a66253 j_mayer
#if defined (DEBUG_MMU)
134 76a66253 j_mayer
                if (loglevel > 0)
135 76a66253 j_mayer
                    fprintf(logfile, "PTE access rejected\n");
136 76a66253 j_mayer
#endif
137 76a66253 j_mayer
                ret = -2;
138 76a66253 j_mayer
            }
139 76a66253 j_mayer
        }
140 76a66253 j_mayer
    }
141 76a66253 j_mayer
142 76a66253 j_mayer
    return ret;
143 76a66253 j_mayer
}
144 76a66253 j_mayer
145 76a66253 j_mayer
static int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
146 76a66253 j_mayer
                             int ret, int rw)
147 76a66253 j_mayer
{
148 76a66253 j_mayer
    int store = 0;
149 76a66253 j_mayer
150 76a66253 j_mayer
    /* Update page flags */
151 76a66253 j_mayer
    if (!(*pte1p & 0x00000100)) {
152 76a66253 j_mayer
        /* Update accessed flag */
153 76a66253 j_mayer
        *pte1p |= 0x00000100;
154 76a66253 j_mayer
        store = 1;
155 76a66253 j_mayer
    }
156 76a66253 j_mayer
    if (!(*pte1p & 0x00000080)) {
157 76a66253 j_mayer
        if (rw == 1 && ret == 0) {
158 76a66253 j_mayer
            /* Update changed flag */
159 76a66253 j_mayer
            *pte1p |= 0x00000080;
160 76a66253 j_mayer
            store = 1;
161 76a66253 j_mayer
        } else {
162 76a66253 j_mayer
            /* Force page fault for first write access */
163 76a66253 j_mayer
            ctx->prot &= ~PAGE_WRITE;
164 76a66253 j_mayer
        }
165 76a66253 j_mayer
    }
166 76a66253 j_mayer
167 76a66253 j_mayer
    return store;
168 76a66253 j_mayer
}
169 76a66253 j_mayer
170 76a66253 j_mayer
/* Software driven TLB helpers */
171 76a66253 j_mayer
static int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
172 76a66253 j_mayer
                              int way, int is_code)
173 76a66253 j_mayer
{
174 76a66253 j_mayer
    int nr;
175 76a66253 j_mayer
176 76a66253 j_mayer
    /* Select TLB num in a way from address */
177 76a66253 j_mayer
    nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
178 76a66253 j_mayer
    /* Select TLB way */
179 76a66253 j_mayer
    nr += env->tlb_per_way * way;
180 76a66253 j_mayer
    /* 6xx have separate TLBs for instructions and data */
181 76a66253 j_mayer
    if (is_code && env->id_tlbs == 1)
182 76a66253 j_mayer
        nr += env->nb_tlb;
183 76a66253 j_mayer
184 76a66253 j_mayer
    return nr;
185 76a66253 j_mayer
}
186 76a66253 j_mayer
187 76a66253 j_mayer
void ppc6xx_tlb_invalidate_all (CPUState *env)
188 76a66253 j_mayer
{
189 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
190 76a66253 j_mayer
    int nr, max;
191 76a66253 j_mayer
192 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB) && 0
193 76a66253 j_mayer
    if (loglevel != 0) {
194 76a66253 j_mayer
        fprintf(logfile, "Invalidate all TLBs\n");
195 76a66253 j_mayer
    }
196 76a66253 j_mayer
#endif
197 76a66253 j_mayer
    /* Invalidate all defined software TLB */
198 76a66253 j_mayer
    max = env->nb_tlb;
199 76a66253 j_mayer
    if (env->id_tlbs == 1)
200 76a66253 j_mayer
        max *= 2;
201 76a66253 j_mayer
    for (nr = 0; nr < max; nr++) {
202 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
203 76a66253 j_mayer
#if !defined(FLUSH_ALL_TLBS)
204 76a66253 j_mayer
        tlb_flush_page(env, tlb->EPN);
205 76a66253 j_mayer
#endif
206 76a66253 j_mayer
        pte_invalidate(&tlb->pte0);
207 76a66253 j_mayer
    }
208 76a66253 j_mayer
#if defined(FLUSH_ALL_TLBS)
209 76a66253 j_mayer
    tlb_flush(env, 1);
210 76a66253 j_mayer
#endif
211 76a66253 j_mayer
}
212 76a66253 j_mayer
213 76a66253 j_mayer
static inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
214 76a66253 j_mayer
                                                 target_ulong eaddr,
215 76a66253 j_mayer
                                                 int is_code, int match_epn)
216 76a66253 j_mayer
{
217 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
218 76a66253 j_mayer
    int way, nr;
219 76a66253 j_mayer
220 76a66253 j_mayer
#if !defined(FLUSH_ALL_TLBS)
221 76a66253 j_mayer
    /* Invalidate ITLB + DTLB, all ways */
222 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
223 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
224 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
225 76a66253 j_mayer
        if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
226 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
227 76a66253 j_mayer
            if (loglevel != 0) {
228 1b9eb036 j_mayer
                fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
229 76a66253 j_mayer
                        nr, env->nb_tlb, eaddr);
230 76a66253 j_mayer
            }
231 76a66253 j_mayer
#endif
232 76a66253 j_mayer
            pte_invalidate(&tlb->pte0);
233 76a66253 j_mayer
            tlb_flush_page(env, tlb->EPN);
234 76a66253 j_mayer
        }
235 76a66253 j_mayer
    }
236 76a66253 j_mayer
#else
237 76a66253 j_mayer
    /* XXX: PowerPC specification say this is valid as well */
238 76a66253 j_mayer
    ppc6xx_tlb_invalidate_all(env);
239 76a66253 j_mayer
#endif
240 76a66253 j_mayer
}
241 76a66253 j_mayer
242 76a66253 j_mayer
void ppc6xx_tlb_invalidate_virt (CPUState *env, target_ulong eaddr,
243 76a66253 j_mayer
                                 int is_code)
244 76a66253 j_mayer
{
245 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
246 76a66253 j_mayer
}
247 76a66253 j_mayer
248 76a66253 j_mayer
void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
249 76a66253 j_mayer
                       target_ulong pte0, target_ulong pte1)
250 76a66253 j_mayer
{
251 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
252 76a66253 j_mayer
    int nr;
253 76a66253 j_mayer
254 76a66253 j_mayer
    nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
255 1d0a48fb j_mayer
    tlb = &env->tlb[nr].tlb6;
256 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
257 76a66253 j_mayer
    if (loglevel != 0) {
258 1b9eb036 j_mayer
        fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX 
259 1b9eb036 j_mayer
                " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
260 76a66253 j_mayer
    }
261 76a66253 j_mayer
#endif
262 76a66253 j_mayer
    /* Invalidate any pending reference in Qemu for this virtual address */
263 76a66253 j_mayer
    __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
264 76a66253 j_mayer
    tlb->pte0 = pte0;
265 76a66253 j_mayer
    tlb->pte1 = pte1;
266 76a66253 j_mayer
    tlb->EPN = EPN;
267 76a66253 j_mayer
    /* Store last way for LRU mechanism */
268 76a66253 j_mayer
    env->last_way = way;
269 76a66253 j_mayer
}
270 76a66253 j_mayer
271 76a66253 j_mayer
static int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
272 76a66253 j_mayer
                             target_ulong eaddr, int rw, int access_type)
273 76a66253 j_mayer
{
274 1d0a48fb j_mayer
    ppc6xx_tlb_t *tlb;
275 76a66253 j_mayer
    int nr, best, way;
276 76a66253 j_mayer
    int ret;
277 d9bce9d9 j_mayer
278 76a66253 j_mayer
    best = -1;
279 76a66253 j_mayer
    ret = -1; /* No TLB found */
280 76a66253 j_mayer
    for (way = 0; way < env->nb_ways; way++) {
281 76a66253 j_mayer
        nr = ppc6xx_tlb_getnum(env, eaddr, way,
282 76a66253 j_mayer
                               access_type == ACCESS_CODE ? 1 : 0);
283 1d0a48fb j_mayer
        tlb = &env->tlb[nr].tlb6;
284 76a66253 j_mayer
        /* This test "emulates" the PTE index match for hardware TLBs */
285 76a66253 j_mayer
        if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
286 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
287 76a66253 j_mayer
            if (loglevel != 0) {
288 1b9eb036 j_mayer
                fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
289 1b9eb036 j_mayer
                        "] <> " ADDRX "\n",
290 76a66253 j_mayer
                        nr, env->nb_tlb,
291 76a66253 j_mayer
                        pte_is_valid(tlb->pte0) ? "valid" : "inval",
292 76a66253 j_mayer
                        tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
293 76a66253 j_mayer
            }
294 76a66253 j_mayer
#endif
295 76a66253 j_mayer
            continue;
296 76a66253 j_mayer
        }
297 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
298 76a66253 j_mayer
        if (loglevel != 0) {
299 1b9eb036 j_mayer
            fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
300 1b9eb036 j_mayer
                    " %c %c\n",
301 76a66253 j_mayer
                    nr, env->nb_tlb,
302 76a66253 j_mayer
                    pte_is_valid(tlb->pte0) ? "valid" : "inval",
303 76a66253 j_mayer
                    tlb->EPN, eaddr, tlb->pte1,
304 76a66253 j_mayer
                    rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
305 76a66253 j_mayer
        }
306 76a66253 j_mayer
#endif
307 76a66253 j_mayer
        switch (pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw)) {
308 76a66253 j_mayer
        case -3:
309 76a66253 j_mayer
            /* TLB inconsistency */
310 76a66253 j_mayer
            return -1;
311 76a66253 j_mayer
        case -2:
312 76a66253 j_mayer
            /* Access violation */
313 76a66253 j_mayer
            ret = -2;
314 76a66253 j_mayer
            best = nr;
315 76a66253 j_mayer
            break;
316 76a66253 j_mayer
        case -1:
317 76a66253 j_mayer
        default:
318 76a66253 j_mayer
            /* No match */
319 76a66253 j_mayer
            break;
320 76a66253 j_mayer
        case 0:
321 76a66253 j_mayer
            /* access granted */
322 76a66253 j_mayer
            /* XXX: we should go on looping to check all TLBs consistency
323 76a66253 j_mayer
             *      but we can speed-up the whole thing as the
324 76a66253 j_mayer
             *      result would be undefined if TLBs are not consistent.
325 76a66253 j_mayer
             */
326 76a66253 j_mayer
            ret = 0;
327 76a66253 j_mayer
            best = nr;
328 76a66253 j_mayer
            goto done;
329 76a66253 j_mayer
        }
330 76a66253 j_mayer
    }
331 76a66253 j_mayer
    if (best != -1) {
332 76a66253 j_mayer
    done:
333 76a66253 j_mayer
#if defined (DEBUG_SOFTWARE_TLB)
334 76a66253 j_mayer
        if (loglevel > 0) {
335 76a66253 j_mayer
            fprintf(logfile, "found TLB at addr 0x%08lx prot=0x%01x ret=%d\n",
336 76a66253 j_mayer
                    ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
337 76a66253 j_mayer
        }
338 76a66253 j_mayer
#endif
339 76a66253 j_mayer
        /* Update page flags */
340 1d0a48fb j_mayer
        pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
341 76a66253 j_mayer
    }
342 76a66253 j_mayer
343 76a66253 j_mayer
    return ret;
344 76a66253 j_mayer
}
345 76a66253 j_mayer
346 9a64fbe4 bellard
/* Perform BAT hit & translation */
347 76a66253 j_mayer
static int get_bat (CPUState *env, mmu_ctx_t *ctx,
348 76a66253 j_mayer
                    target_ulong virtual, int rw, int type)
349 9a64fbe4 bellard
{
350 76a66253 j_mayer
    target_ulong *BATlt, *BATut, *BATu, *BATl;
351 76a66253 j_mayer
    target_ulong base, BEPIl, BEPIu, bl;
352 9a64fbe4 bellard
    int i;
353 9a64fbe4 bellard
    int ret = -1;
354 9a64fbe4 bellard
355 9a64fbe4 bellard
#if defined (DEBUG_BATS)
356 9a64fbe4 bellard
    if (loglevel > 0) {
357 1b9eb036 j_mayer
        fprintf(logfile, "%s: %cBAT v 0x" ADDRX "\n", __func__,
358 76a66253 j_mayer
                type == ACCESS_CODE ? 'I' : 'D', virtual);
359 9a64fbe4 bellard
    }
360 9a64fbe4 bellard
#endif
361 9a64fbe4 bellard
    switch (type) {
362 9a64fbe4 bellard
    case ACCESS_CODE:
363 9a64fbe4 bellard
        BATlt = env->IBAT[1];
364 9a64fbe4 bellard
        BATut = env->IBAT[0];
365 9a64fbe4 bellard
        break;
366 9a64fbe4 bellard
    default:
367 9a64fbe4 bellard
        BATlt = env->DBAT[1];
368 9a64fbe4 bellard
        BATut = env->DBAT[0];
369 9a64fbe4 bellard
        break;
370 9a64fbe4 bellard
    }
371 9a64fbe4 bellard
#if defined (DEBUG_BATS)
372 9a64fbe4 bellard
    if (loglevel > 0) {
373 1b9eb036 j_mayer
        fprintf(logfile, "%s...: %cBAT v 0x" ADDRX "\n", __func__,
374 76a66253 j_mayer
                type == ACCESS_CODE ? 'I' : 'D', virtual);
375 9a64fbe4 bellard
    }
376 9a64fbe4 bellard
#endif
377 9a64fbe4 bellard
    base = virtual & 0xFFFC0000;
378 9a64fbe4 bellard
    for (i = 0; i < 4; i++) {
379 9a64fbe4 bellard
        BATu = &BATut[i];
380 9a64fbe4 bellard
        BATl = &BATlt[i];
381 9a64fbe4 bellard
        BEPIu = *BATu & 0xF0000000;
382 9a64fbe4 bellard
        BEPIl = *BATu & 0x0FFE0000;
383 9a64fbe4 bellard
        bl = (*BATu & 0x00001FFC) << 15;
384 9a64fbe4 bellard
#if defined (DEBUG_BATS)
385 9a64fbe4 bellard
        if (loglevel > 0) {
386 1b9eb036 j_mayer
            fprintf(logfile, "%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX 
387 1b9eb036 j_mayer
                    " BATl 0x" ADDRX "\n",
388 9a64fbe4 bellard
                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
389 9a64fbe4 bellard
                    *BATu, *BATl);
390 9a64fbe4 bellard
        }
391 9a64fbe4 bellard
#endif
392 9a64fbe4 bellard
        if ((virtual & 0xF0000000) == BEPIu &&
393 9a64fbe4 bellard
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
394 9a64fbe4 bellard
            /* BAT matches */
395 9a64fbe4 bellard
            if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
396 9a64fbe4 bellard
                (msr_pr == 1 && (*BATu & 0x00000001))) {
397 9a64fbe4 bellard
                /* Get physical address */
398 76a66253 j_mayer
                ctx->raddr = (*BATl & 0xF0000000) |
399 9a64fbe4 bellard
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
400 a541f297 bellard
                    (virtual & 0x0001F000);
401 9a64fbe4 bellard
                if (*BATl & 0x00000001)
402 76a66253 j_mayer
                    ctx->prot = PAGE_READ;
403 9a64fbe4 bellard
                if (*BATl & 0x00000002)
404 76a66253 j_mayer
                    ctx->prot = PAGE_WRITE | PAGE_READ;
405 9a64fbe4 bellard
#if defined (DEBUG_BATS)
406 9a64fbe4 bellard
                if (loglevel > 0) {
407 1b9eb036 j_mayer
                    fprintf(logfile, "BAT %d match: r 0x" ADDRX
408 1b9eb036 j_mayer
                            " prot=%c%c\n",
409 76a66253 j_mayer
                            i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
410 76a66253 j_mayer
                            ctx->prot & PAGE_WRITE ? 'W' : '-');
411 9a64fbe4 bellard
                }
412 9a64fbe4 bellard
#endif
413 9a64fbe4 bellard
                ret = 0;
414 9a64fbe4 bellard
                break;
415 9a64fbe4 bellard
            }
416 9a64fbe4 bellard
        }
417 9a64fbe4 bellard
    }
418 9a64fbe4 bellard
    if (ret < 0) {
419 9a64fbe4 bellard
#if defined (DEBUG_BATS)
420 1b9eb036 j_mayer
        printf("no BAT match for 0x" ADDRX ":\n", virtual);
421 9a64fbe4 bellard
        for (i = 0; i < 4; i++) {
422 9a64fbe4 bellard
            BATu = &BATut[i];
423 9a64fbe4 bellard
            BATl = &BATlt[i];
424 9a64fbe4 bellard
            BEPIu = *BATu & 0xF0000000;
425 9a64fbe4 bellard
            BEPIl = *BATu & 0x0FFE0000;
426 9a64fbe4 bellard
            bl = (*BATu & 0x00001FFC) << 15;
427 1b9eb036 j_mayer
            printf("%s: %cBAT%d v 0x" ADDRX " BATu 0x" ADDRX
428 1b9eb036 j_mayer
                   " BATl 0x" ADDRX " \n\t"
429 1b9eb036 j_mayer
                   "0x" ADDRX " 0x" ADDRX " 0x" ADDRX "\n",
430 9a64fbe4 bellard
                   __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
431 9a64fbe4 bellard
                   *BATu, *BATl, BEPIu, BEPIl, bl);
432 9a64fbe4 bellard
        }
433 9a64fbe4 bellard
#endif
434 9a64fbe4 bellard
    }
435 9a64fbe4 bellard
    /* No hit */
436 9a64fbe4 bellard
    return ret;
437 9a64fbe4 bellard
}
438 9a64fbe4 bellard
439 9a64fbe4 bellard
/* PTE table lookup */
440 76a66253 j_mayer
static int find_pte (mmu_ctx_t *ctx, int h, int rw)
441 9a64fbe4 bellard
{
442 76a66253 j_mayer
    target_ulong base, pte0, pte1;
443 76a66253 j_mayer
    int i, good = -1;
444 76a66253 j_mayer
    int ret;
445 9a64fbe4 bellard
446 76a66253 j_mayer
    ret = -1; /* No entry found */
447 76a66253 j_mayer
    base = ctx->pg_addr[h];
448 9a64fbe4 bellard
    for (i = 0; i < 8; i++) {
449 8df1cd07 bellard
        pte0 = ldl_phys(base + (i * 8));
450 8df1cd07 bellard
        pte1 =  ldl_phys(base + (i * 8) + 4);
451 9a64fbe4 bellard
#if defined (DEBUG_MMU)
452 d094807b bellard
        if (loglevel > 0) {
453 1b9eb036 j_mayer
            fprintf(logfile, "Load pte from 0x" ADDRX " => 0x" ADDRX 
454 1b9eb036 j_mayer
                    " 0x" ADDRX " %d %d %d 0x" ADDRX "\n",
455 1b9eb036 j_mayer
                    base + (i * 8), pte0, pte1,
456 76a66253 j_mayer
                    pte0 >> 31, h, (pte0 >> 6) & 1, ctx->ptem);
457 76a66253 j_mayer
        }
458 9a64fbe4 bellard
#endif
459 76a66253 j_mayer
        switch (pte_check(ctx, pte0, pte1, h, rw)) {
460 76a66253 j_mayer
        case -3:
461 76a66253 j_mayer
            /* PTE inconsistency */
462 76a66253 j_mayer
            return -1;
463 76a66253 j_mayer
        case -2:
464 76a66253 j_mayer
            /* Access violation */
465 76a66253 j_mayer
            ret = -2;
466 76a66253 j_mayer
            good = i;
467 76a66253 j_mayer
            break;
468 76a66253 j_mayer
        case -1:
469 76a66253 j_mayer
        default:
470 76a66253 j_mayer
            /* No PTE match */
471 76a66253 j_mayer
            break;
472 76a66253 j_mayer
        case 0:
473 76a66253 j_mayer
            /* access granted */
474 76a66253 j_mayer
            /* XXX: we should go on looping to check all PTEs consistency
475 76a66253 j_mayer
             *      but if we can speed-up the whole thing as the
476 76a66253 j_mayer
             *      result would be undefined if PTEs are not consistent.
477 76a66253 j_mayer
             */
478 76a66253 j_mayer
            ret = 0;
479 76a66253 j_mayer
            good = i;
480 76a66253 j_mayer
            goto done;
481 9a64fbe4 bellard
        }
482 9a64fbe4 bellard
    }
483 9a64fbe4 bellard
    if (good != -1) {
484 76a66253 j_mayer
    done:
485 9a64fbe4 bellard
#if defined (DEBUG_MMU)
486 d094807b bellard
        if (loglevel > 0) {
487 1b9eb036 j_mayer
            fprintf(logfile, "found PTE at addr 0x" ADDRX " prot=0x%01x "
488 1b9eb036 j_mayer
                    "ret=%d\n",
489 76a66253 j_mayer
                    ctx->raddr, ctx->prot, ret);
490 76a66253 j_mayer
        }
491 9a64fbe4 bellard
#endif
492 9a64fbe4 bellard
        /* Update page flags */
493 76a66253 j_mayer
        pte1 = ctx->raddr;
494 76a66253 j_mayer
        if (pte_update_flags(ctx, &pte1, ret, rw) == 1)
495 76a66253 j_mayer
            stl_phys_notdirty(base + (good * 8) + 4, pte1);
496 9a64fbe4 bellard
    }
497 9a64fbe4 bellard
498 9a64fbe4 bellard
    return ret;
499 79aceca5 bellard
}
500 79aceca5 bellard
501 76a66253 j_mayer
static inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
502 76a66253 j_mayer
                                             target_phys_addr_t hash,
503 76a66253 j_mayer
                                             target_phys_addr_t mask)
504 79aceca5 bellard
{
505 9a64fbe4 bellard
    return (sdr1 & 0xFFFF0000) | (hash & mask);
506 79aceca5 bellard
}
507 79aceca5 bellard
508 9a64fbe4 bellard
/* Perform segment based translation */
509 76a66253 j_mayer
static int get_segment (CPUState *env, mmu_ctx_t *ctx,
510 76a66253 j_mayer
                        target_ulong eaddr, int rw, int type)
511 79aceca5 bellard
{
512 76a66253 j_mayer
    target_phys_addr_t sdr, hash, mask;
513 76a66253 j_mayer
    target_ulong sr, vsid, pgidx;
514 9a64fbe4 bellard
    int ret = -1, ret2;
515 79aceca5 bellard
516 76a66253 j_mayer
    sr = env->sr[eaddr >> 28];
517 9a64fbe4 bellard
#if defined (DEBUG_MMU)
518 a541f297 bellard
    if (loglevel > 0) {
519 1b9eb036 j_mayer
        fprintf(logfile, "Check segment v=0x" ADDRX " %d 0x" ADDRX " nip=0x"
520 1b9eb036 j_mayer
                ADDRX " lr=0x" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
521 76a66253 j_mayer
                eaddr, eaddr >> 28, sr, env->nip,
522 76a66253 j_mayer
                env->lr, msr_ir, msr_dr, msr_pr, rw, type);
523 a541f297 bellard
    }
524 9a64fbe4 bellard
#endif
525 76a66253 j_mayer
    ctx->key = (((sr & 0x20000000) && msr_pr == 1) ||
526 76a66253 j_mayer
                ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
527 9a64fbe4 bellard
    if ((sr & 0x80000000) == 0) {
528 9a64fbe4 bellard
#if defined (DEBUG_MMU)
529 76a66253 j_mayer
        if (loglevel > 0) 
530 1b9eb036 j_mayer
            fprintf(logfile, "pte segment: key=%d n=0x" ADDRX "\n",
531 76a66253 j_mayer
                    ctx->key, sr & 0x10000000);
532 9a64fbe4 bellard
#endif
533 9a64fbe4 bellard
        /* Check if instruction fetch is allowed, if needed */
534 9a64fbe4 bellard
        if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
535 9a64fbe4 bellard
            /* Page address translation */
536 76a66253 j_mayer
            pgidx = (eaddr >> TARGET_PAGE_BITS) & 0xFFFF;
537 9a64fbe4 bellard
            vsid = sr & 0x00FFFFFF;
538 a541f297 bellard
            hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
539 76a66253 j_mayer
            /* Primary table address */
540 76a66253 j_mayer
            sdr = env->sdr1;
541 9a64fbe4 bellard
            mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
542 76a66253 j_mayer
            ctx->pg_addr[0] = get_pgaddr(sdr, hash, mask);
543 76a66253 j_mayer
            /* Secondary table address */
544 76a66253 j_mayer
            hash = (~hash) & 0x01FFFFC0;
545 76a66253 j_mayer
            ctx->pg_addr[1] = get_pgaddr(sdr, hash, mask);
546 76a66253 j_mayer
            ctx->ptem = (vsid << 7) | (pgidx >> 10);
547 76a66253 j_mayer
            /* Initialize real address with an invalid value */
548 76a66253 j_mayer
            ctx->raddr = (target_ulong)-1;
549 76a66253 j_mayer
            if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
550 76a66253 j_mayer
                /* Software TLB search */
551 76a66253 j_mayer
                ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
552 76a66253 j_mayer
            } else {
553 9a64fbe4 bellard
#if defined (DEBUG_MMU)
554 76a66253 j_mayer
                if (loglevel > 0) {
555 1b9eb036 j_mayer
                    fprintf(logfile, "0 sdr1=0x" ADDRX " vsid=0x%06x "
556 1b9eb036 j_mayer
                            "api=0x%04x hash=0x%07x pg_addr=0x" ADDRX "\n",
557 1b9eb036 j_mayer
                            sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
558 76a66253 j_mayer
                }
559 9a64fbe4 bellard
#endif
560 76a66253 j_mayer
                /* Primary table lookup */
561 76a66253 j_mayer
                ret = find_pte(ctx, 0, rw);
562 76a66253 j_mayer
                if (ret < 0) {
563 76a66253 j_mayer
                    /* Secondary table lookup */
564 9a64fbe4 bellard
#if defined (DEBUG_MMU)
565 76a66253 j_mayer
                    if (eaddr != 0xEFFFFFFF && loglevel > 0) {
566 76a66253 j_mayer
                        fprintf(logfile,
567 1b9eb036 j_mayer
                                "1 sdr1=0x" ADDRX " vsid=0x%06x api=0x%04x "
568 1b9eb036 j_mayer
                                "hash=0x%05x pg_addr=0x" ADDRX "\n",
569 1b9eb036 j_mayer
                                sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
570 76a66253 j_mayer
                    }
571 9a64fbe4 bellard
#endif
572 76a66253 j_mayer
                    ret2 = find_pte(ctx, 1, rw);
573 76a66253 j_mayer
                    if (ret2 != -1)
574 76a66253 j_mayer
                        ret = ret2;
575 76a66253 j_mayer
                }
576 9a64fbe4 bellard
            }
577 9a64fbe4 bellard
        } else {
578 9a64fbe4 bellard
#if defined (DEBUG_MMU)
579 76a66253 j_mayer
            if (loglevel > 0)
580 76a66253 j_mayer
                fprintf(logfile, "No access allowed\n");
581 9a64fbe4 bellard
#endif
582 76a66253 j_mayer
            ret = -3;
583 9a64fbe4 bellard
        }
584 9a64fbe4 bellard
    } else {
585 9a64fbe4 bellard
#if defined (DEBUG_MMU)
586 a541f297 bellard
        if (loglevel > 0)
587 76a66253 j_mayer
            fprintf(logfile, "direct store...\n");
588 9a64fbe4 bellard
#endif
589 9a64fbe4 bellard
        /* Direct-store segment : absolutely *BUGGY* for now */
590 9a64fbe4 bellard
        switch (type) {
591 9a64fbe4 bellard
        case ACCESS_INT:
592 9a64fbe4 bellard
            /* Integer load/store : only access allowed */
593 9a64fbe4 bellard
            break;
594 9a64fbe4 bellard
        case ACCESS_CODE:
595 9a64fbe4 bellard
            /* No code fetch is allowed in direct-store areas */
596 9a64fbe4 bellard
            return -4;
597 9a64fbe4 bellard
        case ACCESS_FLOAT:
598 9a64fbe4 bellard
            /* Floating point load/store */
599 9a64fbe4 bellard
            return -4;
600 9a64fbe4 bellard
        case ACCESS_RES:
601 9a64fbe4 bellard
            /* lwarx, ldarx or srwcx. */
602 9a64fbe4 bellard
            return -4;
603 9a64fbe4 bellard
        case ACCESS_CACHE:
604 9a64fbe4 bellard
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
605 9a64fbe4 bellard
            /* Should make the instruction do no-op.
606 9a64fbe4 bellard
             * As it already do no-op, it's quite easy :-)
607 9a64fbe4 bellard
             */
608 76a66253 j_mayer
            ctx->raddr = eaddr;
609 9a64fbe4 bellard
            return 0;
610 9a64fbe4 bellard
        case ACCESS_EXT:
611 9a64fbe4 bellard
            /* eciwx or ecowx */
612 9a64fbe4 bellard
            return -4;
613 9a64fbe4 bellard
        default:
614 9a64fbe4 bellard
            if (logfile) {
615 9a64fbe4 bellard
                fprintf(logfile, "ERROR: instruction should not need "
616 9a64fbe4 bellard
                        "address translation\n");
617 9a64fbe4 bellard
            }
618 9a64fbe4 bellard
            printf("ERROR: instruction should not need "
619 9a64fbe4 bellard
                   "address translation\n");
620 9a64fbe4 bellard
            return -4;
621 9a64fbe4 bellard
        }
622 76a66253 j_mayer
        if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
623 76a66253 j_mayer
            ctx->raddr = eaddr;
624 9a64fbe4 bellard
            ret = 2;
625 9a64fbe4 bellard
        } else {
626 9a64fbe4 bellard
            ret = -2;
627 9a64fbe4 bellard
        }
628 79aceca5 bellard
    }
629 9a64fbe4 bellard
630 9a64fbe4 bellard
    return ret;
631 79aceca5 bellard
}
632 79aceca5 bellard
633 a8dea12f j_mayer
int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
634 a8dea12f j_mayer
                                 uint32_t address, int rw, int access_type)
635 a8dea12f j_mayer
{
636 a8dea12f j_mayer
    ppcemb_tlb_t *tlb;
637 a8dea12f j_mayer
    target_phys_addr_t raddr;
638 a8dea12f j_mayer
    target_ulong mask;
639 a8dea12f j_mayer
    int i, ret, zsel, zpr;
640 a8dea12f j_mayer
            
641 a8dea12f j_mayer
    ret = -6;
642 a8dea12f j_mayer
    for (i = 0; i < env->nb_tlb; i++) {
643 a8dea12f j_mayer
        tlb = &env->tlb[i].tlbe;
644 a8dea12f j_mayer
        /* Check valid flag */
645 a8dea12f j_mayer
        if (!(tlb->prot & PAGE_VALID)) {
646 a8dea12f j_mayer
            if (loglevel)
647 a8dea12f j_mayer
                fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
648 a8dea12f j_mayer
            continue;
649 a8dea12f j_mayer
        }
650 a8dea12f j_mayer
        mask = ~(tlb->size - 1);
651 a8dea12f j_mayer
        if (loglevel) {
652 a8dea12f j_mayer
            fprintf(logfile, "%s: TLB %d address %08x PID %04x <=> "
653 a8dea12f j_mayer
                    "%08x %08x %04x\n",
654 a8dea12f j_mayer
                    __func__, i, address, env->spr[SPR_40x_PID],
655 a8dea12f j_mayer
                    tlb->EPN, mask, tlb->PID);
656 a8dea12f j_mayer
        }
657 a8dea12f j_mayer
        /* Check PID */
658 a8dea12f j_mayer
        if (tlb->PID != 0 && tlb->PID != env->spr[SPR_40x_PID])
659 a8dea12f j_mayer
            continue;
660 a8dea12f j_mayer
        /* Check effective address */
661 a8dea12f j_mayer
        if ((address & mask) != tlb->EPN)
662 a8dea12f j_mayer
            continue;
663 a8dea12f j_mayer
        raddr = (tlb->RPN & mask) | (address & ~mask);
664 a8dea12f j_mayer
        zsel = (tlb->attr >> 4) & 0xF;
665 a8dea12f j_mayer
        zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
666 a8dea12f j_mayer
        if (loglevel) {
667 a8dea12f j_mayer
            fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
668 a8dea12f j_mayer
                    __func__, i, zsel, zpr, rw, tlb->attr);
669 a8dea12f j_mayer
        }
670 a8dea12f j_mayer
        if (access_type == ACCESS_CODE) {
671 a8dea12f j_mayer
            /* Check execute enable bit */
672 a8dea12f j_mayer
            switch (zpr) {
673 a8dea12f j_mayer
            case 0x0:
674 a8dea12f j_mayer
                if (msr_pr) {
675 a8dea12f j_mayer
                    ret = -3;
676 a8dea12f j_mayer
                    ctx->prot = 0;
677 a8dea12f j_mayer
                    break;
678 a8dea12f j_mayer
                }
679 a8dea12f j_mayer
                /* No break here */
680 a8dea12f j_mayer
            case 0x1:
681 a8dea12f j_mayer
            case 0x2:
682 a8dea12f j_mayer
                /* Check from TLB entry */
683 a8dea12f j_mayer
                if (!(tlb->prot & PAGE_EXEC)) {
684 a8dea12f j_mayer
                    ret = -3;
685 a8dea12f j_mayer
                } else {
686 a8dea12f j_mayer
                    if (tlb->prot & PAGE_WRITE)
687 a8dea12f j_mayer
                        ctx->prot = PAGE_READ | PAGE_WRITE;
688 a8dea12f j_mayer
                    else
689 a8dea12f j_mayer
                        ctx->prot = PAGE_READ;
690 a8dea12f j_mayer
                    ret = 0;
691 a8dea12f j_mayer
                }
692 a8dea12f j_mayer
                break;
693 a8dea12f j_mayer
            case 0x3:
694 a8dea12f j_mayer
                /* All accesses granted */
695 a8dea12f j_mayer
                ret = 0;
696 a8dea12f j_mayer
                ctx->prot = PAGE_READ | PAGE_WRITE;
697 a8dea12f j_mayer
                break;
698 a8dea12f j_mayer
            }
699 a8dea12f j_mayer
        } else {
700 a8dea12f j_mayer
            switch (zpr) {
701 a8dea12f j_mayer
            case 0x0:
702 a8dea12f j_mayer
                if (msr_pr) {
703 a8dea12f j_mayer
                    ret = -2;
704 a8dea12f j_mayer
                    ctx->prot = 0;
705 a8dea12f j_mayer
                    break;
706 a8dea12f j_mayer
                }
707 a8dea12f j_mayer
                /* No break here */
708 a8dea12f j_mayer
            case 0x1:
709 a8dea12f j_mayer
            case 0x2:
710 a8dea12f j_mayer
                /* Check from TLB entry */
711 a8dea12f j_mayer
                /* Check write protection bit */
712 a8dea12f j_mayer
                if (rw && !(tlb->prot & PAGE_WRITE)) {
713 a8dea12f j_mayer
                    ret = -2;
714 a8dea12f j_mayer
                } else {
715 a8dea12f j_mayer
                    ret = 2;
716 a8dea12f j_mayer
                    if (tlb->prot & PAGE_WRITE)
717 a8dea12f j_mayer
                        ctx->prot = PAGE_READ | PAGE_WRITE;
718 a8dea12f j_mayer
                    else
719 a8dea12f j_mayer
                        ctx->prot = PAGE_READ;
720 a8dea12f j_mayer
                }
721 a8dea12f j_mayer
                break;
722 a8dea12f j_mayer
            case 0x3:
723 a8dea12f j_mayer
                /* All accesses granted */
724 a8dea12f j_mayer
                ret = 2;
725 a8dea12f j_mayer
                ctx->prot = PAGE_READ | PAGE_WRITE;
726 a8dea12f j_mayer
                break;
727 a8dea12f j_mayer
            }
728 a8dea12f j_mayer
        }
729 a8dea12f j_mayer
        if (ret >= 0) {
730 a8dea12f j_mayer
            ctx->raddr = raddr;
731 a8dea12f j_mayer
            if (loglevel) {
732 a8dea12f j_mayer
                fprintf(logfile, "%s: access granted " ADDRX " => " REGX
733 a8dea12f j_mayer
                        " %d\n", __func__, address, ctx->raddr, ctx->prot);
734 a8dea12f j_mayer
            }
735 a8dea12f j_mayer
            return i;
736 a8dea12f j_mayer
        }
737 a8dea12f j_mayer
    }
738 a8dea12f j_mayer
    
739 a8dea12f j_mayer
    return ret;
740 a8dea12f j_mayer
}
741 a8dea12f j_mayer
742 76a66253 j_mayer
static int check_physical (CPUState *env, mmu_ctx_t *ctx,
743 76a66253 j_mayer
                           target_ulong eaddr, int rw)
744 76a66253 j_mayer
{
745 76a66253 j_mayer
    int in_plb, ret;
746 76a66253 j_mayer
        
747 76a66253 j_mayer
    ctx->raddr = eaddr;
748 76a66253 j_mayer
    ctx->prot = PAGE_READ;
749 76a66253 j_mayer
    ret = 0;
750 76a66253 j_mayer
    if (unlikely(msr_pe != 0 && PPC_MMU(env) == PPC_FLAGS_MMU_403)) {
751 76a66253 j_mayer
        /* 403 family add some particular protections,
752 76a66253 j_mayer
         * using PBL/PBU registers for accesses with no translation.
753 76a66253 j_mayer
         */
754 76a66253 j_mayer
        in_plb =
755 76a66253 j_mayer
            /* Check PLB validity */
756 76a66253 j_mayer
            (env->pb[0] < env->pb[1] &&
757 76a66253 j_mayer
             /* and address in plb area */
758 76a66253 j_mayer
             eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
759 76a66253 j_mayer
            (env->pb[2] < env->pb[3] &&
760 76a66253 j_mayer
             eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
761 76a66253 j_mayer
        if (in_plb ^ msr_px) {
762 76a66253 j_mayer
            /* Access in protected area */
763 76a66253 j_mayer
            if (rw == 1) {
764 76a66253 j_mayer
                /* Access is not allowed */
765 76a66253 j_mayer
                ret = -2;
766 76a66253 j_mayer
            }
767 76a66253 j_mayer
        } else {
768 76a66253 j_mayer
            /* Read-write access is allowed */
769 76a66253 j_mayer
            ctx->prot |= PAGE_WRITE;
770 76a66253 j_mayer
        }
771 76a66253 j_mayer
    } else {
772 76a66253 j_mayer
        ctx->prot |= PAGE_WRITE;
773 76a66253 j_mayer
    }
774 76a66253 j_mayer
775 76a66253 j_mayer
    return ret;
776 76a66253 j_mayer
}
777 76a66253 j_mayer
778 76a66253 j_mayer
int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
779 76a66253 j_mayer
                          int rw, int access_type, int check_BATs)
780 9a64fbe4 bellard
{
781 9a64fbe4 bellard
    int ret;
782 514fb8c1 bellard
#if 0
783 9a64fbe4 bellard
    if (loglevel > 0) {
784 9a64fbe4 bellard
        fprintf(logfile, "%s\n", __func__);
785 9a64fbe4 bellard
    }
786 d9bce9d9 j_mayer
#endif
787 4b3686fa bellard
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
788 4b3686fa bellard
        (access_type != ACCESS_CODE && msr_dr == 0)) {
789 9a64fbe4 bellard
        /* No address translation */
790 76a66253 j_mayer
        ret = check_physical(env, ctx, eaddr, rw);
791 9a64fbe4 bellard
    } else {
792 a8dea12f j_mayer
        switch (PPC_MMU(env)) {
793 a8dea12f j_mayer
        case PPC_FLAGS_MMU_32B:
794 a8dea12f j_mayer
        case PPC_FLAGS_MMU_SOFT_6xx:
795 a8dea12f j_mayer
            /* Try to find a BAT */
796 a8dea12f j_mayer
            ret = -1;
797 a8dea12f j_mayer
            if (check_BATs)
798 a8dea12f j_mayer
                ret = get_bat(env, ctx, eaddr, rw, access_type);
799 a8dea12f j_mayer
            if (ret < 0) {
800 a8dea12f j_mayer
                /* We didn't match any BAT entry */
801 a8dea12f j_mayer
                ret = get_segment(env, ctx, eaddr, rw, access_type);
802 a8dea12f j_mayer
            }
803 a8dea12f j_mayer
            break;
804 a8dea12f j_mayer
        case PPC_FLAGS_MMU_SOFT_4xx:
805 a8dea12f j_mayer
            ret = mmu4xx_get_physical_address(env, ctx, eaddr,
806 a8dea12f j_mayer
                                              rw, access_type);
807 a8dea12f j_mayer
            break;
808 a8dea12f j_mayer
        default:
809 a8dea12f j_mayer
            /* XXX: TODO */
810 a8dea12f j_mayer
            cpu_abort(env, "MMU model not implemented\n");
811 a8dea12f j_mayer
            return -1;
812 9a64fbe4 bellard
        }
813 9a64fbe4 bellard
    }
814 514fb8c1 bellard
#if 0
815 a541f297 bellard
    if (loglevel > 0) {
816 1b9eb036 j_mayer
        fprintf(logfile, "%s address " ADDRX " => " ADDRX "\n",
817 76a66253 j_mayer
                __func__, eaddr, ctx->raddr);
818 a541f297 bellard
    }
819 76a66253 j_mayer
#endif
820 d9bce9d9 j_mayer
821 9a64fbe4 bellard
    return ret;
822 9a64fbe4 bellard
}
823 9a64fbe4 bellard
824 9b3c35e0 j_mayer
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
825 a6b025d3 bellard
{
826 76a66253 j_mayer
    mmu_ctx_t ctx;
827 a6b025d3 bellard
828 76a66253 j_mayer
    if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT, 1) != 0))
829 a6b025d3 bellard
        return -1;
830 76a66253 j_mayer
831 76a66253 j_mayer
    return ctx.raddr & TARGET_PAGE_MASK;
832 a6b025d3 bellard
}
833 9a64fbe4 bellard
834 9a64fbe4 bellard
/* Perform address translation */
835 9a64fbe4 bellard
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
836 a541f297 bellard
                              int is_user, int is_softmmu)
837 9a64fbe4 bellard
{
838 76a66253 j_mayer
    mmu_ctx_t ctx;
839 9a64fbe4 bellard
    int exception = 0, error_code = 0;
840 a541f297 bellard
    int access_type;
841 9a64fbe4 bellard
    int ret = 0;
842 d9bce9d9 j_mayer
843 b769d8fe bellard
    if (rw == 2) {
844 b769d8fe bellard
        /* code access */
845 b769d8fe bellard
        rw = 0;
846 b769d8fe bellard
        access_type = ACCESS_CODE;
847 b769d8fe bellard
    } else {
848 b769d8fe bellard
        /* data access */
849 b769d8fe bellard
        /* XXX: put correct access by using cpu_restore_state()
850 b769d8fe bellard
           correctly */
851 b769d8fe bellard
        access_type = ACCESS_INT;
852 b769d8fe bellard
        //        access_type = env->access_type;
853 b769d8fe bellard
    }
854 76a66253 j_mayer
    ret = get_physical_address(env, &ctx, address, rw, access_type, 1);
855 9a64fbe4 bellard
    if (ret == 0) {
856 76a66253 j_mayer
        ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
857 76a66253 j_mayer
                           ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
858 76a66253 j_mayer
                           is_user, is_softmmu);
859 9a64fbe4 bellard
    } else if (ret < 0) {
860 9a64fbe4 bellard
#if defined (DEBUG_MMU)
861 76a66253 j_mayer
        if (loglevel > 0)
862 76a66253 j_mayer
            cpu_dump_state(env, logfile, fprintf, 0);
863 9a64fbe4 bellard
#endif
864 9a64fbe4 bellard
        if (access_type == ACCESS_CODE) {
865 9a64fbe4 bellard
            exception = EXCP_ISI;
866 9a64fbe4 bellard
            switch (ret) {
867 9a64fbe4 bellard
            case -1:
868 76a66253 j_mayer
                /* No matches in page tables or TLB */
869 76a66253 j_mayer
                if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
870 76a66253 j_mayer
                    exception = EXCP_I_TLBMISS;
871 76a66253 j_mayer
                    env->spr[SPR_IMISS] = address;
872 76a66253 j_mayer
                    env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
873 76a66253 j_mayer
                    error_code = 1 << 18;
874 76a66253 j_mayer
                    goto tlb_miss;
875 76a66253 j_mayer
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
876 a8dea12f j_mayer
                    exception = EXCP_40x_ITLBMISS;
877 a8dea12f j_mayer
                    error_code = 0;
878 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
879 a8dea12f j_mayer
                    env->spr[SPR_40x_ESR] = 0x00000000;
880 76a66253 j_mayer
                } else {
881 76a66253 j_mayer
                    error_code = 0x40000000;
882 76a66253 j_mayer
                }
883 9a64fbe4 bellard
                break;
884 9a64fbe4 bellard
            case -2:
885 9a64fbe4 bellard
                /* Access rights violation */
886 2be0071f bellard
                error_code = 0x08000000;
887 9a64fbe4 bellard
                break;
888 9a64fbe4 bellard
            case -3:
889 76a66253 j_mayer
                /* No execute protection violation */
890 2be0071f bellard
                error_code = 0x10000000;
891 9a64fbe4 bellard
                break;
892 9a64fbe4 bellard
            case -4:
893 9a64fbe4 bellard
                /* Direct store exception */
894 9a64fbe4 bellard
                /* No code fetch is allowed in direct-store areas */
895 2be0071f bellard
                error_code = 0x10000000;
896 2be0071f bellard
                break;
897 2be0071f bellard
            case -5:
898 2be0071f bellard
                /* No match in segment table */
899 2be0071f bellard
                exception = EXCP_ISEG;
900 2be0071f bellard
                error_code = 0;
901 9a64fbe4 bellard
                break;
902 9a64fbe4 bellard
            }
903 9a64fbe4 bellard
        } else {
904 9a64fbe4 bellard
            exception = EXCP_DSI;
905 9a64fbe4 bellard
            switch (ret) {
906 9a64fbe4 bellard
            case -1:
907 76a66253 j_mayer
                /* No matches in page tables or TLB */
908 76a66253 j_mayer
                if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
909 76a66253 j_mayer
                    if (rw == 1) {
910 76a66253 j_mayer
                        exception = EXCP_DS_TLBMISS;
911 76a66253 j_mayer
                        error_code = 1 << 16;
912 76a66253 j_mayer
                    } else {
913 76a66253 j_mayer
                        exception = EXCP_DL_TLBMISS;
914 76a66253 j_mayer
                        error_code = 0;
915 76a66253 j_mayer
                    }
916 76a66253 j_mayer
                    env->spr[SPR_DMISS] = address;
917 76a66253 j_mayer
                    env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
918 76a66253 j_mayer
                tlb_miss:
919 76a66253 j_mayer
                    error_code |= ctx.key << 19;
920 76a66253 j_mayer
                    env->spr[SPR_HASH1] = ctx.pg_addr[0];
921 76a66253 j_mayer
                    env->spr[SPR_HASH2] = ctx.pg_addr[1];
922 76a66253 j_mayer
                    /* Do not alter DAR nor DSISR */
923 76a66253 j_mayer
                    goto out;
924 76a66253 j_mayer
                } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
925 a8dea12f j_mayer
                    exception = EXCP_40x_DTLBMISS;
926 a8dea12f j_mayer
                    error_code = 0;
927 a8dea12f j_mayer
                    env->spr[SPR_40x_DEAR] = address;
928 a8dea12f j_mayer
                    if (rw)
929 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00800000;
930 a8dea12f j_mayer
                    else
931 a8dea12f j_mayer
                        env->spr[SPR_40x_ESR] = 0x00000000;
932 76a66253 j_mayer
                } else {
933 76a66253 j_mayer
                    error_code = 0x40000000;
934 76a66253 j_mayer
                }
935 9a64fbe4 bellard
                break;
936 9a64fbe4 bellard
            case -2:
937 9a64fbe4 bellard
                /* Access rights violation */
938 2be0071f bellard
                error_code = 0x08000000;
939 9a64fbe4 bellard
                break;
940 9a64fbe4 bellard
            case -4:
941 9a64fbe4 bellard
                /* Direct store exception */
942 9a64fbe4 bellard
                switch (access_type) {
943 9a64fbe4 bellard
                case ACCESS_FLOAT:
944 9a64fbe4 bellard
                    /* Floating point load/store */
945 9a64fbe4 bellard
                    exception = EXCP_ALIGN;
946 9a64fbe4 bellard
                    error_code = EXCP_ALIGN_FP;
947 9a64fbe4 bellard
                    break;
948 9a64fbe4 bellard
                case ACCESS_RES:
949 9a64fbe4 bellard
                    /* lwarx, ldarx or srwcx. */
950 2be0071f bellard
                    error_code = 0x04000000;
951 9a64fbe4 bellard
                    break;
952 9a64fbe4 bellard
                case ACCESS_EXT:
953 9a64fbe4 bellard
                    /* eciwx or ecowx */
954 2be0071f bellard
                    error_code = 0x04100000;
955 9a64fbe4 bellard
                    break;
956 9a64fbe4 bellard
                default:
957 76a66253 j_mayer
                    printf("DSI: invalid exception (%d)\n", ret);
958 9a64fbe4 bellard
                    exception = EXCP_PROGRAM;
959 9a64fbe4 bellard
                    error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
960 9a64fbe4 bellard
                    break;
961 9a64fbe4 bellard
                }
962 fdabc366 bellard
                break;
963 2be0071f bellard
            case -5:
964 2be0071f bellard
                /* No match in segment table */
965 2be0071f bellard
                exception = EXCP_DSEG;
966 2be0071f bellard
                error_code = 0;
967 2be0071f bellard
                break;
968 9a64fbe4 bellard
            }
969 fdabc366 bellard
            if (exception == EXCP_DSI && rw == 1)
970 2be0071f bellard
                error_code |= 0x02000000;
971 76a66253 j_mayer
            /* Store fault address */
972 76a66253 j_mayer
            env->spr[SPR_DAR] = address;
973 2be0071f bellard
            env->spr[SPR_DSISR] = error_code;
974 9a64fbe4 bellard
        }
975 76a66253 j_mayer
    out:
976 9a64fbe4 bellard
#if 0
977 9a64fbe4 bellard
        printf("%s: set exception to %d %02x\n",
978 9a64fbe4 bellard
               __func__, exception, error_code);
979 9a64fbe4 bellard
#endif
980 9a64fbe4 bellard
        env->exception_index = exception;
981 9a64fbe4 bellard
        env->error_code = error_code;
982 9a64fbe4 bellard
        ret = 1;
983 9a64fbe4 bellard
    }
984 76a66253 j_mayer
985 9a64fbe4 bellard
    return ret;
986 9a64fbe4 bellard
}
987 9a64fbe4 bellard
988 3fc6c082 bellard
/*****************************************************************************/
989 3fc6c082 bellard
/* BATs management */
990 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
991 3fc6c082 bellard
static inline void do_invalidate_BAT (CPUPPCState *env,
992 3fc6c082 bellard
                                      target_ulong BATu, target_ulong mask)
993 3fc6c082 bellard
{
994 3fc6c082 bellard
    target_ulong base, end, page;
995 76a66253 j_mayer
996 3fc6c082 bellard
    base = BATu & ~0x0001FFFF;
997 3fc6c082 bellard
    end = base + mask + 0x00020000;
998 3fc6c082 bellard
#if defined (DEBUG_BATS)
999 76a66253 j_mayer
    if (loglevel != 0) {
1000 1b9eb036 j_mayer
        fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1001 76a66253 j_mayer
                base, end, mask);
1002 76a66253 j_mayer
    }
1003 3fc6c082 bellard
#endif
1004 3fc6c082 bellard
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
1005 3fc6c082 bellard
        tlb_flush_page(env, page);
1006 3fc6c082 bellard
#if defined (DEBUG_BATS)
1007 3fc6c082 bellard
    if (loglevel != 0)
1008 3fc6c082 bellard
        fprintf(logfile, "Flush done\n");
1009 3fc6c082 bellard
#endif
1010 3fc6c082 bellard
}
1011 3fc6c082 bellard
#endif
1012 3fc6c082 bellard
1013 3fc6c082 bellard
static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
1014 3fc6c082 bellard
                                   target_ulong value)
1015 3fc6c082 bellard
{
1016 3fc6c082 bellard
#if defined (DEBUG_BATS)
1017 3fc6c082 bellard
    if (loglevel != 0) {
1018 1b9eb036 j_mayer
        fprintf(logfile, "Set %cBAT%d%c to 0x" ADDRX " (0x" ADDRX ")\n",
1019 1b9eb036 j_mayer
                ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1020 3fc6c082 bellard
    }
1021 3fc6c082 bellard
#endif
1022 3fc6c082 bellard
}
1023 3fc6c082 bellard
1024 3fc6c082 bellard
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1025 3fc6c082 bellard
{
1026 3fc6c082 bellard
    return env->IBAT[0][nr];
1027 3fc6c082 bellard
}
1028 3fc6c082 bellard
1029 3fc6c082 bellard
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1030 3fc6c082 bellard
{
1031 3fc6c082 bellard
    return env->IBAT[1][nr];
1032 3fc6c082 bellard
}
1033 3fc6c082 bellard
1034 3fc6c082 bellard
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1035 3fc6c082 bellard
{
1036 3fc6c082 bellard
    target_ulong mask;
1037 3fc6c082 bellard
1038 3fc6c082 bellard
    dump_store_bat(env, 'I', 0, nr, value);
1039 3fc6c082 bellard
    if (env->IBAT[0][nr] != value) {
1040 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1041 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1042 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1043 3fc6c082 bellard
#endif
1044 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1045 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1046 3fc6c082 bellard
         */
1047 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1048 3fc6c082 bellard
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1049 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1050 3fc6c082 bellard
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1051 3fc6c082 bellard
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1052 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1053 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1054 76a66253 j_mayer
#else
1055 3fc6c082 bellard
        tlb_flush(env, 1);
1056 3fc6c082 bellard
#endif
1057 3fc6c082 bellard
    }
1058 3fc6c082 bellard
}
1059 3fc6c082 bellard
1060 3fc6c082 bellard
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1061 3fc6c082 bellard
{
1062 3fc6c082 bellard
    dump_store_bat(env, 'I', 1, nr, value);
1063 3fc6c082 bellard
    env->IBAT[1][nr] = value;
1064 3fc6c082 bellard
}
1065 3fc6c082 bellard
1066 3fc6c082 bellard
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1067 3fc6c082 bellard
{
1068 3fc6c082 bellard
    return env->DBAT[0][nr];
1069 3fc6c082 bellard
}
1070 3fc6c082 bellard
1071 3fc6c082 bellard
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1072 3fc6c082 bellard
{
1073 3fc6c082 bellard
    return env->DBAT[1][nr];
1074 3fc6c082 bellard
}
1075 3fc6c082 bellard
1076 3fc6c082 bellard
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1077 3fc6c082 bellard
{
1078 3fc6c082 bellard
    target_ulong mask;
1079 3fc6c082 bellard
1080 3fc6c082 bellard
    dump_store_bat(env, 'D', 0, nr, value);
1081 3fc6c082 bellard
    if (env->DBAT[0][nr] != value) {
1082 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
1083 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
1084 3fc6c082 bellard
         */
1085 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1086 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1087 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1088 3fc6c082 bellard
#endif
1089 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
1090 3fc6c082 bellard
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1091 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
1092 3fc6c082 bellard
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1093 3fc6c082 bellard
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1094 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
1095 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1096 3fc6c082 bellard
#else
1097 3fc6c082 bellard
        tlb_flush(env, 1);
1098 3fc6c082 bellard
#endif
1099 3fc6c082 bellard
    }
1100 3fc6c082 bellard
}
1101 3fc6c082 bellard
1102 3fc6c082 bellard
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1103 3fc6c082 bellard
{
1104 3fc6c082 bellard
    dump_store_bat(env, 'D', 1, nr, value);
1105 3fc6c082 bellard
    env->DBAT[1][nr] = value;
1106 3fc6c082 bellard
}
1107 3fc6c082 bellard
1108 3fc6c082 bellard
/*****************************************************************************/
1109 3fc6c082 bellard
/* Special registers manipulation */
1110 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1111 d9bce9d9 j_mayer
target_ulong ppc_load_asr (CPUPPCState *env)
1112 d9bce9d9 j_mayer
{
1113 d9bce9d9 j_mayer
    return env->asr;
1114 d9bce9d9 j_mayer
}
1115 d9bce9d9 j_mayer
1116 d9bce9d9 j_mayer
void ppc_store_asr (CPUPPCState *env, target_ulong value)
1117 d9bce9d9 j_mayer
{
1118 d9bce9d9 j_mayer
    if (env->asr != value) {
1119 d9bce9d9 j_mayer
        env->asr = value;
1120 d9bce9d9 j_mayer
        tlb_flush(env, 1);
1121 d9bce9d9 j_mayer
    }
1122 d9bce9d9 j_mayer
}
1123 d9bce9d9 j_mayer
#endif
1124 d9bce9d9 j_mayer
1125 3fc6c082 bellard
target_ulong do_load_sdr1 (CPUPPCState *env)
1126 3fc6c082 bellard
{
1127 3fc6c082 bellard
    return env->sdr1;
1128 3fc6c082 bellard
}
1129 3fc6c082 bellard
1130 3fc6c082 bellard
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
1131 3fc6c082 bellard
{
1132 3fc6c082 bellard
#if defined (DEBUG_MMU)
1133 3fc6c082 bellard
    if (loglevel != 0) {
1134 1b9eb036 j_mayer
        fprintf(logfile, "%s: 0x" ADDRX "\n", __func__, value);
1135 3fc6c082 bellard
    }
1136 3fc6c082 bellard
#endif
1137 3fc6c082 bellard
    if (env->sdr1 != value) {
1138 3fc6c082 bellard
        env->sdr1 = value;
1139 76a66253 j_mayer
        tlb_flush(env, 1);
1140 3fc6c082 bellard
    }
1141 3fc6c082 bellard
}
1142 3fc6c082 bellard
1143 3fc6c082 bellard
target_ulong do_load_sr (CPUPPCState *env, int srnum)
1144 3fc6c082 bellard
{
1145 3fc6c082 bellard
    return env->sr[srnum];
1146 3fc6c082 bellard
}
1147 3fc6c082 bellard
1148 3fc6c082 bellard
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1149 3fc6c082 bellard
{
1150 3fc6c082 bellard
#if defined (DEBUG_MMU)
1151 3fc6c082 bellard
    if (loglevel != 0) {
1152 1b9eb036 j_mayer
        fprintf(logfile, "%s: reg=%d 0x" ADDRX " " ADDRX "\n",
1153 1b9eb036 j_mayer
                __func__, srnum, value, env->sr[srnum]);
1154 3fc6c082 bellard
    }
1155 3fc6c082 bellard
#endif
1156 3fc6c082 bellard
    if (env->sr[srnum] != value) {
1157 3fc6c082 bellard
        env->sr[srnum] = value;
1158 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS) && 0
1159 3fc6c082 bellard
        {
1160 3fc6c082 bellard
            target_ulong page, end;
1161 3fc6c082 bellard
            /* Invalidate 256 MB of virtual memory */
1162 3fc6c082 bellard
            page = (16 << 20) * srnum;
1163 3fc6c082 bellard
            end = page + (16 << 20);
1164 3fc6c082 bellard
            for (; page != end; page += TARGET_PAGE_SIZE)
1165 3fc6c082 bellard
                tlb_flush_page(env, page);
1166 3fc6c082 bellard
        }
1167 3fc6c082 bellard
#else
1168 76a66253 j_mayer
        tlb_flush(env, 1);
1169 3fc6c082 bellard
#endif
1170 3fc6c082 bellard
    }
1171 3fc6c082 bellard
}
1172 76a66253 j_mayer
#endif /* !defined (CONFIG_USER_ONLY) */
1173 3fc6c082 bellard
1174 76a66253 j_mayer
uint32_t ppc_load_xer (CPUPPCState *env)
1175 79aceca5 bellard
{
1176 79aceca5 bellard
    return (xer_so << XER_SO) |
1177 79aceca5 bellard
        (xer_ov << XER_OV) |
1178 79aceca5 bellard
        (xer_ca << XER_CA) |
1179 3fc6c082 bellard
        (xer_bc << XER_BC) |
1180 3fc6c082 bellard
        (xer_cmp << XER_CMP);
1181 79aceca5 bellard
}
1182 79aceca5 bellard
1183 76a66253 j_mayer
void ppc_store_xer (CPUPPCState *env, uint32_t value)
1184 79aceca5 bellard
{
1185 79aceca5 bellard
    xer_so = (value >> XER_SO) & 0x01;
1186 79aceca5 bellard
    xer_ov = (value >> XER_OV) & 0x01;
1187 79aceca5 bellard
    xer_ca = (value >> XER_CA) & 0x01;
1188 3fc6c082 bellard
    xer_cmp = (value >> XER_CMP) & 0xFF;
1189 d9bce9d9 j_mayer
    xer_bc = (value >> XER_BC) & 0x7F;
1190 79aceca5 bellard
}
1191 79aceca5 bellard
1192 76a66253 j_mayer
/* Swap temporary saved registers with GPRs */
1193 76a66253 j_mayer
static inline void swap_gpr_tgpr (CPUPPCState *env)
1194 79aceca5 bellard
{
1195 76a66253 j_mayer
    ppc_gpr_t tmp;
1196 76a66253 j_mayer
1197 76a66253 j_mayer
    tmp = env->gpr[0];
1198 76a66253 j_mayer
    env->gpr[0] = env->tgpr[0];
1199 76a66253 j_mayer
    env->tgpr[0] = tmp;
1200 76a66253 j_mayer
    tmp = env->gpr[1];
1201 76a66253 j_mayer
    env->gpr[1] = env->tgpr[1];
1202 76a66253 j_mayer
    env->tgpr[1] = tmp;
1203 76a66253 j_mayer
    tmp = env->gpr[2];
1204 76a66253 j_mayer
    env->gpr[2] = env->tgpr[2];
1205 76a66253 j_mayer
    env->tgpr[2] = tmp;
1206 76a66253 j_mayer
    tmp = env->gpr[3];
1207 76a66253 j_mayer
    env->gpr[3] = env->tgpr[3];
1208 76a66253 j_mayer
    env->tgpr[3] = tmp;
1209 79aceca5 bellard
}
1210 79aceca5 bellard
1211 76a66253 j_mayer
/* GDBstub can read and write MSR... */
1212 76a66253 j_mayer
target_ulong do_load_msr (CPUPPCState *env)
1213 79aceca5 bellard
{
1214 76a66253 j_mayer
    return
1215 76a66253 j_mayer
#if defined (TARGET_PPC64)
1216 d9bce9d9 j_mayer
        ((target_ulong)msr_sf   << MSR_SF)   |
1217 d9bce9d9 j_mayer
        ((target_ulong)msr_isf  << MSR_ISF)  |
1218 d9bce9d9 j_mayer
        ((target_ulong)msr_hv   << MSR_HV)   |
1219 76a66253 j_mayer
#endif
1220 d9bce9d9 j_mayer
        ((target_ulong)msr_ucle << MSR_UCLE) |
1221 d9bce9d9 j_mayer
        ((target_ulong)msr_vr   << MSR_VR)   | /* VR / SPE */
1222 d9bce9d9 j_mayer
        ((target_ulong)msr_ap   << MSR_AP)   |
1223 d9bce9d9 j_mayer
        ((target_ulong)msr_sa   << MSR_SA)   |
1224 d9bce9d9 j_mayer
        ((target_ulong)msr_key  << MSR_KEY)  |
1225 d9bce9d9 j_mayer
        ((target_ulong)msr_pow  << MSR_POW)  | /* POW / WE */
1226 d9bce9d9 j_mayer
        ((target_ulong)msr_tlb  << MSR_TLB)  | /* TLB / TGPE / CE */
1227 d9bce9d9 j_mayer
        ((target_ulong)msr_ile  << MSR_ILE)  |
1228 d9bce9d9 j_mayer
        ((target_ulong)msr_ee   << MSR_EE)   |
1229 d9bce9d9 j_mayer
        ((target_ulong)msr_pr   << MSR_PR)   |
1230 d9bce9d9 j_mayer
        ((target_ulong)msr_fp   << MSR_FP)   |
1231 d9bce9d9 j_mayer
        ((target_ulong)msr_me   << MSR_ME)   |
1232 d9bce9d9 j_mayer
        ((target_ulong)msr_fe0  << MSR_FE0)  |
1233 d9bce9d9 j_mayer
        ((target_ulong)msr_se   << MSR_SE)   | /* SE / DWE / UBLE */
1234 d9bce9d9 j_mayer
        ((target_ulong)msr_be   << MSR_BE)   | /* BE / DE */
1235 d9bce9d9 j_mayer
        ((target_ulong)msr_fe1  << MSR_FE1)  |
1236 d9bce9d9 j_mayer
        ((target_ulong)msr_al   << MSR_AL)   |
1237 d9bce9d9 j_mayer
        ((target_ulong)msr_ip   << MSR_IP)   |
1238 d9bce9d9 j_mayer
        ((target_ulong)msr_ir   << MSR_IR)   | /* IR / IS */
1239 d9bce9d9 j_mayer
        ((target_ulong)msr_dr   << MSR_DR)   | /* DR / DS */
1240 d9bce9d9 j_mayer
        ((target_ulong)msr_pe   << MSR_PE)   | /* PE / EP */
1241 d9bce9d9 j_mayer
        ((target_ulong)msr_px   << MSR_PX)   | /* PX / PMM */
1242 d9bce9d9 j_mayer
        ((target_ulong)msr_ri   << MSR_RI)   |
1243 d9bce9d9 j_mayer
        ((target_ulong)msr_le   << MSR_LE);
1244 3fc6c082 bellard
}
1245 3fc6c082 bellard
1246 3fc6c082 bellard
void do_store_msr (CPUPPCState *env, target_ulong value)
1247 313adae9 bellard
{
1248 50443c98 bellard
    int enter_pm;
1249 50443c98 bellard
1250 3fc6c082 bellard
    value &= env->msr_mask;
1251 3fc6c082 bellard
    if (((value >> MSR_IR) & 1) != msr_ir ||
1252 3fc6c082 bellard
        ((value >> MSR_DR) & 1) != msr_dr) {
1253 76a66253 j_mayer
        /* Flush all tlb when changing translation mode */
1254 d094807b bellard
        tlb_flush(env, 1);
1255 3fc6c082 bellard
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1256 a541f297 bellard
    }
1257 3fc6c082 bellard
#if 0
1258 3fc6c082 bellard
    if (loglevel != 0) {
1259 3fc6c082 bellard
        fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
1260 3fc6c082 bellard
    }
1261 3fc6c082 bellard
#endif
1262 76a66253 j_mayer
    switch (PPC_EXCP(env)) {
1263 76a66253 j_mayer
    case PPC_FLAGS_EXCP_602:
1264 76a66253 j_mayer
    case PPC_FLAGS_EXCP_603:
1265 76a66253 j_mayer
        if (((value >> MSR_TGPR) & 1) != msr_tgpr) {
1266 76a66253 j_mayer
            /* Swap temporary saved registers with GPRs */
1267 76a66253 j_mayer
            swap_gpr_tgpr(env);
1268 76a66253 j_mayer
        }
1269 76a66253 j_mayer
        break;
1270 76a66253 j_mayer
    default:
1271 76a66253 j_mayer
        break;
1272 76a66253 j_mayer
    }
1273 76a66253 j_mayer
#if defined (TARGET_PPC64)
1274 76a66253 j_mayer
    msr_sf   = (value >> MSR_SF)   & 1;
1275 76a66253 j_mayer
    msr_isf  = (value >> MSR_ISF)  & 1;
1276 76a66253 j_mayer
    msr_hv   = (value >> MSR_HV)   & 1;
1277 76a66253 j_mayer
#endif
1278 76a66253 j_mayer
    msr_ucle = (value >> MSR_UCLE) & 1;
1279 76a66253 j_mayer
    msr_vr   = (value >> MSR_VR)   & 1; /* VR / SPE */
1280 76a66253 j_mayer
    msr_ap   = (value >> MSR_AP)   & 1;
1281 76a66253 j_mayer
    msr_sa   = (value >> MSR_SA)   & 1;
1282 76a66253 j_mayer
    msr_key  = (value >> MSR_KEY)  & 1;
1283 76a66253 j_mayer
    msr_pow  = (value >> MSR_POW)  & 1; /* POW / WE */
1284 76a66253 j_mayer
    msr_tlb  = (value >> MSR_TLB)  & 1; /* TLB / TGPR / CE */
1285 76a66253 j_mayer
    msr_ile  = (value >> MSR_ILE)  & 1;
1286 76a66253 j_mayer
    msr_ee   = (value >> MSR_EE)   & 1;
1287 76a66253 j_mayer
    msr_pr   = (value >> MSR_PR)   & 1;
1288 76a66253 j_mayer
    msr_fp   = (value >> MSR_FP)   & 1;
1289 76a66253 j_mayer
    msr_me   = (value >> MSR_ME)   & 1;
1290 76a66253 j_mayer
    msr_fe0  = (value >> MSR_FE0)  & 1;
1291 76a66253 j_mayer
    msr_se   = (value >> MSR_SE)   & 1; /* SE / DWE / UBLE */
1292 76a66253 j_mayer
    msr_be   = (value >> MSR_BE)   & 1; /* BE / DE */
1293 76a66253 j_mayer
    msr_fe1  = (value >> MSR_FE1)  & 1;
1294 76a66253 j_mayer
    msr_al   = (value >> MSR_AL)   & 1;
1295 76a66253 j_mayer
    msr_ip   = (value >> MSR_IP)   & 1;
1296 76a66253 j_mayer
    msr_ir   = (value >> MSR_IR)   & 1; /* IR / IS */
1297 76a66253 j_mayer
    msr_dr   = (value >> MSR_DR)   & 1; /* DR / DS */
1298 76a66253 j_mayer
    msr_pe   = (value >> MSR_PE)   & 1; /* PE / EP */
1299 76a66253 j_mayer
    msr_px   = (value >> MSR_PX)   & 1; /* PX / PMM */
1300 76a66253 j_mayer
    msr_ri   = (value >> MSR_RI)   & 1;
1301 76a66253 j_mayer
    msr_le   = (value >> MSR_LE)   & 1;
1302 3fc6c082 bellard
    do_compute_hflags(env);
1303 50443c98 bellard
1304 50443c98 bellard
    enter_pm = 0;
1305 50443c98 bellard
    switch (PPC_EXCP(env)) {
1306 d9bce9d9 j_mayer
    case PPC_FLAGS_EXCP_603:
1307 d9bce9d9 j_mayer
        /* Don't handle SLEEP mode: we should disable all clocks...
1308 d9bce9d9 j_mayer
         * No dynamic power-management.
1309 d9bce9d9 j_mayer
         */
1310 d9bce9d9 j_mayer
        if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00C00000) != 0)
1311 d9bce9d9 j_mayer
            enter_pm = 1;
1312 d9bce9d9 j_mayer
        break;
1313 d9bce9d9 j_mayer
    case PPC_FLAGS_EXCP_604:
1314 d9bce9d9 j_mayer
        if (msr_pow == 1)
1315 d9bce9d9 j_mayer
            enter_pm = 1;
1316 d9bce9d9 j_mayer
        break;
1317 50443c98 bellard
    case PPC_FLAGS_EXCP_7x0:
1318 76a66253 j_mayer
        if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
1319 50443c98 bellard
            enter_pm = 1;
1320 50443c98 bellard
        break;
1321 50443c98 bellard
    default:
1322 50443c98 bellard
        break;
1323 50443c98 bellard
    }
1324 50443c98 bellard
    if (enter_pm) {
1325 e80e1cc4 bellard
        /* power save: exit cpu loop */
1326 50443c98 bellard
        env->halted = 1;
1327 e80e1cc4 bellard
        env->exception_index = EXCP_HLT;
1328 e80e1cc4 bellard
        cpu_loop_exit();
1329 e80e1cc4 bellard
    }
1330 3fc6c082 bellard
}
1331 3fc6c082 bellard
1332 d9bce9d9 j_mayer
#if defined(TARGET_PPC64)
1333 426613db j_mayer
void ppc_store_msr_32 (CPUPPCState *env, uint32_t value)
1334 d9bce9d9 j_mayer
{
1335 426613db j_mayer
    do_store_msr(env,
1336 426613db j_mayer
                 (do_load_msr(env) & ~0xFFFFFFFFULL) | (value & 0xFFFFFFFF));
1337 d9bce9d9 j_mayer
}
1338 d9bce9d9 j_mayer
#endif
1339 d9bce9d9 j_mayer
1340 76a66253 j_mayer
void do_compute_hflags (CPUPPCState *env)
1341 3fc6c082 bellard
{
1342 76a66253 j_mayer
    /* Compute current hflags */
1343 c62db105 j_mayer
    env->hflags = (msr_cm << MSR_CM) | (msr_vr << MSR_VR) |
1344 c62db105 j_mayer
        (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) |
1345 c62db105 j_mayer
        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) |
1346 c62db105 j_mayer
        (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE);
1347 76a66253 j_mayer
#if defined (TARGET_PPC64)
1348 c62db105 j_mayer
    /* No care here: PowerPC 64 MSR_SF means the same as MSR_CM for BookE */
1349 d9bce9d9 j_mayer
    env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32));
1350 4b3686fa bellard
#endif
1351 3fc6c082 bellard
}
1352 3fc6c082 bellard
1353 3fc6c082 bellard
/*****************************************************************************/
1354 3fc6c082 bellard
/* Exception processing */
1355 18fba28c bellard
#if defined (CONFIG_USER_ONLY)
1356 9a64fbe4 bellard
void do_interrupt (CPUState *env)
1357 79aceca5 bellard
{
1358 18fba28c bellard
    env->exception_index = -1;
1359 18fba28c bellard
}
1360 47103572 j_mayer
1361 e9df014c j_mayer
void ppc_hw_interrupt (CPUState *env)
1362 47103572 j_mayer
{
1363 47103572 j_mayer
    env->exception_index = -1;
1364 47103572 j_mayer
}
1365 76a66253 j_mayer
#else /* defined (CONFIG_USER_ONLY) */
1366 d094807b bellard
static void dump_syscall(CPUState *env)
1367 d094807b bellard
{
1368 d9bce9d9 j_mayer
    fprintf(logfile, "syscall r0=0x" REGX " r3=0x" REGX " r4=0x" REGX
1369 1b9eb036 j_mayer
            " r5=0x" REGX " r6=0x" REGX " nip=0x" ADDRX "\n",
1370 d094807b bellard
            env->gpr[0], env->gpr[3], env->gpr[4],
1371 d094807b bellard
            env->gpr[5], env->gpr[6], env->nip);
1372 d094807b bellard
}
1373 d094807b bellard
1374 18fba28c bellard
void do_interrupt (CPUState *env)
1375 18fba28c bellard
{
1376 c62db105 j_mayer
    target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1;
1377 c62db105 j_mayer
    int excp, idx;
1378 79aceca5 bellard
1379 18fba28c bellard
    excp = env->exception_index;
1380 3fc6c082 bellard
    msr = do_load_msr(env);
1381 2be0071f bellard
    /* The default is to use SRR0 & SRR1 to save the exception context */
1382 2be0071f bellard
    srr_0 = &env->spr[SPR_SRR0];
1383 2be0071f bellard
    srr_1 = &env->spr[SPR_SRR1];
1384 c62db105 j_mayer
    asrr_0 = NULL;
1385 c62db105 j_mayer
    asrr_1 = NULL;
1386 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
1387 2be0071f bellard
    if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
1388 2be0071f bellard
        if (loglevel != 0) {
1389 1b9eb036 j_mayer
            fprintf(logfile,
1390 1b9eb036 j_mayer
                    "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
1391 1b9eb036 j_mayer
                    env->nip, excp, env->error_code);
1392 76a66253 j_mayer
            cpu_dump_state(env, logfile, fprintf, 0);
1393 b769d8fe bellard
        }
1394 79aceca5 bellard
    }
1395 9a64fbe4 bellard
#endif
1396 b769d8fe bellard
    if (loglevel & CPU_LOG_INT) {
1397 1b9eb036 j_mayer
        fprintf(logfile, "Raise exception at 0x" ADDRX " => 0x%08x (%02x)\n",
1398 1b9eb036 j_mayer
                env->nip, excp, env->error_code);
1399 b769d8fe bellard
    }
1400 2be0071f bellard
    msr_pow = 0;
1401 c62db105 j_mayer
    idx = -1;
1402 9a64fbe4 bellard
    /* Generate informations in save/restore registers */
1403 9a64fbe4 bellard
    switch (excp) {
1404 76a66253 j_mayer
    /* Generic PowerPC exceptions */
1405 2be0071f bellard
    case EXCP_RESET: /* 0x0100 */
1406 c62db105 j_mayer
        switch (PPC_EXCP(env)) {
1407 c62db105 j_mayer
        case PPC_FLAGS_EXCP_40x:
1408 c62db105 j_mayer
            srr_0 = &env->spr[SPR_40x_SRR2];
1409 c62db105 j_mayer
            srr_1 = &env->spr[SPR_40x_SRR3];
1410 c62db105 j_mayer
            break;
1411 c62db105 j_mayer
        case PPC_FLAGS_EXCP_BOOKE:
1412 c62db105 j_mayer
            idx = 0;
1413 c62db105 j_mayer
            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1414 c62db105 j_mayer
            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1415 c62db105 j_mayer
            break;
1416 c62db105 j_mayer
        default:
1417 2be0071f bellard
            if (msr_ip)
1418 2be0071f bellard
                excp += 0xFFC00;
1419 2be0071f bellard
            excp |= 0xFFC00000;
1420 c62db105 j_mayer
            break;
1421 2be0071f bellard
        }
1422 9a64fbe4 bellard
        goto store_next;
1423 2be0071f bellard
    case EXCP_MACHINE_CHECK: /* 0x0200 */
1424 c62db105 j_mayer
        switch (PPC_EXCP(env)) {
1425 c62db105 j_mayer
        case PPC_FLAGS_EXCP_40x:
1426 2be0071f bellard
            srr_0 = &env->spr[SPR_40x_SRR2];
1427 2be0071f bellard
            srr_1 = &env->spr[SPR_40x_SRR3];
1428 c62db105 j_mayer
            break;
1429 c62db105 j_mayer
        case PPC_FLAGS_EXCP_BOOKE:
1430 c62db105 j_mayer
            idx = 1;
1431 c62db105 j_mayer
            srr_0 = &env->spr[SPR_BOOKE_MCSRR0];
1432 c62db105 j_mayer
            srr_1 = &env->spr[SPR_BOOKE_MCSRR1];
1433 c62db105 j_mayer
            asrr_0 = &env->spr[SPR_BOOKE_CSRR0];
1434 c62db105 j_mayer
            asrr_1 = &env->spr[SPR_BOOKE_CSRR1];
1435 c62db105 j_mayer
            msr_ce = 0;
1436 c62db105 j_mayer
            break;
1437 c62db105 j_mayer
        default:
1438 c62db105 j_mayer
            break;
1439 2be0071f bellard
        }
1440 9a64fbe4 bellard
        msr_me = 0;
1441 9a64fbe4 bellard
        break;
1442 2be0071f bellard
    case EXCP_DSI: /* 0x0300 */
1443 9a64fbe4 bellard
        /* Store exception cause */
1444 9a64fbe4 bellard
        /* data location address has been stored
1445 9a64fbe4 bellard
         * when the fault has been detected
1446 2be0071f bellard
         */
1447 c62db105 j_mayer
        idx = 2;
1448 76a66253 j_mayer
        msr &= ~0xFFFF0000;
1449 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
1450 76a66253 j_mayer
        if (loglevel) {
1451 1b9eb036 j_mayer
            fprintf(logfile, "DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX
1452 1b9eb036 j_mayer
                    "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1453 76a66253 j_mayer
        } else {
1454 1b9eb036 j_mayer
            printf("DSI exception: DSISR=0x" ADDRX" DAR=0x" ADDRX "\n",
1455 76a66253 j_mayer
                   env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1456 76a66253 j_mayer
        }
1457 a541f297 bellard
#endif
1458 a541f297 bellard
        goto store_next;
1459 2be0071f bellard
    case EXCP_ISI: /* 0x0400 */
1460 9a64fbe4 bellard
        /* Store exception cause */
1461 c62db105 j_mayer
        idx = 3;
1462 76a66253 j_mayer
        msr &= ~0xFFFF0000;
1463 2be0071f bellard
        msr |= env->error_code;
1464 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
1465 76a66253 j_mayer
        if (loglevel != 0) {
1466 1b9eb036 j_mayer
            fprintf(logfile, "ISI exception: msr=0x" ADDRX ", nip=0x" ADDRX
1467 1b9eb036 j_mayer
                    "\n", msr, env->nip);
1468 76a66253 j_mayer
        }
1469 a541f297 bellard
#endif
1470 9a64fbe4 bellard
        goto store_next;
1471 2be0071f bellard
    case EXCP_EXTERNAL: /* 0x0500 */
1472 c62db105 j_mayer
        idx = 4;
1473 9a64fbe4 bellard
        goto store_next;
1474 2be0071f bellard
    case EXCP_ALIGN: /* 0x0600 */
1475 76a66253 j_mayer
        if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) {
1476 2be0071f bellard
            /* Store exception cause */
1477 c62db105 j_mayer
            idx = 5;
1478 2be0071f bellard
            /* Get rS/rD and rA from faulting opcode */
1479 2be0071f bellard
            env->spr[SPR_DSISR] |=
1480 2be0071f bellard
                (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1481 2be0071f bellard
            /* data location address has been stored
1482 2be0071f bellard
             * when the fault has been detected
1483 2be0071f bellard
             */
1484 2be0071f bellard
        } else {
1485 2be0071f bellard
            /* IO error exception on PowerPC 601 */
1486 2be0071f bellard
            /* XXX: TODO */
1487 2be0071f bellard
            cpu_abort(env,
1488 2be0071f bellard
                      "601 IO error exception is not implemented yet !\n");
1489 2be0071f bellard
        }
1490 9a64fbe4 bellard
        goto store_current;
1491 2be0071f bellard
    case EXCP_PROGRAM: /* 0x0700 */
1492 c62db105 j_mayer
        idx = 6;
1493 9a64fbe4 bellard
        msr &= ~0xFFFF0000;
1494 9a64fbe4 bellard
        switch (env->error_code & ~0xF) {
1495 9a64fbe4 bellard
        case EXCP_FP:
1496 9a64fbe4 bellard
            if (msr_fe0 == 0 && msr_fe1 == 0) {
1497 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
1498 9a64fbe4 bellard
                printf("Ignore floating point exception\n");
1499 9a64fbe4 bellard
#endif
1500 9a64fbe4 bellard
                return;
1501 76a66253 j_mayer
            }
1502 9a64fbe4 bellard
            msr |= 0x00100000;
1503 9a64fbe4 bellard
            /* Set FX */
1504 9a64fbe4 bellard
            env->fpscr[7] |= 0x8;
1505 9a64fbe4 bellard
            /* Finally, update FEX */
1506 9a64fbe4 bellard
            if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
1507 9a64fbe4 bellard
                ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
1508 9a64fbe4 bellard
                env->fpscr[7] |= 0x4;
1509 76a66253 j_mayer
            break;
1510 9a64fbe4 bellard
        case EXCP_INVAL:
1511 1b9eb036 j_mayer
            //      printf("Invalid instruction at 0x" ADDRX "\n", env->nip);
1512 9a64fbe4 bellard
            msr |= 0x00080000;
1513 76a66253 j_mayer
            break;
1514 9a64fbe4 bellard
        case EXCP_PRIV:
1515 9a64fbe4 bellard
            msr |= 0x00040000;
1516 76a66253 j_mayer
            break;
1517 9a64fbe4 bellard
        case EXCP_TRAP:
1518 c62db105 j_mayer
            idx = 15;
1519 9a64fbe4 bellard
            msr |= 0x00020000;
1520 9a64fbe4 bellard
            break;
1521 9a64fbe4 bellard
        default:
1522 9a64fbe4 bellard
            /* Should never occur */
1523 76a66253 j_mayer
            break;
1524 76a66253 j_mayer
        }
1525 9a64fbe4 bellard
        msr |= 0x00010000;
1526 9a64fbe4 bellard
        goto store_current;
1527 2be0071f bellard
    case EXCP_NO_FP: /* 0x0800 */
1528 c62db105 j_mayer
        idx = 7;
1529 4ecc3190 bellard
        msr &= ~0xFFFF0000;
1530 9a64fbe4 bellard
        goto store_current;
1531 9a64fbe4 bellard
    case EXCP_DECR:
1532 9a64fbe4 bellard
        goto store_next;
1533 2be0071f bellard
    case EXCP_SYSCALL: /* 0x0C00 */
1534 c62db105 j_mayer
        idx = 8;
1535 d094807b bellard
        /* NOTE: this is a temporary hack to support graphics OSI
1536 d094807b bellard
           calls from the MOL driver */
1537 d094807b bellard
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
1538 d094807b bellard
            env->osi_call) {
1539 d094807b bellard
            if (env->osi_call(env) != 0)
1540 d094807b bellard
                return;
1541 d094807b bellard
        }
1542 b769d8fe bellard
        if (loglevel & CPU_LOG_INT) {
1543 d094807b bellard
            dump_syscall(env);
1544 b769d8fe bellard
        }
1545 9a64fbe4 bellard
        goto store_next;
1546 2be0071f bellard
    case EXCP_TRACE: /* 0x0D00 */
1547 2be0071f bellard
        goto store_next;
1548 2be0071f bellard
    case EXCP_PERF: /* 0x0F00 */
1549 2be0071f bellard
        /* XXX: TODO */
1550 2be0071f bellard
        cpu_abort(env,
1551 2be0071f bellard
                  "Performance counter exception is not implemented yet !\n");
1552 2be0071f bellard
        goto store_next;
1553 2be0071f bellard
    /* 32 bits PowerPC specific exceptions */
1554 2be0071f bellard
    case EXCP_FP_ASSIST: /* 0x0E00 */
1555 2be0071f bellard
        /* XXX: TODO */
1556 2be0071f bellard
        cpu_abort(env, "Floating point assist exception "
1557 2be0071f bellard
                  "is not implemented yet !\n");
1558 2be0071f bellard
        goto store_next;
1559 76a66253 j_mayer
        /* 64 bits PowerPC exceptions */
1560 2be0071f bellard
    case EXCP_DSEG: /* 0x0380 */
1561 2be0071f bellard
        /* XXX: TODO */
1562 2be0071f bellard
        cpu_abort(env, "Data segment exception is not implemented yet !\n");
1563 9a64fbe4 bellard
        goto store_next;
1564 2be0071f bellard
    case EXCP_ISEG: /* 0x0480 */
1565 2be0071f bellard
        /* XXX: TODO */
1566 2be0071f bellard
        cpu_abort(env,
1567 2be0071f bellard
                  "Instruction segment exception is not implemented yet !\n");
1568 9a64fbe4 bellard
        goto store_next;
1569 2be0071f bellard
    case EXCP_HDECR: /* 0x0980 */
1570 76a66253 j_mayer
        /* XXX: TODO */
1571 76a66253 j_mayer
        cpu_abort(env, "Hypervisor decrementer exception is not implemented "
1572 76a66253 j_mayer
                  "yet !\n");
1573 2be0071f bellard
        goto store_next;
1574 2be0071f bellard
    /* Implementation specific exceptions */
1575 2be0071f bellard
    case 0x0A00:
1576 76a66253 j_mayer
        if (likely(env->spr[SPR_PVR] == CPU_PPC_G2 ||
1577 76a66253 j_mayer
                   env->spr[SPR_PVR] == CPU_PPC_G2LE)) {
1578 2be0071f bellard
            /* Critical interrupt on G2 */
1579 2be0071f bellard
            /* XXX: TODO */
1580 2be0071f bellard
            cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
1581 2be0071f bellard
            goto store_next;
1582 2be0071f bellard
        } else {
1583 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x0A00 !\n");
1584 2be0071f bellard
        }
1585 9a64fbe4 bellard
        return;
1586 2be0071f bellard
    case 0x0F20:
1587 c62db105 j_mayer
        idx = 9;
1588 2be0071f bellard
        switch (PPC_EXCP(env)) {
1589 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1590 2be0071f bellard
            /* APU unavailable on 405 */
1591 2be0071f bellard
            /* XXX: TODO */
1592 2be0071f bellard
            cpu_abort(env,
1593 2be0071f bellard
                      "APU unavailable exception is not implemented yet !\n");
1594 2be0071f bellard
            goto store_next;
1595 2be0071f bellard
        case PPC_FLAGS_EXCP_74xx:
1596 2be0071f bellard
            /* Altivec unavailable */
1597 2be0071f bellard
            /* XXX: TODO */
1598 2be0071f bellard
            cpu_abort(env, "Altivec unavailable exception "
1599 2be0071f bellard
                      "is not implemented yet !\n");
1600 2be0071f bellard
            goto store_next;
1601 2be0071f bellard
        default:
1602 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x0F20 !\n");
1603 2be0071f bellard
            break;
1604 2be0071f bellard
        }
1605 2be0071f bellard
        return;
1606 2be0071f bellard
    case 0x1000:
1607 c62db105 j_mayer
        idx = 10;
1608 2be0071f bellard
        switch (PPC_EXCP(env)) {
1609 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1610 2be0071f bellard
            /* PIT on 4xx */
1611 c62db105 j_mayer
            msr &= ~0xFFFF0000;
1612 c62db105 j_mayer
            if (loglevel != 0)
1613 c62db105 j_mayer
                fprintf(logfile, "PIT exception\n");
1614 2be0071f bellard
            goto store_next;
1615 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1616 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1617 2be0071f bellard
            /* ITLBMISS on 602/603 */
1618 2be0071f bellard
            goto store_gprs;
1619 76a66253 j_mayer
        case PPC_FLAGS_EXCP_7x5:
1620 76a66253 j_mayer
            /* ITLBMISS on 745/755 */
1621 76a66253 j_mayer
            goto tlb_miss;
1622 2be0071f bellard
        default:
1623 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1000 !\n");
1624 2be0071f bellard
            break;
1625 2be0071f bellard
        }
1626 2be0071f bellard
        return;
1627 2be0071f bellard
    case 0x1010:
1628 c62db105 j_mayer
        idx = 11;
1629 2be0071f bellard
        switch (PPC_EXCP(env)) {
1630 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1631 2be0071f bellard
            /* FIT on 4xx */
1632 c62db105 j_mayer
            msr &= ~0xFFFF0000;
1633 c62db105 j_mayer
            if (loglevel != 0)
1634 c62db105 j_mayer
                fprintf(logfile, "FIT exception\n");
1635 2be0071f bellard
            goto store_next;
1636 2be0071f bellard
        default:
1637 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1010 !\n");
1638 2be0071f bellard
            break;
1639 2be0071f bellard
        }
1640 2be0071f bellard
        return;
1641 2be0071f bellard
    case 0x1020:
1642 c62db105 j_mayer
        idx = 12;
1643 2be0071f bellard
        switch (PPC_EXCP(env)) {
1644 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1645 2be0071f bellard
            /* Watchdog on 4xx */
1646 c62db105 j_mayer
            msr &= ~0xFFFF0000;
1647 c62db105 j_mayer
            if (loglevel != 0)
1648 c62db105 j_mayer
                fprintf(logfile, "WDT exception\n");
1649 2be0071f bellard
            goto store_next;
1650 c62db105 j_mayer
        case PPC_FLAGS_EXCP_BOOKE:
1651 c62db105 j_mayer
            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1652 c62db105 j_mayer
            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1653 c62db105 j_mayer
            break;
1654 2be0071f bellard
        default:
1655 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1020 !\n");
1656 2be0071f bellard
            break;
1657 2be0071f bellard
        }
1658 2be0071f bellard
        return;
1659 2be0071f bellard
    case 0x1100:
1660 c62db105 j_mayer
        idx = 13;
1661 2be0071f bellard
        switch (PPC_EXCP(env)) {
1662 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1663 2be0071f bellard
            /* DTLBMISS on 4xx */
1664 a8dea12f j_mayer
            msr &= ~0xFFFF0000;
1665 2be0071f bellard
            goto store_next;
1666 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1667 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1668 2be0071f bellard
            /* DLTLBMISS on 602/603 */
1669 2be0071f bellard
            goto store_gprs;
1670 76a66253 j_mayer
        case PPC_FLAGS_EXCP_7x5:
1671 76a66253 j_mayer
            /* DLTLBMISS on 745/755 */
1672 76a66253 j_mayer
            goto tlb_miss;
1673 2be0071f bellard
        default:
1674 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1100 !\n");
1675 2be0071f bellard
            break;
1676 2be0071f bellard
        }
1677 2be0071f bellard
        return;
1678 2be0071f bellard
    case 0x1200:
1679 c62db105 j_mayer
        idx = 14;
1680 2be0071f bellard
        switch (PPC_EXCP(env)) {
1681 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1682 2be0071f bellard
            /* ITLBMISS on 4xx */
1683 a8dea12f j_mayer
            msr &= ~0xFFFF0000;
1684 2be0071f bellard
            goto store_next;
1685 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1686 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1687 2be0071f bellard
            /* DSTLBMISS on 602/603 */
1688 2be0071f bellard
        store_gprs:
1689 76a66253 j_mayer
            /* Swap temporary saved registers with GPRs */
1690 76a66253 j_mayer
            swap_gpr_tgpr(env);
1691 76a66253 j_mayer
            msr_tgpr = 1;
1692 2be0071f bellard
#if defined (DEBUG_SOFTWARE_TLB)
1693 2be0071f bellard
            if (loglevel != 0) {
1694 76a66253 j_mayer
                const unsigned char *es;
1695 76a66253 j_mayer
                target_ulong *miss, *cmp;
1696 76a66253 j_mayer
                int en;
1697 76a66253 j_mayer
                if (excp == 0x1000) {
1698 76a66253 j_mayer
                    es = "I";
1699 76a66253 j_mayer
                    en = 'I';
1700 76a66253 j_mayer
                    miss = &env->spr[SPR_IMISS];
1701 76a66253 j_mayer
                    cmp = &env->spr[SPR_ICMP];
1702 76a66253 j_mayer
                } else {
1703 76a66253 j_mayer
                    if (excp == 0x1100)
1704 76a66253 j_mayer
                        es = "DL";
1705 76a66253 j_mayer
                    else
1706 76a66253 j_mayer
                        es = "DS";
1707 76a66253 j_mayer
                    en = 'D';
1708 76a66253 j_mayer
                    miss = &env->spr[SPR_DMISS];
1709 76a66253 j_mayer
                    cmp = &env->spr[SPR_DCMP];
1710 76a66253 j_mayer
                }
1711 1b9eb036 j_mayer
                fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
1712 1b9eb036 j_mayer
                        " H1 " ADDRX " H2 " ADDRX " " ADDRX "\n",
1713 1b9eb036 j_mayer
                        es, en, *miss, en, *cmp,
1714 76a66253 j_mayer
                        env->spr[SPR_HASH1], env->spr[SPR_HASH2],
1715 2be0071f bellard
                        env->error_code);
1716 2be0071f bellard
            }
1717 9a64fbe4 bellard
#endif
1718 76a66253 j_mayer
            goto tlb_miss;
1719 76a66253 j_mayer
        case PPC_FLAGS_EXCP_7x5:
1720 76a66253 j_mayer
            /* DSTLBMISS on 745/755 */
1721 76a66253 j_mayer
        tlb_miss:
1722 76a66253 j_mayer
            msr &= ~0xF83F0000;
1723 2be0071f bellard
            msr |= env->crf[0] << 28;
1724 2be0071f bellard
            msr |= env->error_code; /* key, D/I, S/L bits */
1725 2be0071f bellard
            /* Set way using a LRU mechanism */
1726 76a66253 j_mayer
            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
1727 2be0071f bellard
            goto store_next;
1728 2be0071f bellard
        default:
1729 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1200 !\n");
1730 2be0071f bellard
            break;
1731 2be0071f bellard
        }
1732 2be0071f bellard
        return;
1733 2be0071f bellard
    case 0x1300:
1734 2be0071f bellard
        switch (PPC_EXCP(env)) {
1735 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1736 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1737 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1738 2be0071f bellard
        case PPC_FLAGS_EXCP_604:
1739 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1740 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1741 2be0071f bellard
            /* IABR on 6xx/7xx */
1742 2be0071f bellard
            /* XXX: TODO */
1743 2be0071f bellard
            cpu_abort(env, "IABR exception is not implemented yet !\n");
1744 2be0071f bellard
            goto store_next;
1745 2be0071f bellard
        default:
1746 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1300 !\n");
1747 2be0071f bellard
            break;
1748 2be0071f bellard
        }
1749 2be0071f bellard
        return;
1750 2be0071f bellard
    case 0x1400:
1751 2be0071f bellard
        switch (PPC_EXCP(env)) {
1752 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1753 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1754 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1755 2be0071f bellard
        case PPC_FLAGS_EXCP_604:
1756 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1757 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1758 2be0071f bellard
            /* SMI on 6xx/7xx */
1759 2be0071f bellard
            /* XXX: TODO */
1760 2be0071f bellard
            cpu_abort(env, "SMI exception is not implemented yet !\n");
1761 2be0071f bellard
            goto store_next;
1762 2be0071f bellard
        default:
1763 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1400 !\n");
1764 2be0071f bellard
            break;
1765 2be0071f bellard
        }
1766 2be0071f bellard
        return;
1767 2be0071f bellard
    case 0x1500:
1768 2be0071f bellard
        switch (PPC_EXCP(env)) {
1769 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1770 2be0071f bellard
            /* Watchdog on 602 */
1771 76a66253 j_mayer
            /* XXX: TODO */
1772 2be0071f bellard
            cpu_abort(env,
1773 2be0071f bellard
                      "602 watchdog exception is not implemented yet !\n");
1774 2be0071f bellard
            goto store_next;
1775 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1776 2be0071f bellard
            /* Soft patch exception on 970 */
1777 2be0071f bellard
            /* XXX: TODO */
1778 2be0071f bellard
            cpu_abort(env,
1779 2be0071f bellard
                      "970 soft-patch exception is not implemented yet !\n");
1780 2be0071f bellard
            goto store_next;
1781 2be0071f bellard
        case PPC_FLAGS_EXCP_74xx:
1782 2be0071f bellard
            /* VPU assist on 74xx */
1783 2be0071f bellard
            /* XXX: TODO */
1784 2be0071f bellard
            cpu_abort(env, "VPU assist exception is not implemented yet !\n");
1785 2be0071f bellard
            goto store_next;
1786 2be0071f bellard
        default:
1787 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1500 !\n");
1788 2be0071f bellard
            break;
1789 2be0071f bellard
        }
1790 2be0071f bellard
        return;
1791 2be0071f bellard
    case 0x1600:
1792 2be0071f bellard
        switch (PPC_EXCP(env)) {
1793 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1794 2be0071f bellard
            /* Emulation trap on 602 */
1795 2be0071f bellard
            /* XXX: TODO */
1796 2be0071f bellard
            cpu_abort(env, "602 emulation trap exception "
1797 2be0071f bellard
                      "is not implemented yet !\n");
1798 2be0071f bellard
            goto store_next;
1799 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1800 2be0071f bellard
            /* Maintenance exception on 970 */
1801 2be0071f bellard
            /* XXX: TODO */
1802 2be0071f bellard
            cpu_abort(env,
1803 2be0071f bellard
                      "970 maintenance exception is not implemented yet !\n");
1804 2be0071f bellard
            goto store_next;
1805 2be0071f bellard
        default:
1806 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1600 !\n");
1807 2be0071f bellard
            break;
1808 2be0071f bellard
        }
1809 2be0071f bellard
        return;
1810 2be0071f bellard
    case 0x1700:
1811 2be0071f bellard
        switch (PPC_EXCP(env)) {
1812 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1813 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1814 2be0071f bellard
            /* Thermal management interrupt on G3 */
1815 2be0071f bellard
            /* XXX: TODO */
1816 2be0071f bellard
            cpu_abort(env, "G3 thermal management exception "
1817 2be0071f bellard
                      "is not implemented yet !\n");
1818 2be0071f bellard
            goto store_next;
1819 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1820 2be0071f bellard
            /* VPU assist on 970 */
1821 2be0071f bellard
            /* XXX: TODO */
1822 2be0071f bellard
            cpu_abort(env,
1823 2be0071f bellard
                      "970 VPU assist exception is not implemented yet !\n");
1824 2be0071f bellard
            goto store_next;
1825 2be0071f bellard
        default:
1826 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1700 !\n");
1827 2be0071f bellard
            break;
1828 2be0071f bellard
        }
1829 2be0071f bellard
        return;
1830 2be0071f bellard
    case 0x1800:
1831 2be0071f bellard
        switch (PPC_EXCP(env)) {
1832 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1833 2be0071f bellard
            /* Thermal exception on 970 */
1834 2be0071f bellard
            /* XXX: TODO */
1835 2be0071f bellard
            cpu_abort(env, "970 thermal management exception "
1836 2be0071f bellard
                      "is not implemented yet !\n");
1837 2be0071f bellard
            goto store_next;
1838 2be0071f bellard
        default:
1839 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1800 !\n");
1840 2be0071f bellard
            break;
1841 2be0071f bellard
        }
1842 2be0071f bellard
        return;
1843 2be0071f bellard
    case 0x2000:
1844 2be0071f bellard
        switch (PPC_EXCP(env)) {
1845 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1846 2be0071f bellard
            /* DEBUG on 4xx */
1847 2be0071f bellard
            /* XXX: TODO */
1848 2be0071f bellard
            cpu_abort(env, "40x debug exception is not implemented yet !\n");
1849 2be0071f bellard
            goto store_next;
1850 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1851 2be0071f bellard
            /* Run mode exception on 601 */
1852 2be0071f bellard
            /* XXX: TODO */
1853 2be0071f bellard
            cpu_abort(env,
1854 2be0071f bellard
                      "601 run mode exception is not implemented yet !\n");
1855 2be0071f bellard
            goto store_next;
1856 c62db105 j_mayer
        case PPC_FLAGS_EXCP_BOOKE:
1857 c62db105 j_mayer
            srr_0 = &env->spr[SPR_BOOKE_CSRR0];
1858 c62db105 j_mayer
            srr_1 = &env->spr[SPR_BOOKE_CSRR1];
1859 c62db105 j_mayer
            break;
1860 2be0071f bellard
        default:
1861 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1800 !\n");
1862 2be0071f bellard
            break;
1863 2be0071f bellard
        }
1864 2be0071f bellard
        return;
1865 2be0071f bellard
    /* Other exceptions */
1866 2be0071f bellard
    /* Qemu internal exceptions:
1867 2be0071f bellard
     * we should never come here with those values: abort execution
1868 2be0071f bellard
     */
1869 2be0071f bellard
    default:
1870 2be0071f bellard
        cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
1871 9a64fbe4 bellard
        return;
1872 9a64fbe4 bellard
    store_current:
1873 2be0071f bellard
        /* save current instruction location */
1874 c62db105 j_mayer
        *srr_0 = env->nip - 4;
1875 9a64fbe4 bellard
        break;
1876 9a64fbe4 bellard
    store_next:
1877 2be0071f bellard
        /* save next instruction location */
1878 c62db105 j_mayer
        *srr_0 = env->nip;
1879 9a64fbe4 bellard
        break;
1880 9a64fbe4 bellard
    }
1881 2be0071f bellard
    /* Save msr */
1882 2be0071f bellard
    *srr_1 = msr;
1883 c62db105 j_mayer
    if (asrr_0 != NULL)
1884 c62db105 j_mayer
        *asrr_0 = *srr_0;
1885 c62db105 j_mayer
    if (asrr_1 != NULL)
1886 c62db105 j_mayer
        *asrr_1 = *srr_1;
1887 2be0071f bellard
    /* If we disactivated any translation, flush TLBs */
1888 2be0071f bellard
    if (msr_ir || msr_dr) {
1889 2be0071f bellard
        tlb_flush(env, 1);
1890 2be0071f bellard
    }
1891 9a64fbe4 bellard
    /* reload MSR with correct bits */
1892 9a64fbe4 bellard
    msr_ee = 0;
1893 9a64fbe4 bellard
    msr_pr = 0;
1894 9a64fbe4 bellard
    msr_fp = 0;
1895 9a64fbe4 bellard
    msr_fe0 = 0;
1896 9a64fbe4 bellard
    msr_se = 0;
1897 9a64fbe4 bellard
    msr_be = 0;
1898 9a64fbe4 bellard
    msr_fe1 = 0;
1899 9a64fbe4 bellard
    msr_ir = 0;
1900 9a64fbe4 bellard
    msr_dr = 0;
1901 9a64fbe4 bellard
    msr_ri = 0;
1902 9a64fbe4 bellard
    msr_le = msr_ile;
1903 c62db105 j_mayer
    if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) {
1904 c62db105 j_mayer
        msr_cm = msr_icm;
1905 c62db105 j_mayer
        if (idx == -1 || (idx >= 16 && idx < 32)) {
1906 c62db105 j_mayer
            cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n",
1907 c62db105 j_mayer
                      excp, excp, idx);
1908 c62db105 j_mayer
        }
1909 c62db105 j_mayer
#if defined(TARGET_PPC64)
1910 c62db105 j_mayer
        if (msr_cm)
1911 c62db105 j_mayer
            env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR];
1912 c62db105 j_mayer
        else
1913 c62db105 j_mayer
#endif
1914 c62db105 j_mayer
            env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR];
1915 c62db105 j_mayer
        if (idx < 16)
1916 c62db105 j_mayer
            env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx];
1917 c62db105 j_mayer
        else if (idx < 38)
1918 c62db105 j_mayer
            env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32];
1919 c62db105 j_mayer
    } else {
1920 c62db105 j_mayer
        msr_sf = msr_isf;
1921 c62db105 j_mayer
        env->nip = excp;
1922 c62db105 j_mayer
    }
1923 3fc6c082 bellard
    do_compute_hflags(env);
1924 9a64fbe4 bellard
    /* Jump to handler */
1925 9a64fbe4 bellard
    env->exception_index = EXCP_NONE;
1926 fb0eaffc bellard
}
1927 47103572 j_mayer
1928 e9df014c j_mayer
void ppc_hw_interrupt (CPUPPCState *env)
1929 47103572 j_mayer
{
1930 47103572 j_mayer
    int raised = 0;
1931 47103572 j_mayer
1932 47103572 j_mayer
#if 0
1933 47103572 j_mayer
    printf("%s: %p pending %08x req %08x %08x me %d ee %d\n",
1934 47103572 j_mayer
           __func__, env, env->pending_interrupts,
1935 47103572 j_mayer
           env->interrupt_request, interrupt_request,
1936 47103572 j_mayer
           msr_me, msr_ee);
1937 47103572 j_mayer
#endif
1938 47103572 j_mayer
    /* Raise it */
1939 47103572 j_mayer
    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
1940 47103572 j_mayer
        /* External reset / critical input */
1941 e9df014c j_mayer
        /* XXX: critical input should be handled another way.
1942 e9df014c j_mayer
         *      This code is not correct !
1943 e9df014c j_mayer
         */
1944 47103572 j_mayer
        env->exception_index = EXCP_RESET;
1945 47103572 j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
1946 47103572 j_mayer
        raised = 1;
1947 47103572 j_mayer
    }
1948 47103572 j_mayer
    if (raised == 0 && msr_me != 0) {
1949 47103572 j_mayer
        /* Machine check exception */
1950 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
1951 47103572 j_mayer
            env->exception_index = EXCP_MACHINE_CHECK;
1952 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
1953 47103572 j_mayer
            raised = 1;
1954 47103572 j_mayer
        }
1955 47103572 j_mayer
    }
1956 47103572 j_mayer
    if (raised == 0 && msr_ee != 0) {
1957 47103572 j_mayer
#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
1958 47103572 j_mayer
        /* Hypervisor decrementer exception */
1959 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
1960 47103572 j_mayer
            env->exception_index = EXCP_HDECR;
1961 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1962 47103572 j_mayer
            raised = 1;
1963 47103572 j_mayer
        } else
1964 47103572 j_mayer
#endif
1965 47103572 j_mayer
        /* Decrementer exception */
1966 47103572 j_mayer
        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
1967 47103572 j_mayer
            env->exception_index = EXCP_DECR;
1968 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
1969 47103572 j_mayer
            raised = 1;
1970 47103572 j_mayer
        /* Programmable interval timer on embedded PowerPC */
1971 47103572 j_mayer
        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
1972 47103572 j_mayer
            env->exception_index = EXCP_40x_PIT;
1973 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
1974 47103572 j_mayer
            raised = 1;
1975 47103572 j_mayer
        /* Fixed interval timer on embedded PowerPC */
1976 47103572 j_mayer
        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
1977 47103572 j_mayer
            env->exception_index = EXCP_40x_FIT;
1978 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
1979 47103572 j_mayer
            raised = 1;
1980 47103572 j_mayer
        /* Watchdog timer on embedded PowerPC */
1981 47103572 j_mayer
        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
1982 47103572 j_mayer
            env->exception_index = EXCP_40x_WATCHDOG;
1983 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
1984 47103572 j_mayer
            raised = 1;
1985 47103572 j_mayer
        /* External interrupt */
1986 47103572 j_mayer
        } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
1987 47103572 j_mayer
            env->exception_index = EXCP_EXTERNAL;
1988 e9df014c j_mayer
            /* Taking an external interrupt does not clear the external
1989 e9df014c j_mayer
             * interrupt status
1990 e9df014c j_mayer
             */
1991 e9df014c j_mayer
#if 0
1992 47103572 j_mayer
            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
1993 e9df014c j_mayer
#endif
1994 47103572 j_mayer
            raised = 1;
1995 47103572 j_mayer
        }
1996 47103572 j_mayer
#if 0 // TODO
1997 47103572 j_mayer
    /* External debug exception */
1998 47103572 j_mayer
    } else if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
1999 47103572 j_mayer
        env->exception_index = EXCP_xxx;
2000 47103572 j_mayer
        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2001 47103572 j_mayer
        raised = 1;
2002 47103572 j_mayer
#endif
2003 47103572 j_mayer
    }
2004 47103572 j_mayer
    if (raised != 0) {
2005 47103572 j_mayer
        env->error_code = 0;
2006 47103572 j_mayer
        do_interrupt(env);
2007 47103572 j_mayer
    }
2008 47103572 j_mayer
}
2009 18fba28c bellard
#endif /* !CONFIG_USER_ONLY */