Statistics
| Branch: | Revision:

root / target-ppc / helper.c @ 50443c98

History | View | Annotate | Download (43.3 kB)

1 79aceca5 bellard
/*
2 3fc6c082 bellard
 *  PowerPC emulation helpers for qemu.
3 79aceca5 bellard
 * 
4 3fc6c082 bellard
 *  Copyright (c) 2003-2005 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 9a64fbe4 bellard
//#define DEBUG_EXCEPTIONS
34 fdabc366 bellard
//#define FLUSH_ALL_TLBS
35 9a64fbe4 bellard
36 9a64fbe4 bellard
/*****************************************************************************/
37 3fc6c082 bellard
/* PowerPC MMU emulation */
38 a541f297 bellard
39 24741ef3 bellard
#if defined(CONFIG_USER_ONLY) 
40 24741ef3 bellard
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
41 24741ef3 bellard
                              int is_user, int is_softmmu)
42 24741ef3 bellard
{
43 24741ef3 bellard
    int exception, error_code;
44 24741ef3 bellard
    
45 24741ef3 bellard
    if (rw == 2) {
46 24741ef3 bellard
        exception = EXCP_ISI;
47 24741ef3 bellard
        error_code = 0;
48 24741ef3 bellard
    } else {
49 24741ef3 bellard
        exception = EXCP_DSI;
50 24741ef3 bellard
        error_code = 0;
51 24741ef3 bellard
        if (rw)
52 24741ef3 bellard
            error_code |= 0x02000000;
53 24741ef3 bellard
        env->spr[SPR_DAR] = address;
54 24741ef3 bellard
        env->spr[SPR_DSISR] = error_code;
55 24741ef3 bellard
    }
56 24741ef3 bellard
    env->exception_index = exception;
57 24741ef3 bellard
    env->error_code = error_code;
58 24741ef3 bellard
    return 1;
59 24741ef3 bellard
}
60 24741ef3 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
61 24741ef3 bellard
{
62 24741ef3 bellard
    return addr;
63 24741ef3 bellard
}
64 24741ef3 bellard
#else
65 9a64fbe4 bellard
/* Perform BAT hit & translation */
66 9a64fbe4 bellard
static int get_bat (CPUState *env, uint32_t *real, int *prot,
67 9a64fbe4 bellard
                    uint32_t virtual, int rw, int type)
68 9a64fbe4 bellard
{
69 9a64fbe4 bellard
    uint32_t *BATlt, *BATut, *BATu, *BATl;
70 9a64fbe4 bellard
    uint32_t base, BEPIl, BEPIu, bl;
71 9a64fbe4 bellard
    int i;
72 9a64fbe4 bellard
    int ret = -1;
73 9a64fbe4 bellard
74 9a64fbe4 bellard
#if defined (DEBUG_BATS)
75 9a64fbe4 bellard
    if (loglevel > 0) {
76 9a64fbe4 bellard
        fprintf(logfile, "%s: %cBAT v 0x%08x\n", __func__,
77 9a64fbe4 bellard
               type == ACCESS_CODE ? 'I' : 'D', virtual);
78 9a64fbe4 bellard
    }
79 9a64fbe4 bellard
#endif
80 9a64fbe4 bellard
    switch (type) {
81 9a64fbe4 bellard
    case ACCESS_CODE:
82 9a64fbe4 bellard
        BATlt = env->IBAT[1];
83 9a64fbe4 bellard
        BATut = env->IBAT[0];
84 9a64fbe4 bellard
        break;
85 9a64fbe4 bellard
    default:
86 9a64fbe4 bellard
        BATlt = env->DBAT[1];
87 9a64fbe4 bellard
        BATut = env->DBAT[0];
88 9a64fbe4 bellard
        break;
89 9a64fbe4 bellard
    }
90 9a64fbe4 bellard
#if defined (DEBUG_BATS)
91 9a64fbe4 bellard
    if (loglevel > 0) {
92 9a64fbe4 bellard
        fprintf(logfile, "%s...: %cBAT v 0x%08x\n", __func__,
93 9a64fbe4 bellard
               type == ACCESS_CODE ? 'I' : 'D', virtual);
94 9a64fbe4 bellard
    }
95 9a64fbe4 bellard
#endif
96 9a64fbe4 bellard
    base = virtual & 0xFFFC0000;
97 9a64fbe4 bellard
    for (i = 0; i < 4; i++) {
98 9a64fbe4 bellard
        BATu = &BATut[i];
99 9a64fbe4 bellard
        BATl = &BATlt[i];
100 9a64fbe4 bellard
        BEPIu = *BATu & 0xF0000000;
101 9a64fbe4 bellard
        BEPIl = *BATu & 0x0FFE0000;
102 9a64fbe4 bellard
        bl = (*BATu & 0x00001FFC) << 15;
103 9a64fbe4 bellard
#if defined (DEBUG_BATS)
104 9a64fbe4 bellard
        if (loglevel > 0) {
105 9a64fbe4 bellard
            fprintf(logfile, "%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x\n",
106 9a64fbe4 bellard
                    __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
107 9a64fbe4 bellard
                    *BATu, *BATl);
108 9a64fbe4 bellard
        }
109 9a64fbe4 bellard
#endif
110 9a64fbe4 bellard
        if ((virtual & 0xF0000000) == BEPIu &&
111 9a64fbe4 bellard
            ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
112 9a64fbe4 bellard
            /* BAT matches */
113 9a64fbe4 bellard
            if ((msr_pr == 0 && (*BATu & 0x00000002)) ||
114 9a64fbe4 bellard
                (msr_pr == 1 && (*BATu & 0x00000001))) {
115 9a64fbe4 bellard
                /* Get physical address */
116 9a64fbe4 bellard
                *real = (*BATl & 0xF0000000) |
117 9a64fbe4 bellard
                    ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
118 a541f297 bellard
                    (virtual & 0x0001F000);
119 9a64fbe4 bellard
                if (*BATl & 0x00000001)
120 5f21aef2 bellard
                    *prot = PAGE_READ;
121 9a64fbe4 bellard
                if (*BATl & 0x00000002)
122 5f21aef2 bellard
                    *prot = PAGE_WRITE | PAGE_READ;
123 9a64fbe4 bellard
#if defined (DEBUG_BATS)
124 9a64fbe4 bellard
                if (loglevel > 0) {
125 9a64fbe4 bellard
                    fprintf(logfile, "BAT %d match: r 0x%08x prot=%c%c\n",
126 5f21aef2 bellard
                            i, *real, *prot & PAGE_READ ? 'R' : '-',
127 5f21aef2 bellard
                            *prot & PAGE_WRITE ? 'W' : '-');
128 9a64fbe4 bellard
                }
129 9a64fbe4 bellard
#endif
130 9a64fbe4 bellard
                ret = 0;
131 9a64fbe4 bellard
                break;
132 9a64fbe4 bellard
            }
133 9a64fbe4 bellard
        }
134 9a64fbe4 bellard
    }
135 9a64fbe4 bellard
    if (ret < 0) {
136 9a64fbe4 bellard
#if defined (DEBUG_BATS)
137 9a64fbe4 bellard
        printf("no BAT match for 0x%08x:\n", virtual);
138 9a64fbe4 bellard
        for (i = 0; i < 4; i++) {
139 9a64fbe4 bellard
            BATu = &BATut[i];
140 9a64fbe4 bellard
            BATl = &BATlt[i];
141 9a64fbe4 bellard
            BEPIu = *BATu & 0xF0000000;
142 9a64fbe4 bellard
            BEPIl = *BATu & 0x0FFE0000;
143 9a64fbe4 bellard
            bl = (*BATu & 0x00001FFC) << 15;
144 9a64fbe4 bellard
            printf("%s: %cBAT%d v 0x%08x BATu 0x%08x BATl 0x%08x \n\t"
145 9a64fbe4 bellard
                   "0x%08x 0x%08x 0x%08x\n",
146 9a64fbe4 bellard
                   __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
147 9a64fbe4 bellard
                   *BATu, *BATl, BEPIu, BEPIl, bl);
148 9a64fbe4 bellard
        }
149 9a64fbe4 bellard
#endif
150 9a64fbe4 bellard
    }
151 9a64fbe4 bellard
    /* No hit */
152 9a64fbe4 bellard
    return ret;
153 9a64fbe4 bellard
}
154 9a64fbe4 bellard
155 9a64fbe4 bellard
/* PTE table lookup */
156 9a64fbe4 bellard
static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va,
157 9a64fbe4 bellard
                     int h, int key, int rw)
158 9a64fbe4 bellard
{
159 a541f297 bellard
    uint32_t pte0, pte1, keep = 0, access = 0;
160 9a64fbe4 bellard
    int i, good = -1, store = 0;
161 9a64fbe4 bellard
    int ret = -1; /* No entry found */
162 9a64fbe4 bellard
163 9a64fbe4 bellard
    for (i = 0; i < 8; i++) {
164 8df1cd07 bellard
        pte0 = ldl_phys(base + (i * 8));
165 8df1cd07 bellard
        pte1 =  ldl_phys(base + (i * 8) + 4);
166 9a64fbe4 bellard
#if defined (DEBUG_MMU)
167 d094807b bellard
        if (loglevel > 0) {
168 a541f297 bellard
            fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x "
169 a541f297 bellard
                    "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1,
170 a541f297 bellard
                    pte0 >> 31, h, (pte0 >> 6) & 1, va);
171 a541f297 bellard
        }
172 9a64fbe4 bellard
#endif
173 9a64fbe4 bellard
        /* Check validity and table match */
174 9a64fbe4 bellard
        if (pte0 & 0x80000000 && (h == ((pte0 >> 6) & 1))) {
175 9a64fbe4 bellard
            /* Check vsid & api */
176 9a64fbe4 bellard
            if ((pte0 & 0x7FFFFFBF) == va) {
177 9a64fbe4 bellard
                if (good == -1) {
178 9a64fbe4 bellard
                    good = i;
179 9a64fbe4 bellard
                    keep = pte1;
180 9a64fbe4 bellard
                } else {
181 9a64fbe4 bellard
                    /* All matches should have equal RPN, WIMG & PP */
182 9a64fbe4 bellard
                    if ((keep & 0xFFFFF07B) != (pte1 & 0xFFFFF07B)) {
183 a541f297 bellard
                        if (loglevel > 0)
184 a541f297 bellard
                            fprintf(logfile, "Bad RPN/WIMG/PP\n");
185 9a64fbe4 bellard
                        return -1;
186 9a64fbe4 bellard
                    }
187 9a64fbe4 bellard
                }
188 9a64fbe4 bellard
                /* Check access rights */
189 9a64fbe4 bellard
                if (key == 0) {
190 5f21aef2 bellard
                    access = PAGE_READ;
191 9a64fbe4 bellard
                    if ((pte1 & 0x00000003) != 0x3)
192 5f21aef2 bellard
                        access |= PAGE_WRITE;
193 9a64fbe4 bellard
                } else {
194 9a64fbe4 bellard
                    switch (pte1 & 0x00000003) {
195 9a64fbe4 bellard
                    case 0x0:
196 a541f297 bellard
                        access = 0;
197 9a64fbe4 bellard
                        break;
198 9a64fbe4 bellard
                    case 0x1:
199 9a64fbe4 bellard
                    case 0x3:
200 5f21aef2 bellard
                        access = PAGE_READ;
201 9a64fbe4 bellard
                        break;
202 9a64fbe4 bellard
                    case 0x2:
203 5f21aef2 bellard
                        access = PAGE_READ | PAGE_WRITE;
204 9a64fbe4 bellard
                        break;
205 9a64fbe4 bellard
                    }
206 9a64fbe4 bellard
                }
207 a541f297 bellard
                if (ret < 0) {
208 5f21aef2 bellard
                    if ((rw == 0 && (access & PAGE_READ)) ||
209 5f21aef2 bellard
                        (rw == 1 && (access & PAGE_WRITE))) {
210 9a64fbe4 bellard
#if defined (DEBUG_MMU)
211 a541f297 bellard
                        if (loglevel > 0)
212 a541f297 bellard
                            fprintf(logfile, "PTE access granted !\n");
213 9a64fbe4 bellard
#endif
214 d094807b bellard
                        good = i;
215 d094807b bellard
                        keep = pte1;
216 d094807b bellard
                        ret = 0;
217 a541f297 bellard
                    } else {
218 a541f297 bellard
                        /* Access right violation */
219 d094807b bellard
                        ret = -2;
220 9a64fbe4 bellard
#if defined (DEBUG_MMU)
221 a541f297 bellard
                        if (loglevel > 0)
222 a541f297 bellard
                            fprintf(logfile, "PTE access rejected\n");
223 9a64fbe4 bellard
#endif
224 d094807b bellard
                    }
225 a541f297 bellard
                    *prot = access;
226 a541f297 bellard
                }
227 9a64fbe4 bellard
            }
228 9a64fbe4 bellard
        }
229 9a64fbe4 bellard
    }
230 9a64fbe4 bellard
    if (good != -1) {
231 9a64fbe4 bellard
        *RPN = keep & 0xFFFFF000;
232 9a64fbe4 bellard
#if defined (DEBUG_MMU)
233 d094807b bellard
        if (loglevel > 0) {
234 a541f297 bellard
            fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n",
235 9a64fbe4 bellard
               *RPN, *prot, ret);
236 a541f297 bellard
        }
237 9a64fbe4 bellard
#endif
238 9a64fbe4 bellard
        /* Update page flags */
239 9a64fbe4 bellard
        if (!(keep & 0x00000100)) {
240 a541f297 bellard
            /* Access flag */
241 9a64fbe4 bellard
            keep |= 0x00000100;
242 9a64fbe4 bellard
            store = 1;
243 9a64fbe4 bellard
        }
244 d094807b bellard
        if (!(keep & 0x00000080)) {
245 a541f297 bellard
            if (rw && ret == 0) {
246 a541f297 bellard
                /* Change flag */
247 9a64fbe4 bellard
                keep |= 0x00000080;
248 9a64fbe4 bellard
                store = 1;
249 a541f297 bellard
            } else {
250 a541f297 bellard
                /* Force page fault for first write access */
251 5f21aef2 bellard
                *prot &= ~PAGE_WRITE;
252 9a64fbe4 bellard
            }
253 9a64fbe4 bellard
        }
254 a541f297 bellard
        if (store) {
255 8df1cd07 bellard
            stl_phys_notdirty(base + (good * 8) + 4, keep);
256 a541f297 bellard
        }
257 9a64fbe4 bellard
    }
258 9a64fbe4 bellard
259 9a64fbe4 bellard
    return ret;
260 79aceca5 bellard
}
261 79aceca5 bellard
262 9a64fbe4 bellard
static inline uint32_t get_pgaddr (uint32_t sdr1, uint32_t hash, uint32_t mask)
263 79aceca5 bellard
{
264 9a64fbe4 bellard
    return (sdr1 & 0xFFFF0000) | (hash & mask);
265 79aceca5 bellard
}
266 79aceca5 bellard
267 9a64fbe4 bellard
/* Perform segment based translation */
268 9a64fbe4 bellard
static int get_segment (CPUState *env, uint32_t *real, int *prot,
269 9a64fbe4 bellard
                        uint32_t virtual, int rw, int type)
270 79aceca5 bellard
{
271 9a64fbe4 bellard
    uint32_t pg_addr, sdr, ptem, vsid, pgidx;
272 9a64fbe4 bellard
    uint32_t hash, mask;
273 9a64fbe4 bellard
    uint32_t sr;
274 9a64fbe4 bellard
    int key;
275 9a64fbe4 bellard
    int ret = -1, ret2;
276 79aceca5 bellard
277 9a64fbe4 bellard
    sr = env->sr[virtual >> 28];
278 9a64fbe4 bellard
#if defined (DEBUG_MMU)
279 a541f297 bellard
    if (loglevel > 0) {
280 a541f297 bellard
        fprintf(logfile, "Check segment v=0x%08x %d 0x%08x nip=0x%08x "
281 a541f297 bellard
                "lr=0x%08x ir=%d dr=%d pr=%d %d t=%d\n",
282 a541f297 bellard
                virtual, virtual >> 28, sr, env->nip,
283 a541f297 bellard
                env->lr, msr_ir, msr_dr, msr_pr, rw, type);
284 a541f297 bellard
    }
285 9a64fbe4 bellard
#endif
286 a541f297 bellard
    key = (((sr & 0x20000000) && msr_pr == 1) ||
287 a541f297 bellard
        ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0;
288 9a64fbe4 bellard
    if ((sr & 0x80000000) == 0) {
289 9a64fbe4 bellard
#if defined (DEBUG_MMU)
290 d094807b bellard
    if (loglevel > 0) 
291 a541f297 bellard
            fprintf(logfile, "pte segment: key=%d n=0x%08x\n",
292 a541f297 bellard
                    key, sr & 0x10000000);
293 9a64fbe4 bellard
#endif
294 9a64fbe4 bellard
        /* Check if instruction fetch is allowed, if needed */
295 9a64fbe4 bellard
        if (type != ACCESS_CODE || (sr & 0x10000000) == 0) {
296 9a64fbe4 bellard
            /* Page address translation */
297 9a64fbe4 bellard
            vsid = sr & 0x00FFFFFF;
298 9a64fbe4 bellard
            pgidx = (virtual >> 12) & 0xFFFF;
299 a541f297 bellard
            sdr = env->sdr1;
300 a541f297 bellard
            hash = ((vsid ^ pgidx) & 0x0007FFFF) << 6;
301 9a64fbe4 bellard
            mask = ((sdr & 0x000001FF) << 16) | 0xFFC0;
302 9a64fbe4 bellard
            pg_addr = get_pgaddr(sdr, hash, mask);
303 9a64fbe4 bellard
            ptem = (vsid << 7) | (pgidx >> 10);
304 9a64fbe4 bellard
#if defined (DEBUG_MMU)
305 a541f297 bellard
            if (loglevel > 0) {
306 a541f297 bellard
                fprintf(logfile, "0 sdr1=0x%08x vsid=0x%06x api=0x%04x "
307 a541f297 bellard
                        "hash=0x%07x pg_addr=0x%08x\n", sdr, vsid, pgidx, hash,
308 a541f297 bellard
                        pg_addr);
309 a541f297 bellard
            }
310 9a64fbe4 bellard
#endif
311 9a64fbe4 bellard
            /* Primary table lookup */
312 9a64fbe4 bellard
            ret = find_pte(real, prot, pg_addr, ptem, 0, key, rw);
313 9a64fbe4 bellard
            if (ret < 0) {
314 9a64fbe4 bellard
                /* Secondary table lookup */
315 9a64fbe4 bellard
                hash = (~hash) & 0x01FFFFC0;
316 9a64fbe4 bellard
                pg_addr = get_pgaddr(sdr, hash, mask);
317 9a64fbe4 bellard
#if defined (DEBUG_MMU)
318 a541f297 bellard
                if (virtual != 0xEFFFFFFF && loglevel > 0) {
319 a541f297 bellard
                    fprintf(logfile, "1 sdr1=0x%08x vsid=0x%06x api=0x%04x "
320 a541f297 bellard
                            "hash=0x%05x pg_addr=0x%08x\n", sdr, vsid, pgidx,
321 a541f297 bellard
                            hash, pg_addr);
322 a541f297 bellard
                }
323 9a64fbe4 bellard
#endif
324 9a64fbe4 bellard
                ret2 = find_pte(real, prot, pg_addr, ptem, 1, key, rw);
325 9a64fbe4 bellard
                if (ret2 != -1)
326 9a64fbe4 bellard
                    ret = ret2;
327 9a64fbe4 bellard
            }
328 9a64fbe4 bellard
        } else {
329 9a64fbe4 bellard
#if defined (DEBUG_MMU)
330 a541f297 bellard
            if (loglevel > 0)
331 a541f297 bellard
                fprintf(logfile, "No access allowed\n");
332 9a64fbe4 bellard
#endif
333 a541f297 bellard
            ret = -3;
334 9a64fbe4 bellard
        }
335 9a64fbe4 bellard
    } else {
336 9a64fbe4 bellard
#if defined (DEBUG_MMU)
337 a541f297 bellard
        if (loglevel > 0)
338 a541f297 bellard
            fprintf(logfile, "direct store...\n");
339 9a64fbe4 bellard
#endif
340 9a64fbe4 bellard
        /* Direct-store segment : absolutely *BUGGY* for now */
341 9a64fbe4 bellard
        switch (type) {
342 9a64fbe4 bellard
        case ACCESS_INT:
343 9a64fbe4 bellard
            /* Integer load/store : only access allowed */
344 9a64fbe4 bellard
            break;
345 9a64fbe4 bellard
        case ACCESS_CODE:
346 9a64fbe4 bellard
            /* No code fetch is allowed in direct-store areas */
347 9a64fbe4 bellard
            return -4;
348 9a64fbe4 bellard
        case ACCESS_FLOAT:
349 9a64fbe4 bellard
            /* Floating point load/store */
350 9a64fbe4 bellard
            return -4;
351 9a64fbe4 bellard
        case ACCESS_RES:
352 9a64fbe4 bellard
            /* lwarx, ldarx or srwcx. */
353 9a64fbe4 bellard
            return -4;
354 9a64fbe4 bellard
        case ACCESS_CACHE:
355 9a64fbe4 bellard
            /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
356 9a64fbe4 bellard
            /* Should make the instruction do no-op.
357 9a64fbe4 bellard
             * As it already do no-op, it's quite easy :-)
358 9a64fbe4 bellard
             */
359 9a64fbe4 bellard
            *real = virtual;
360 9a64fbe4 bellard
            return 0;
361 9a64fbe4 bellard
        case ACCESS_EXT:
362 9a64fbe4 bellard
            /* eciwx or ecowx */
363 9a64fbe4 bellard
            return -4;
364 9a64fbe4 bellard
        default:
365 9a64fbe4 bellard
            if (logfile) {
366 9a64fbe4 bellard
                fprintf(logfile, "ERROR: instruction should not need "
367 9a64fbe4 bellard
                        "address translation\n");
368 9a64fbe4 bellard
            }
369 9a64fbe4 bellard
            printf("ERROR: instruction should not need "
370 9a64fbe4 bellard
                   "address translation\n");
371 9a64fbe4 bellard
            return -4;
372 9a64fbe4 bellard
        }
373 9a64fbe4 bellard
        if ((rw == 1 || key != 1) && (rw == 0 || key != 0)) {
374 9a64fbe4 bellard
            *real = virtual;
375 9a64fbe4 bellard
            ret = 2;
376 9a64fbe4 bellard
        } else {
377 9a64fbe4 bellard
            ret = -2;
378 9a64fbe4 bellard
        }
379 79aceca5 bellard
    }
380 9a64fbe4 bellard
381 9a64fbe4 bellard
    return ret;
382 79aceca5 bellard
}
383 79aceca5 bellard
384 24741ef3 bellard
static int get_physical_address (CPUState *env, uint32_t *physical, int *prot,
385 24741ef3 bellard
                                 uint32_t address, int rw, int access_type)
386 9a64fbe4 bellard
{
387 9a64fbe4 bellard
    int ret;
388 514fb8c1 bellard
#if 0
389 9a64fbe4 bellard
    if (loglevel > 0) {
390 9a64fbe4 bellard
        fprintf(logfile, "%s\n", __func__);
391 9a64fbe4 bellard
    }
392 514fb8c1 bellard
#endif    
393 4b3686fa bellard
    if ((access_type == ACCESS_CODE && msr_ir == 0) ||
394 4b3686fa bellard
        (access_type != ACCESS_CODE && msr_dr == 0)) {
395 9a64fbe4 bellard
        /* No address translation */
396 a541f297 bellard
        *physical = address & ~0xFFF;
397 5f21aef2 bellard
        *prot = PAGE_READ | PAGE_WRITE;
398 9a64fbe4 bellard
        ret = 0;
399 9a64fbe4 bellard
    } else {
400 9a64fbe4 bellard
        /* Try to find a BAT */
401 9a64fbe4 bellard
        ret = get_bat(env, physical, prot, address, rw, access_type);
402 9a64fbe4 bellard
        if (ret < 0) {
403 9a64fbe4 bellard
            /* We didn't match any BAT entry */
404 9a64fbe4 bellard
            ret = get_segment(env, physical, prot, address, rw, access_type);
405 9a64fbe4 bellard
        }
406 9a64fbe4 bellard
    }
407 514fb8c1 bellard
#if 0
408 a541f297 bellard
    if (loglevel > 0) {
409 a541f297 bellard
        fprintf(logfile, "%s address %08x => %08x\n",
410 a541f297 bellard
                __func__, address, *physical);
411 a541f297 bellard
    }
412 514fb8c1 bellard
#endif    
413 9a64fbe4 bellard
    return ret;
414 9a64fbe4 bellard
}
415 9a64fbe4 bellard
416 a6b025d3 bellard
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
417 a6b025d3 bellard
{
418 a6b025d3 bellard
    uint32_t phys_addr;
419 a6b025d3 bellard
    int prot;
420 a6b025d3 bellard
421 a6b025d3 bellard
    if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
422 a6b025d3 bellard
        return -1;
423 a6b025d3 bellard
    return phys_addr;
424 a6b025d3 bellard
}
425 9a64fbe4 bellard
426 9a64fbe4 bellard
/* Perform address translation */
427 9a64fbe4 bellard
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
428 a541f297 bellard
                              int is_user, int is_softmmu)
429 9a64fbe4 bellard
{
430 9a64fbe4 bellard
    uint32_t physical;
431 9a64fbe4 bellard
    int prot;
432 9a64fbe4 bellard
    int exception = 0, error_code = 0;
433 a541f297 bellard
    int access_type;
434 9a64fbe4 bellard
    int ret = 0;
435 9a64fbe4 bellard
436 b769d8fe bellard
    if (rw == 2) {
437 b769d8fe bellard
        /* code access */
438 b769d8fe bellard
        rw = 0;
439 b769d8fe bellard
        access_type = ACCESS_CODE;
440 b769d8fe bellard
    } else {
441 b769d8fe bellard
        /* data access */
442 b769d8fe bellard
        /* XXX: put correct access by using cpu_restore_state()
443 b769d8fe bellard
           correctly */
444 b769d8fe bellard
        access_type = ACCESS_INT;
445 b769d8fe bellard
        //        access_type = env->access_type;
446 b769d8fe bellard
    }
447 9a64fbe4 bellard
    if (env->user_mode_only) {
448 9a64fbe4 bellard
        /* user mode only emulation */
449 1ef59d0a bellard
        ret = -2;
450 9a64fbe4 bellard
        goto do_fault;
451 9a64fbe4 bellard
    }
452 9a64fbe4 bellard
    ret = get_physical_address(env, &physical, &prot,
453 9a64fbe4 bellard
                               address, rw, access_type);
454 9a64fbe4 bellard
    if (ret == 0) {
455 a541f297 bellard
        ret = tlb_set_page(env, address & ~0xFFF, physical, prot,
456 a541f297 bellard
                           is_user, is_softmmu);
457 9a64fbe4 bellard
    } else if (ret < 0) {
458 9a64fbe4 bellard
    do_fault:
459 9a64fbe4 bellard
#if defined (DEBUG_MMU)
460 a541f297 bellard
        if (loglevel > 0)
461 7fe48483 bellard
            cpu_dump_state(env, logfile, fprintf, 0);
462 9a64fbe4 bellard
#endif
463 9a64fbe4 bellard
        if (access_type == ACCESS_CODE) {
464 9a64fbe4 bellard
            exception = EXCP_ISI;
465 9a64fbe4 bellard
            switch (ret) {
466 9a64fbe4 bellard
            case -1:
467 9a64fbe4 bellard
                /* No matches in page tables */
468 2be0071f bellard
                error_code = 0x40000000;
469 9a64fbe4 bellard
                break;
470 9a64fbe4 bellard
            case -2:
471 9a64fbe4 bellard
                /* Access rights violation */
472 2be0071f bellard
                error_code = 0x08000000;
473 9a64fbe4 bellard
                break;
474 9a64fbe4 bellard
            case -3:
475 a541f297 bellard
                /* No execute protection violation */
476 2be0071f bellard
                error_code = 0x10000000;
477 9a64fbe4 bellard
                break;
478 9a64fbe4 bellard
            case -4:
479 9a64fbe4 bellard
                /* Direct store exception */
480 9a64fbe4 bellard
                /* No code fetch is allowed in direct-store areas */
481 2be0071f bellard
                error_code = 0x10000000;
482 2be0071f bellard
                break;
483 2be0071f bellard
            case -5:
484 2be0071f bellard
                /* No match in segment table */
485 2be0071f bellard
                exception = EXCP_ISEG;
486 2be0071f bellard
                error_code = 0;
487 9a64fbe4 bellard
                break;
488 9a64fbe4 bellard
            }
489 9a64fbe4 bellard
        } else {
490 9a64fbe4 bellard
            exception = EXCP_DSI;
491 9a64fbe4 bellard
            switch (ret) {
492 9a64fbe4 bellard
            case -1:
493 9a64fbe4 bellard
                /* No matches in page tables */
494 2be0071f bellard
                error_code = 0x40000000;
495 9a64fbe4 bellard
                break;
496 9a64fbe4 bellard
            case -2:
497 9a64fbe4 bellard
                /* Access rights violation */
498 2be0071f bellard
                error_code = 0x08000000;
499 9a64fbe4 bellard
                break;
500 9a64fbe4 bellard
            case -4:
501 9a64fbe4 bellard
                /* Direct store exception */
502 9a64fbe4 bellard
                switch (access_type) {
503 9a64fbe4 bellard
                case ACCESS_FLOAT:
504 9a64fbe4 bellard
                    /* Floating point load/store */
505 9a64fbe4 bellard
                    exception = EXCP_ALIGN;
506 9a64fbe4 bellard
                    error_code = EXCP_ALIGN_FP;
507 9a64fbe4 bellard
                    break;
508 9a64fbe4 bellard
                case ACCESS_RES:
509 9a64fbe4 bellard
                    /* lwarx, ldarx or srwcx. */
510 2be0071f bellard
                    error_code = 0x04000000;
511 9a64fbe4 bellard
                    break;
512 9a64fbe4 bellard
                case ACCESS_EXT:
513 9a64fbe4 bellard
                    /* eciwx or ecowx */
514 2be0071f bellard
                    error_code = 0x04100000;
515 9a64fbe4 bellard
                    break;
516 9a64fbe4 bellard
                default:
517 a541f297 bellard
                    printf("DSI: invalid exception (%d)\n", ret);
518 9a64fbe4 bellard
                    exception = EXCP_PROGRAM;
519 9a64fbe4 bellard
                    error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
520 9a64fbe4 bellard
                    break;
521 9a64fbe4 bellard
                }
522 fdabc366 bellard
                break;
523 2be0071f bellard
            case -5:
524 2be0071f bellard
                /* No match in segment table */
525 2be0071f bellard
                exception = EXCP_DSEG;
526 2be0071f bellard
                error_code = 0;
527 2be0071f bellard
                break;
528 9a64fbe4 bellard
            }
529 fdabc366 bellard
            if (exception == EXCP_DSI && rw == 1)
530 2be0071f bellard
                error_code |= 0x02000000;
531 a541f297 bellard
            /* Store fault address */
532 3fc6c082 bellard
            env->spr[SPR_DAR] = address;
533 2be0071f bellard
            env->spr[SPR_DSISR] = error_code;
534 9a64fbe4 bellard
        }
535 9a64fbe4 bellard
#if 0
536 9a64fbe4 bellard
        printf("%s: set exception to %d %02x\n",
537 9a64fbe4 bellard
               __func__, exception, error_code);
538 9a64fbe4 bellard
#endif
539 9a64fbe4 bellard
        env->exception_index = exception;
540 9a64fbe4 bellard
        env->error_code = error_code;
541 9a64fbe4 bellard
        ret = 1;
542 9a64fbe4 bellard
    }
543 9a64fbe4 bellard
    return ret;
544 9a64fbe4 bellard
}
545 24741ef3 bellard
#endif
546 9a64fbe4 bellard
547 3fc6c082 bellard
/*****************************************************************************/
548 3fc6c082 bellard
/* BATs management */
549 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
550 3fc6c082 bellard
static inline void do_invalidate_BAT (CPUPPCState *env,
551 3fc6c082 bellard
                                      target_ulong BATu, target_ulong mask)
552 3fc6c082 bellard
{
553 3fc6c082 bellard
    target_ulong base, end, page;
554 3fc6c082 bellard
    base = BATu & ~0x0001FFFF;
555 3fc6c082 bellard
    end = base + mask + 0x00020000;
556 3fc6c082 bellard
#if defined (DEBUG_BATS)
557 3fc6c082 bellard
    if (loglevel != 0)
558 3fc6c082 bellard
        fprintf(logfile, "Flush BAT from %08x to %08x (%08x)\n", base, end, mask);
559 3fc6c082 bellard
#endif
560 3fc6c082 bellard
    for (page = base; page != end; page += TARGET_PAGE_SIZE)
561 3fc6c082 bellard
        tlb_flush_page(env, page);
562 3fc6c082 bellard
#if defined (DEBUG_BATS)
563 3fc6c082 bellard
    if (loglevel != 0)
564 3fc6c082 bellard
        fprintf(logfile, "Flush done\n");
565 3fc6c082 bellard
#endif
566 3fc6c082 bellard
}
567 3fc6c082 bellard
#endif
568 3fc6c082 bellard
569 3fc6c082 bellard
static inline void dump_store_bat (CPUPPCState *env, char ID, int ul, int nr,
570 3fc6c082 bellard
                                   target_ulong value)
571 3fc6c082 bellard
{
572 3fc6c082 bellard
#if defined (DEBUG_BATS)
573 3fc6c082 bellard
    if (loglevel != 0) {
574 3fc6c082 bellard
        fprintf(logfile, "Set %cBAT%d%c to 0x%08lx (0x%08lx)\n",
575 3fc6c082 bellard
                ID, nr, ul == 0 ? 'u' : 'l', (unsigned long)value,
576 3fc6c082 bellard
                (unsigned long)env->nip);
577 3fc6c082 bellard
    }
578 3fc6c082 bellard
#endif
579 3fc6c082 bellard
}
580 3fc6c082 bellard
581 3fc6c082 bellard
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
582 3fc6c082 bellard
{
583 3fc6c082 bellard
    return env->IBAT[0][nr];
584 3fc6c082 bellard
}
585 3fc6c082 bellard
586 3fc6c082 bellard
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
587 3fc6c082 bellard
{
588 3fc6c082 bellard
    return env->IBAT[1][nr];
589 3fc6c082 bellard
}
590 3fc6c082 bellard
591 3fc6c082 bellard
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
592 3fc6c082 bellard
{
593 3fc6c082 bellard
    target_ulong mask;
594 3fc6c082 bellard
595 3fc6c082 bellard
    dump_store_bat(env, 'I', 0, nr, value);
596 3fc6c082 bellard
    if (env->IBAT[0][nr] != value) {
597 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
598 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
599 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
600 3fc6c082 bellard
#endif
601 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
602 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
603 3fc6c082 bellard
         */
604 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
605 3fc6c082 bellard
        env->IBAT[0][nr] = (value & 0x00001FFFUL) |
606 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
607 3fc6c082 bellard
        env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
608 3fc6c082 bellard
            (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
609 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
610 3fc6c082 bellard
        do_invalidate_BAT(env, env->IBAT[0][nr], mask);
611 3fc6c082 bellard
#endif
612 3fc6c082 bellard
#if defined(FLUSH_ALL_TLBS)
613 3fc6c082 bellard
        tlb_flush(env, 1);
614 3fc6c082 bellard
#endif
615 3fc6c082 bellard
    }
616 3fc6c082 bellard
}
617 3fc6c082 bellard
618 3fc6c082 bellard
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
619 3fc6c082 bellard
{
620 3fc6c082 bellard
    dump_store_bat(env, 'I', 1, nr, value);
621 3fc6c082 bellard
    env->IBAT[1][nr] = value;
622 3fc6c082 bellard
}
623 3fc6c082 bellard
624 3fc6c082 bellard
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
625 3fc6c082 bellard
{
626 3fc6c082 bellard
    return env->DBAT[0][nr];
627 3fc6c082 bellard
}
628 3fc6c082 bellard
629 3fc6c082 bellard
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
630 3fc6c082 bellard
{
631 3fc6c082 bellard
    return env->DBAT[1][nr];
632 3fc6c082 bellard
}
633 3fc6c082 bellard
634 3fc6c082 bellard
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
635 3fc6c082 bellard
{
636 3fc6c082 bellard
    target_ulong mask;
637 3fc6c082 bellard
638 3fc6c082 bellard
    dump_store_bat(env, 'D', 0, nr, value);
639 3fc6c082 bellard
    if (env->DBAT[0][nr] != value) {
640 3fc6c082 bellard
        /* When storing valid upper BAT, mask BEPI and BRPN
641 3fc6c082 bellard
         * and invalidate all TLBs covered by this BAT
642 3fc6c082 bellard
         */
643 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
644 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
645 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
646 3fc6c082 bellard
#endif
647 3fc6c082 bellard
        mask = (value << 15) & 0x0FFE0000UL;
648 3fc6c082 bellard
        env->DBAT[0][nr] = (value & 0x00001FFFUL) |
649 3fc6c082 bellard
            (value & ~0x0001FFFFUL & ~mask);
650 3fc6c082 bellard
        env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
651 3fc6c082 bellard
            (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
652 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS)
653 3fc6c082 bellard
        do_invalidate_BAT(env, env->DBAT[0][nr], mask);
654 3fc6c082 bellard
#else
655 3fc6c082 bellard
        tlb_flush(env, 1);
656 3fc6c082 bellard
#endif
657 3fc6c082 bellard
    }
658 3fc6c082 bellard
}
659 3fc6c082 bellard
660 3fc6c082 bellard
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
661 3fc6c082 bellard
{
662 3fc6c082 bellard
    dump_store_bat(env, 'D', 1, nr, value);
663 3fc6c082 bellard
    env->DBAT[1][nr] = value;
664 3fc6c082 bellard
}
665 3fc6c082 bellard
666 3fc6c082 bellard
static inline void invalidate_all_tlbs (CPUPPCState *env)
667 3fc6c082 bellard
{
668 3fc6c082 bellard
    /* XXX: this needs to be completed for sotware driven TLB support */
669 3fc6c082 bellard
    tlb_flush(env, 1);
670 3fc6c082 bellard
}
671 3fc6c082 bellard
672 3fc6c082 bellard
/*****************************************************************************/
673 3fc6c082 bellard
/* Special registers manipulation */
674 3fc6c082 bellard
target_ulong do_load_nip (CPUPPCState *env)
675 3fc6c082 bellard
{
676 3fc6c082 bellard
    return env->nip;
677 3fc6c082 bellard
}
678 3fc6c082 bellard
679 3fc6c082 bellard
void do_store_nip (CPUPPCState *env, target_ulong value)
680 3fc6c082 bellard
{
681 3fc6c082 bellard
    env->nip = value;
682 3fc6c082 bellard
}
683 3fc6c082 bellard
684 3fc6c082 bellard
target_ulong do_load_sdr1 (CPUPPCState *env)
685 3fc6c082 bellard
{
686 3fc6c082 bellard
    return env->sdr1;
687 3fc6c082 bellard
}
688 3fc6c082 bellard
689 3fc6c082 bellard
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
690 3fc6c082 bellard
{
691 3fc6c082 bellard
#if defined (DEBUG_MMU)
692 3fc6c082 bellard
    if (loglevel != 0) {
693 3fc6c082 bellard
        fprintf(logfile, "%s: 0x%08lx\n", __func__, (unsigned long)value);
694 3fc6c082 bellard
    }
695 3fc6c082 bellard
#endif
696 3fc6c082 bellard
    if (env->sdr1 != value) {
697 3fc6c082 bellard
        env->sdr1 = value;
698 3fc6c082 bellard
        invalidate_all_tlbs(env);
699 3fc6c082 bellard
    }
700 3fc6c082 bellard
}
701 3fc6c082 bellard
702 3fc6c082 bellard
target_ulong do_load_sr (CPUPPCState *env, int srnum)
703 3fc6c082 bellard
{
704 3fc6c082 bellard
    return env->sr[srnum];
705 3fc6c082 bellard
}
706 3fc6c082 bellard
707 3fc6c082 bellard
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
708 3fc6c082 bellard
{
709 3fc6c082 bellard
#if defined (DEBUG_MMU)
710 3fc6c082 bellard
    if (loglevel != 0) {
711 3fc6c082 bellard
        fprintf(logfile, "%s: reg=%d 0x%08lx %08lx\n",
712 3fc6c082 bellard
                __func__, srnum, (unsigned long)value, env->sr[srnum]);
713 3fc6c082 bellard
    }
714 3fc6c082 bellard
#endif
715 3fc6c082 bellard
    if (env->sr[srnum] != value) {
716 3fc6c082 bellard
        env->sr[srnum] = value;
717 3fc6c082 bellard
#if !defined(FLUSH_ALL_TLBS) && 0
718 3fc6c082 bellard
        {
719 3fc6c082 bellard
            target_ulong page, end;
720 3fc6c082 bellard
            /* Invalidate 256 MB of virtual memory */
721 3fc6c082 bellard
            page = (16 << 20) * srnum;
722 3fc6c082 bellard
            end = page + (16 << 20);
723 3fc6c082 bellard
            for (; page != end; page += TARGET_PAGE_SIZE)
724 3fc6c082 bellard
                tlb_flush_page(env, page);
725 3fc6c082 bellard
        }
726 3fc6c082 bellard
#else
727 3fc6c082 bellard
        invalidate_all_tlbs(env);
728 3fc6c082 bellard
#endif
729 3fc6c082 bellard
    }
730 3fc6c082 bellard
}
731 3fc6c082 bellard
732 3fc6c082 bellard
uint32_t do_load_cr (CPUPPCState *env)
733 3fc6c082 bellard
{
734 3fc6c082 bellard
    return (env->crf[0] << 28) |
735 3fc6c082 bellard
        (env->crf[1] << 24) |
736 3fc6c082 bellard
        (env->crf[2] << 20) |
737 3fc6c082 bellard
        (env->crf[3] << 16) |
738 3fc6c082 bellard
        (env->crf[4] << 12) |
739 3fc6c082 bellard
        (env->crf[5] << 8) |
740 3fc6c082 bellard
        (env->crf[6] << 4) |
741 3fc6c082 bellard
        (env->crf[7] << 0);
742 3fc6c082 bellard
}
743 3fc6c082 bellard
744 3fc6c082 bellard
void do_store_cr (CPUPPCState *env, uint32_t value, uint32_t mask)
745 3fc6c082 bellard
{
746 3fc6c082 bellard
    int i, sh;
747 3fc6c082 bellard
748 3fc6c082 bellard
    for (i = 0, sh = 7; i < 8; i++, sh --) {
749 3fc6c082 bellard
        if (mask & (1 << sh))
750 3fc6c082 bellard
            env->crf[i] = (value >> (sh * 4)) & 0xFUL;
751 3fc6c082 bellard
    }
752 3fc6c082 bellard
}
753 3fc6c082 bellard
754 3fc6c082 bellard
uint32_t do_load_xer (CPUPPCState *env)
755 79aceca5 bellard
{
756 79aceca5 bellard
    return (xer_so << XER_SO) |
757 79aceca5 bellard
        (xer_ov << XER_OV) |
758 79aceca5 bellard
        (xer_ca << XER_CA) |
759 3fc6c082 bellard
        (xer_bc << XER_BC) |
760 3fc6c082 bellard
        (xer_cmp << XER_CMP);
761 79aceca5 bellard
}
762 79aceca5 bellard
763 3fc6c082 bellard
void do_store_xer (CPUPPCState *env, uint32_t value)
764 79aceca5 bellard
{
765 79aceca5 bellard
    xer_so = (value >> XER_SO) & 0x01;
766 79aceca5 bellard
    xer_ov = (value >> XER_OV) & 0x01;
767 79aceca5 bellard
    xer_ca = (value >> XER_CA) & 0x01;
768 3fc6c082 bellard
    xer_cmp = (value >> XER_CMP) & 0xFF;
769 3fc6c082 bellard
    xer_bc = (value >> XER_BC) & 0x3F;
770 79aceca5 bellard
}
771 79aceca5 bellard
772 3fc6c082 bellard
target_ulong do_load_msr (CPUPPCState *env)
773 79aceca5 bellard
{
774 3fc6c082 bellard
    return (msr_vr << MSR_VR)  |
775 3fc6c082 bellard
        (msr_ap  << MSR_AP)  |
776 3fc6c082 bellard
        (msr_sa  << MSR_SA)  |
777 3fc6c082 bellard
        (msr_key << MSR_KEY) |
778 3fc6c082 bellard
        (msr_pow << MSR_POW) |
779 3fc6c082 bellard
        (msr_tlb << MSR_TLB) |
780 79aceca5 bellard
        (msr_ile << MSR_ILE) |
781 79aceca5 bellard
        (msr_ee << MSR_EE) |
782 79aceca5 bellard
        (msr_pr << MSR_PR) |
783 79aceca5 bellard
        (msr_fp << MSR_FP) |
784 79aceca5 bellard
        (msr_me << MSR_ME) |
785 79aceca5 bellard
        (msr_fe0 << MSR_FE0) |
786 79aceca5 bellard
        (msr_se << MSR_SE) |
787 79aceca5 bellard
        (msr_be << MSR_BE) |
788 79aceca5 bellard
        (msr_fe1 << MSR_FE1) |
789 3fc6c082 bellard
        (msr_al  << MSR_AL)  |
790 79aceca5 bellard
        (msr_ip << MSR_IP) |
791 79aceca5 bellard
        (msr_ir << MSR_IR) |
792 79aceca5 bellard
        (msr_dr << MSR_DR) |
793 3fc6c082 bellard
        (msr_pe  << MSR_PE)  |
794 3fc6c082 bellard
        (msr_px  << MSR_PX)  |
795 79aceca5 bellard
        (msr_ri << MSR_RI) |
796 79aceca5 bellard
        (msr_le << MSR_LE);
797 79aceca5 bellard
}
798 79aceca5 bellard
799 3fc6c082 bellard
void do_compute_hflags (CPUPPCState *env)
800 79aceca5 bellard
{
801 3fc6c082 bellard
    /* Compute current hflags */
802 3fc6c082 bellard
    env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) |
803 3fc6c082 bellard
        (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) |
804 3fc6c082 bellard
        (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | 
805 3fc6c082 bellard
        (msr_se << MSR_SE) | (msr_be << MSR_BE);
806 3fc6c082 bellard
}
807 3fc6c082 bellard
808 3fc6c082 bellard
void do_store_msr (CPUPPCState *env, target_ulong value)
809 313adae9 bellard
{
810 50443c98 bellard
    int enter_pm;
811 50443c98 bellard
812 3fc6c082 bellard
    value &= env->msr_mask;
813 3fc6c082 bellard
    if (((value >> MSR_IR) & 1) != msr_ir ||
814 3fc6c082 bellard
        ((value >> MSR_DR) & 1) != msr_dr) {
815 3fc6c082 bellard
        /* Flush all tlb when changing translation mode
816 3fc6c082 bellard
         * When using software driven TLB, we may also need to reload
817 3fc6c082 bellard
         * all defined TLBs
818 3fc6c082 bellard
         */
819 d094807b bellard
        tlb_flush(env, 1);
820 3fc6c082 bellard
        env->interrupt_request |= CPU_INTERRUPT_EXITTB;
821 a541f297 bellard
    }
822 3fc6c082 bellard
#if 0
823 3fc6c082 bellard
    if (loglevel != 0) {
824 3fc6c082 bellard
        fprintf(logfile, "%s: T0 %08lx\n", __func__, value);
825 3fc6c082 bellard
    }
826 3fc6c082 bellard
#endif
827 3fc6c082 bellard
    msr_vr  = (value >> MSR_VR)  & 1;
828 3fc6c082 bellard
    msr_ap  = (value >> MSR_AP)  & 1;
829 3fc6c082 bellard
    msr_sa  = (value >> MSR_SA)  & 1;
830 3fc6c082 bellard
    msr_key = (value >> MSR_KEY) & 1;
831 3fc6c082 bellard
    msr_pow = (value >> MSR_POW) & 1;
832 3fc6c082 bellard
    msr_tlb = (value >> MSR_TLB)  & 1;
833 3fc6c082 bellard
    msr_ile = (value >> MSR_ILE) & 1;
834 3fc6c082 bellard
    msr_ee  = (value >> MSR_EE)  & 1;
835 3fc6c082 bellard
    msr_pr  = (value >> MSR_PR)  & 1;
836 3fc6c082 bellard
    msr_fp  = (value >> MSR_FP)  & 1;
837 3fc6c082 bellard
    msr_me  = (value >> MSR_ME)  & 1;
838 3fc6c082 bellard
    msr_fe0 = (value >> MSR_FE0) & 1;
839 3fc6c082 bellard
    msr_se  = (value >> MSR_SE)  & 1;
840 3fc6c082 bellard
    msr_be  = (value >> MSR_BE)  & 1;
841 3fc6c082 bellard
    msr_fe1 = (value >> MSR_FE1) & 1;
842 3fc6c082 bellard
    msr_al  = (value >> MSR_AL)  & 1;
843 3fc6c082 bellard
    msr_ip  = (value >> MSR_IP)  & 1;
844 3fc6c082 bellard
    msr_ir  = (value >> MSR_IR)  & 1;
845 3fc6c082 bellard
    msr_dr  = (value >> MSR_DR)  & 1;
846 3fc6c082 bellard
    msr_pe  = (value >> MSR_PE)  & 1;
847 3fc6c082 bellard
    msr_px  = (value >> MSR_PX)  & 1;
848 3fc6c082 bellard
    msr_ri  = (value >> MSR_RI)  & 1;
849 3fc6c082 bellard
    msr_le  = (value >> MSR_LE)  & 1;
850 3fc6c082 bellard
    do_compute_hflags(env);
851 50443c98 bellard
852 50443c98 bellard
    enter_pm = 0;
853 50443c98 bellard
    switch (PPC_EXCP(env)) {
854 50443c98 bellard
    case PPC_FLAGS_EXCP_7x0:
855 50443c98 bellard
        if (msr_pow == 1 && (env->spr[SPR_HID0] & 0x00E00000) != 0)
856 50443c98 bellard
            enter_pm = 1;
857 50443c98 bellard
        break;
858 50443c98 bellard
    default:
859 50443c98 bellard
        break;
860 50443c98 bellard
    }
861 50443c98 bellard
    if (enter_pm) {
862 e80e1cc4 bellard
        /* power save: exit cpu loop */
863 50443c98 bellard
        env->halted = 1;
864 e80e1cc4 bellard
        env->exception_index = EXCP_HLT;
865 e80e1cc4 bellard
        cpu_loop_exit();
866 e80e1cc4 bellard
    }
867 3fc6c082 bellard
}
868 3fc6c082 bellard
869 3fc6c082 bellard
float64 do_load_fpscr (CPUPPCState *env)
870 3fc6c082 bellard
{
871 3fc6c082 bellard
    /* The 32 MSB of the target fpr are undefined.
872 3fc6c082 bellard
     * They'll be zero...
873 3fc6c082 bellard
     */
874 3fc6c082 bellard
    union {
875 3fc6c082 bellard
        float64 d;
876 3fc6c082 bellard
        struct {
877 3fc6c082 bellard
            uint32_t u[2];
878 3fc6c082 bellard
        } s;
879 3fc6c082 bellard
    } u;
880 3fc6c082 bellard
    int i;
881 3fc6c082 bellard
882 3fc6c082 bellard
#ifdef WORDS_BIGENDIAN
883 3fc6c082 bellard
#define WORD0 0
884 3fc6c082 bellard
#define WORD1 1
885 3fc6c082 bellard
#else
886 3fc6c082 bellard
#define WORD0 1
887 3fc6c082 bellard
#define WORD1 0
888 4b3686fa bellard
#endif
889 3fc6c082 bellard
    u.s.u[WORD0] = 0;
890 3fc6c082 bellard
    u.s.u[WORD1] = 0;
891 3fc6c082 bellard
    for (i = 0; i < 8; i++)
892 3fc6c082 bellard
        u.s.u[WORD1] |= env->fpscr[i] << (4 * i);
893 3fc6c082 bellard
    return u.d;
894 79aceca5 bellard
}
895 79aceca5 bellard
896 3fc6c082 bellard
void do_store_fpscr (CPUPPCState *env, float64 f, uint32_t mask)
897 3fc6c082 bellard
{
898 3fc6c082 bellard
    /*
899 3fc6c082 bellard
     * We use only the 32 LSB of the incoming fpr
900 3fc6c082 bellard
     */
901 3fc6c082 bellard
    union {
902 3fc6c082 bellard
        double d;
903 3fc6c082 bellard
        struct {
904 3fc6c082 bellard
            uint32_t u[2];
905 3fc6c082 bellard
        } s;
906 3fc6c082 bellard
    } u;
907 3fc6c082 bellard
    int i, rnd_type;
908 3fc6c082 bellard
909 3fc6c082 bellard
    u.d = f;
910 3fc6c082 bellard
    if (mask & 0x80)
911 3fc6c082 bellard
        env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[WORD1] >> 28) & ~0x9);
912 3fc6c082 bellard
    for (i = 1; i < 7; i++) {
913 3fc6c082 bellard
        if (mask & (1 << (7 - i)))
914 3fc6c082 bellard
            env->fpscr[i] = (u.s.u[WORD1] >> (4 * (7 - i))) & 0xF;
915 3fc6c082 bellard
    }
916 3fc6c082 bellard
    /* TODO: update FEX & VX */
917 3fc6c082 bellard
    /* Set rounding mode */
918 3fc6c082 bellard
    switch (env->fpscr[0] & 0x3) {
919 3fc6c082 bellard
    case 0:
920 3fc6c082 bellard
        /* Best approximation (round to nearest) */
921 3fc6c082 bellard
        rnd_type = float_round_nearest_even;
922 3fc6c082 bellard
        break;
923 3fc6c082 bellard
    case 1:
924 3fc6c082 bellard
        /* Smaller magnitude (round toward zero) */
925 3fc6c082 bellard
        rnd_type = float_round_to_zero;
926 3fc6c082 bellard
        break;
927 3fc6c082 bellard
    case 2:
928 3fc6c082 bellard
        /* Round toward +infinite */
929 3fc6c082 bellard
        rnd_type = float_round_up;
930 3fc6c082 bellard
        break;
931 3fc6c082 bellard
    default:
932 3fc6c082 bellard
    case 3:
933 3fc6c082 bellard
        /* Round toward -infinite */
934 3fc6c082 bellard
        rnd_type = float_round_down;
935 3fc6c082 bellard
        break;
936 3fc6c082 bellard
    }
937 3fc6c082 bellard
    set_float_rounding_mode(rnd_type, &env->fp_status);
938 3fc6c082 bellard
}
939 3fc6c082 bellard
940 3fc6c082 bellard
/*****************************************************************************/
941 3fc6c082 bellard
/* Exception processing */
942 18fba28c bellard
#if defined (CONFIG_USER_ONLY)
943 9a64fbe4 bellard
void do_interrupt (CPUState *env)
944 79aceca5 bellard
{
945 18fba28c bellard
    env->exception_index = -1;
946 18fba28c bellard
}
947 9a64fbe4 bellard
#else
948 d094807b bellard
static void dump_syscall(CPUState *env)
949 d094807b bellard
{
950 d094807b bellard
    fprintf(logfile, "syscall r0=0x%08x r3=0x%08x r4=0x%08x r5=0x%08x r6=0x%08x nip=0x%08x\n",
951 d094807b bellard
            env->gpr[0], env->gpr[3], env->gpr[4],
952 d094807b bellard
            env->gpr[5], env->gpr[6], env->nip);
953 d094807b bellard
}
954 d094807b bellard
955 18fba28c bellard
void do_interrupt (CPUState *env)
956 18fba28c bellard
{
957 2be0071f bellard
    target_ulong msr, *srr_0, *srr_1, tmp;
958 18fba28c bellard
    int excp;
959 79aceca5 bellard
960 18fba28c bellard
    excp = env->exception_index;
961 3fc6c082 bellard
    msr = do_load_msr(env);
962 2be0071f bellard
    /* The default is to use SRR0 & SRR1 to save the exception context */
963 2be0071f bellard
    srr_0 = &env->spr[SPR_SRR0];
964 2be0071f bellard
    srr_1 = &env->spr[SPR_SRR1];
965 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
966 2be0071f bellard
    if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
967 2be0071f bellard
        if (loglevel != 0) {
968 2be0071f bellard
            fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
969 2be0071f bellard
                    (unsigned long)env->nip, excp, env->error_code);
970 2be0071f bellard
             cpu_dump_state(env, logfile, fprintf, 0);
971 b769d8fe bellard
        }
972 79aceca5 bellard
    }
973 9a64fbe4 bellard
#endif
974 b769d8fe bellard
    if (loglevel & CPU_LOG_INT) {
975 2be0071f bellard
        fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
976 2be0071f bellard
                (unsigned long)env->nip, excp, env->error_code);
977 b769d8fe bellard
    }
978 2be0071f bellard
    msr_pow = 0;
979 9a64fbe4 bellard
    /* Generate informations in save/restore registers */
980 9a64fbe4 bellard
    switch (excp) {
981 2be0071f bellard
        /* Generic PowerPC exceptions */
982 2be0071f bellard
    case EXCP_RESET: /* 0x0100 */
983 2be0071f bellard
        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) {
984 2be0071f bellard
            if (msr_ip)
985 2be0071f bellard
                excp += 0xFFC00;
986 2be0071f bellard
            excp |= 0xFFC00000;
987 2be0071f bellard
        } else {
988 2be0071f bellard
            srr_0 = &env->spr[SPR_40x_SRR2];
989 2be0071f bellard
            srr_1 = &env->spr[SPR_40x_SRR3];
990 2be0071f bellard
        }
991 9a64fbe4 bellard
        goto store_next;
992 2be0071f bellard
    case EXCP_MACHINE_CHECK: /* 0x0200 */
993 9a64fbe4 bellard
        if (msr_me == 0) {
994 4b3686fa bellard
            cpu_abort(env, "Machine check exception while not allowed\n");
995 79aceca5 bellard
        }
996 2be0071f bellard
        if (PPC_EXCP(env) == PPC_FLAGS_EXCP_40x) {
997 2be0071f bellard
            srr_0 = &env->spr[SPR_40x_SRR2];
998 2be0071f bellard
            srr_1 = &env->spr[SPR_40x_SRR3];
999 2be0071f bellard
        }
1000 9a64fbe4 bellard
        msr_me = 0;
1001 9a64fbe4 bellard
        break;
1002 2be0071f bellard
    case EXCP_DSI: /* 0x0300 */
1003 9a64fbe4 bellard
        /* Store exception cause */
1004 9a64fbe4 bellard
        /* data location address has been stored
1005 9a64fbe4 bellard
         * when the fault has been detected
1006 2be0071f bellard
         */
1007 a541f297 bellard
        msr &= ~0xFFFF0000;
1008 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
1009 a541f297 bellard
        if (loglevel) {
1010 a541f297 bellard
            fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
1011 3fc6c082 bellard
                    env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1012 a541f297 bellard
        } else {
1013 2be0071f bellard
            printf("DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
1014 2be0071f bellard
                   env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1015 a541f297 bellard
        }
1016 a541f297 bellard
#endif
1017 a541f297 bellard
        goto store_next;
1018 2be0071f bellard
    case EXCP_ISI: /* 0x0400 */
1019 9a64fbe4 bellard
        /* Store exception cause */
1020 a541f297 bellard
        msr &= ~0xFFFF0000;
1021 2be0071f bellard
        msr |= env->error_code;
1022 a541f297 bellard
#if defined (DEBUG_EXCEPTIONS)
1023 2be0071f bellard
        if (loglevel != 0) {
1024 a541f297 bellard
            fprintf(logfile, "ISI exception: msr=0x%08x, nip=0x%08x\n",
1025 a541f297 bellard
                    msr, env->nip);
1026 a541f297 bellard
        }
1027 a541f297 bellard
#endif
1028 9a64fbe4 bellard
        goto store_next;
1029 2be0071f bellard
    case EXCP_EXTERNAL: /* 0x0500 */
1030 9a64fbe4 bellard
        if (msr_ee == 0) {
1031 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
1032 9a64fbe4 bellard
            if (loglevel > 0) {
1033 9a64fbe4 bellard
                fprintf(logfile, "Skipping hardware interrupt\n");
1034 2be0071f bellard
            }
1035 9a64fbe4 bellard
#endif
1036 a541f297 bellard
            /* Requeue it */
1037 2be0071f bellard
            env->interrupt_request |= CPU_INTERRUPT_HARD;
1038 9a64fbe4 bellard
            return;
1039 2be0071f bellard
        }
1040 9a64fbe4 bellard
        goto store_next;
1041 2be0071f bellard
    case EXCP_ALIGN: /* 0x0600 */
1042 2be0071f bellard
        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_601) {
1043 2be0071f bellard
            /* Store exception cause */
1044 2be0071f bellard
            /* Get rS/rD and rA from faulting opcode */
1045 2be0071f bellard
            env->spr[SPR_DSISR] |=
1046 2be0071f bellard
                (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1047 2be0071f bellard
            /* data location address has been stored
1048 2be0071f bellard
             * when the fault has been detected
1049 2be0071f bellard
             */
1050 2be0071f bellard
        } else {
1051 2be0071f bellard
            /* IO error exception on PowerPC 601 */
1052 2be0071f bellard
            /* XXX: TODO */
1053 2be0071f bellard
            cpu_abort(env,
1054 2be0071f bellard
                      "601 IO error exception is not implemented yet !\n");
1055 2be0071f bellard
        }
1056 9a64fbe4 bellard
        goto store_current;
1057 2be0071f bellard
    case EXCP_PROGRAM: /* 0x0700 */
1058 9a64fbe4 bellard
        msr &= ~0xFFFF0000;
1059 9a64fbe4 bellard
        switch (env->error_code & ~0xF) {
1060 9a64fbe4 bellard
        case EXCP_FP:
1061 9a64fbe4 bellard
            if (msr_fe0 == 0 && msr_fe1 == 0) {
1062 9a64fbe4 bellard
#if defined (DEBUG_EXCEPTIONS)
1063 9a64fbe4 bellard
                printf("Ignore floating point exception\n");
1064 9a64fbe4 bellard
#endif
1065 9a64fbe4 bellard
                return;
1066 79aceca5 bellard
        }
1067 9a64fbe4 bellard
            msr |= 0x00100000;
1068 9a64fbe4 bellard
            /* Set FX */
1069 9a64fbe4 bellard
            env->fpscr[7] |= 0x8;
1070 9a64fbe4 bellard
            /* Finally, update FEX */
1071 9a64fbe4 bellard
            if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
1072 9a64fbe4 bellard
                ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
1073 9a64fbe4 bellard
                env->fpscr[7] |= 0x4;
1074 9a64fbe4 bellard
        break;
1075 9a64fbe4 bellard
        case EXCP_INVAL:
1076 4b3686fa bellard
            //            printf("Invalid instruction at 0x%08x\n", env->nip);
1077 9a64fbe4 bellard
            msr |= 0x00080000;
1078 9a64fbe4 bellard
        break;
1079 9a64fbe4 bellard
        case EXCP_PRIV:
1080 9a64fbe4 bellard
            msr |= 0x00040000;
1081 9a64fbe4 bellard
        break;
1082 9a64fbe4 bellard
        case EXCP_TRAP:
1083 9a64fbe4 bellard
            msr |= 0x00020000;
1084 9a64fbe4 bellard
            break;
1085 9a64fbe4 bellard
        default:
1086 9a64fbe4 bellard
            /* Should never occur */
1087 9a64fbe4 bellard
        break;
1088 79aceca5 bellard
    }
1089 9a64fbe4 bellard
        msr |= 0x00010000;
1090 9a64fbe4 bellard
        goto store_current;
1091 2be0071f bellard
    case EXCP_NO_FP: /* 0x0800 */
1092 4ecc3190 bellard
        msr &= ~0xFFFF0000;
1093 9a64fbe4 bellard
        goto store_current;
1094 9a64fbe4 bellard
    case EXCP_DECR:
1095 9a64fbe4 bellard
        if (msr_ee == 0) {
1096 2be0071f bellard
#if 1
1097 9a64fbe4 bellard
            /* Requeue it */
1098 2be0071f bellard
            env->interrupt_request |= CPU_INTERRUPT_TIMER;
1099 2be0071f bellard
#endif
1100 9a64fbe4 bellard
            return;
1101 9a64fbe4 bellard
        }
1102 9a64fbe4 bellard
        goto store_next;
1103 2be0071f bellard
    case EXCP_SYSCALL: /* 0x0C00 */
1104 d094807b bellard
        /* NOTE: this is a temporary hack to support graphics OSI
1105 d094807b bellard
           calls from the MOL driver */
1106 d094807b bellard
        if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
1107 d094807b bellard
            env->osi_call) {
1108 d094807b bellard
            if (env->osi_call(env) != 0)
1109 d094807b bellard
                return;
1110 d094807b bellard
        }
1111 b769d8fe bellard
        if (loglevel & CPU_LOG_INT) {
1112 d094807b bellard
            dump_syscall(env);
1113 b769d8fe bellard
        }
1114 9a64fbe4 bellard
        goto store_next;
1115 2be0071f bellard
    case EXCP_TRACE: /* 0x0D00 */
1116 2be0071f bellard
        /* XXX: TODO */
1117 2be0071f bellard
        cpu_abort(env, "Trace exception is not implemented yet !\n");
1118 2be0071f bellard
        goto store_next;
1119 2be0071f bellard
    case EXCP_PERF: /* 0x0F00 */
1120 2be0071f bellard
        /* XXX: TODO */
1121 2be0071f bellard
        cpu_abort(env,
1122 2be0071f bellard
                  "Performance counter exception is not implemented yet !\n");
1123 2be0071f bellard
        goto store_next;
1124 2be0071f bellard
    /* 32 bits PowerPC specific exceptions */
1125 2be0071f bellard
    case EXCP_FP_ASSIST: /* 0x0E00 */
1126 2be0071f bellard
        /* XXX: TODO */
1127 2be0071f bellard
        cpu_abort(env, "Floating point assist exception "
1128 2be0071f bellard
                  "is not implemented yet !\n");
1129 2be0071f bellard
        goto store_next;
1130 2be0071f bellard
    /* 64 bits PowerPC exceptions */
1131 2be0071f bellard
    case EXCP_DSEG: /* 0x0380 */
1132 2be0071f bellard
        /* XXX: TODO */
1133 2be0071f bellard
        cpu_abort(env, "Data segment exception is not implemented yet !\n");
1134 9a64fbe4 bellard
        goto store_next;
1135 2be0071f bellard
    case EXCP_ISEG: /* 0x0480 */
1136 2be0071f bellard
        /* XXX: TODO */
1137 2be0071f bellard
        cpu_abort(env,
1138 2be0071f bellard
                  "Instruction segment exception is not implemented yet !\n");
1139 9a64fbe4 bellard
        goto store_next;
1140 2be0071f bellard
    case EXCP_HDECR: /* 0x0980 */
1141 2be0071f bellard
        if (msr_ee == 0) {
1142 2be0071f bellard
#if 1
1143 2be0071f bellard
            /* Requeue it */
1144 2be0071f bellard
            env->interrupt_request |= CPU_INTERRUPT_TIMER;
1145 2be0071f bellard
#endif
1146 9a64fbe4 bellard
        return;
1147 2be0071f bellard
        }
1148 2be0071f bellard
        cpu_abort(env,
1149 2be0071f bellard
                  "Hypervisor decrementer exception is not implemented yet !\n");
1150 2be0071f bellard
        goto store_next;
1151 2be0071f bellard
    /* Implementation specific exceptions */
1152 2be0071f bellard
    case 0x0A00:
1153 2be0071f bellard
        if (PPC_EXCP(env) != PPC_FLAGS_EXCP_602) {
1154 2be0071f bellard
            /* Critical interrupt on G2 */
1155 2be0071f bellard
            /* XXX: TODO */
1156 2be0071f bellard
            cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
1157 2be0071f bellard
            goto store_next;
1158 2be0071f bellard
        } else {
1159 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x0A00 !\n");
1160 2be0071f bellard
        }
1161 9a64fbe4 bellard
        return;
1162 2be0071f bellard
    case 0x0F20:
1163 2be0071f bellard
        switch (PPC_EXCP(env)) {
1164 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1165 2be0071f bellard
            /* APU unavailable on 405 */
1166 2be0071f bellard
            /* XXX: TODO */
1167 2be0071f bellard
            cpu_abort(env,
1168 2be0071f bellard
                      "APU unavailable exception is not implemented yet !\n");
1169 2be0071f bellard
            goto store_next;
1170 2be0071f bellard
        case PPC_FLAGS_EXCP_74xx:
1171 2be0071f bellard
            /* Altivec unavailable */
1172 2be0071f bellard
            /* XXX: TODO */
1173 2be0071f bellard
            cpu_abort(env, "Altivec unavailable exception "
1174 2be0071f bellard
                      "is not implemented yet !\n");
1175 2be0071f bellard
            goto store_next;
1176 2be0071f bellard
        default:
1177 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x0F20 !\n");
1178 2be0071f bellard
            break;
1179 2be0071f bellard
        }
1180 2be0071f bellard
        return;
1181 2be0071f bellard
    case 0x1000:
1182 2be0071f bellard
        switch (PPC_EXCP(env)) {
1183 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1184 2be0071f bellard
            /* PIT on 4xx */
1185 2be0071f bellard
            /* XXX: TODO */
1186 2be0071f bellard
            cpu_abort(env, "40x PIT exception is not implemented yet !\n");
1187 2be0071f bellard
            goto store_next;
1188 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1189 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1190 2be0071f bellard
            /* ITLBMISS on 602/603 */
1191 2be0071f bellard
            msr &= ~0xF00F0000;
1192 2be0071f bellard
            msr_tgpr = 1;
1193 2be0071f bellard
            goto store_gprs;
1194 2be0071f bellard
        default:
1195 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1000 !\n");
1196 2be0071f bellard
            break;
1197 2be0071f bellard
        }
1198 2be0071f bellard
        return;
1199 2be0071f bellard
    case 0x1010:
1200 2be0071f bellard
        switch (PPC_EXCP(env)) {
1201 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1202 2be0071f bellard
            /* FIT on 4xx */
1203 2be0071f bellard
            cpu_abort(env, "40x FIT exception is not implemented yet !\n");
1204 2be0071f bellard
            /* XXX: TODO */
1205 2be0071f bellard
            goto store_next;
1206 2be0071f bellard
        default:
1207 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1010 !\n");
1208 2be0071f bellard
            break;
1209 2be0071f bellard
        }
1210 2be0071f bellard
        return;
1211 2be0071f bellard
    case 0x1020:
1212 2be0071f bellard
        switch (PPC_EXCP(env)) {
1213 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1214 2be0071f bellard
            /* Watchdog on 4xx */
1215 2be0071f bellard
            /* XXX: TODO */
1216 2be0071f bellard
            cpu_abort(env,
1217 2be0071f bellard
                      "40x watchdog exception is not implemented yet !\n");
1218 2be0071f bellard
            goto store_next;
1219 2be0071f bellard
        default:
1220 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1020 !\n");
1221 2be0071f bellard
            break;
1222 2be0071f bellard
        }
1223 2be0071f bellard
        return;
1224 2be0071f bellard
    case 0x1100:
1225 2be0071f bellard
        switch (PPC_EXCP(env)) {
1226 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1227 2be0071f bellard
            /* DTLBMISS on 4xx */
1228 2be0071f bellard
            /* XXX: TODO */
1229 2be0071f bellard
            cpu_abort(env,
1230 2be0071f bellard
                      "40x DTLBMISS exception is not implemented yet !\n");
1231 2be0071f bellard
            goto store_next;
1232 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1233 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1234 2be0071f bellard
            /* DLTLBMISS on 602/603 */
1235 2be0071f bellard
            msr &= ~0xF00F0000;
1236 2be0071f bellard
            msr_tgpr = 1;
1237 2be0071f bellard
            goto store_gprs;
1238 2be0071f bellard
        default:
1239 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1100 !\n");
1240 2be0071f bellard
            break;
1241 2be0071f bellard
        }
1242 2be0071f bellard
        return;
1243 2be0071f bellard
    case 0x1200:
1244 2be0071f bellard
        switch (PPC_EXCP(env)) {
1245 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1246 2be0071f bellard
            /* ITLBMISS on 4xx */
1247 2be0071f bellard
            /* XXX: TODO */
1248 2be0071f bellard
            cpu_abort(env,
1249 2be0071f bellard
                      "40x ITLBMISS exception is not implemented yet !\n");
1250 2be0071f bellard
            goto store_next;
1251 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1252 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1253 2be0071f bellard
            /* DSTLBMISS on 602/603 */
1254 2be0071f bellard
            msr &= ~0xF00F0000;
1255 2be0071f bellard
            msr_tgpr = 1;
1256 2be0071f bellard
        store_gprs:
1257 2be0071f bellard
#if defined (DEBUG_SOFTWARE_TLB)
1258 2be0071f bellard
            if (loglevel != 0) {
1259 2be0071f bellard
                fprintf(logfile, "6xx %sTLB miss: IM %08x DM %08x IC %08x "
1260 2be0071f bellard
                        "DC %08x H1 %08x H2 %08x %08x\n",
1261 2be0071f bellard
                        excp == 0x1000 ? "I" : excp == 0x1100 ? "DL" : "DS",
1262 2be0071f bellard
                        env->spr[SPR_IMISS], env->spr[SPR_DMISS],
1263 2be0071f bellard
                        env->spr[SPR_ICMP], env->spr[SPR_DCMP],
1264 2be0071f bellard
                        env->spr[SPR_DHASH1], env->spr[SPR_DHASH2],
1265 2be0071f bellard
                        env->error_code);
1266 2be0071f bellard
            }
1267 9a64fbe4 bellard
#endif
1268 2be0071f bellard
            /* Swap temporary saved registers with GPRs */
1269 2be0071f bellard
            tmp = env->gpr[0];
1270 2be0071f bellard
            env->gpr[0] = env->tgpr[0];
1271 2be0071f bellard
            env->tgpr[0] = tmp;
1272 2be0071f bellard
            tmp = env->gpr[1];
1273 2be0071f bellard
            env->gpr[1] = env->tgpr[1];
1274 2be0071f bellard
            env->tgpr[1] = tmp;
1275 2be0071f bellard
            tmp = env->gpr[2];
1276 2be0071f bellard
            env->gpr[2] = env->tgpr[2];
1277 2be0071f bellard
            env->tgpr[2] = tmp;
1278 2be0071f bellard
            tmp = env->gpr[3];
1279 2be0071f bellard
            env->gpr[3] = env->tgpr[3];
1280 2be0071f bellard
            env->tgpr[3] = tmp;
1281 2be0071f bellard
            msr |= env->crf[0] << 28;
1282 2be0071f bellard
            msr |= env->error_code; /* key, D/I, S/L bits */
1283 2be0071f bellard
            /* Set way using a LRU mechanism */
1284 2be0071f bellard
            msr |= (env->last_way ^ 1) << 17;
1285 2be0071f bellard
            goto store_next;
1286 2be0071f bellard
        default:
1287 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1200 !\n");
1288 2be0071f bellard
            break;
1289 2be0071f bellard
        }
1290 2be0071f bellard
        return;
1291 2be0071f bellard
    case 0x1300:
1292 2be0071f bellard
        switch (PPC_EXCP(env)) {
1293 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1294 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1295 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1296 2be0071f bellard
        case PPC_FLAGS_EXCP_604:
1297 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1298 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1299 2be0071f bellard
            /* IABR on 6xx/7xx */
1300 2be0071f bellard
            /* XXX: TODO */
1301 2be0071f bellard
            cpu_abort(env, "IABR exception is not implemented yet !\n");
1302 2be0071f bellard
            goto store_next;
1303 2be0071f bellard
        default:
1304 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1300 !\n");
1305 2be0071f bellard
            break;
1306 2be0071f bellard
        }
1307 2be0071f bellard
        return;
1308 2be0071f bellard
    case 0x1400:
1309 2be0071f bellard
        switch (PPC_EXCP(env)) {
1310 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1311 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1312 2be0071f bellard
        case PPC_FLAGS_EXCP_603:
1313 2be0071f bellard
        case PPC_FLAGS_EXCP_604:
1314 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1315 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1316 2be0071f bellard
            /* SMI on 6xx/7xx */
1317 2be0071f bellard
            /* XXX: TODO */
1318 2be0071f bellard
            cpu_abort(env, "SMI exception is not implemented yet !\n");
1319 2be0071f bellard
            goto store_next;
1320 2be0071f bellard
        default:
1321 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1400 !\n");
1322 2be0071f bellard
            break;
1323 2be0071f bellard
        }
1324 2be0071f bellard
        return;
1325 2be0071f bellard
    case 0x1500:
1326 2be0071f bellard
        switch (PPC_EXCP(env)) {
1327 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1328 2be0071f bellard
            /* Watchdog on 602 */
1329 2be0071f bellard
            cpu_abort(env,
1330 2be0071f bellard
                      "602 watchdog exception is not implemented yet !\n");
1331 2be0071f bellard
            goto store_next;
1332 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1333 2be0071f bellard
            /* Soft patch exception on 970 */
1334 2be0071f bellard
            /* XXX: TODO */
1335 2be0071f bellard
            cpu_abort(env,
1336 2be0071f bellard
                      "970 soft-patch exception is not implemented yet !\n");
1337 2be0071f bellard
            goto store_next;
1338 2be0071f bellard
        case PPC_FLAGS_EXCP_74xx:
1339 2be0071f bellard
            /* VPU assist on 74xx */
1340 2be0071f bellard
            /* XXX: TODO */
1341 2be0071f bellard
            cpu_abort(env, "VPU assist exception is not implemented yet !\n");
1342 2be0071f bellard
            goto store_next;
1343 2be0071f bellard
        default:
1344 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1500 !\n");
1345 2be0071f bellard
            break;
1346 2be0071f bellard
        }
1347 2be0071f bellard
        return;
1348 2be0071f bellard
    case 0x1600:
1349 2be0071f bellard
        switch (PPC_EXCP(env)) {
1350 2be0071f bellard
        case PPC_FLAGS_EXCP_602:
1351 2be0071f bellard
            /* Emulation trap on 602 */
1352 2be0071f bellard
            /* XXX: TODO */
1353 2be0071f bellard
            cpu_abort(env, "602 emulation trap exception "
1354 2be0071f bellard
                      "is not implemented yet !\n");
1355 2be0071f bellard
            goto store_next;
1356 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1357 2be0071f bellard
            /* Maintenance exception on 970 */
1358 2be0071f bellard
            /* XXX: TODO */
1359 2be0071f bellard
            cpu_abort(env,
1360 2be0071f bellard
                      "970 maintenance exception is not implemented yet !\n");
1361 2be0071f bellard
            goto store_next;
1362 2be0071f bellard
        default:
1363 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1600 !\n");
1364 2be0071f bellard
            break;
1365 2be0071f bellard
        }
1366 2be0071f bellard
        return;
1367 2be0071f bellard
    case 0x1700:
1368 2be0071f bellard
        switch (PPC_EXCP(env)) {
1369 2be0071f bellard
        case PPC_FLAGS_EXCP_7x0:
1370 2be0071f bellard
        case PPC_FLAGS_EXCP_7x5:
1371 2be0071f bellard
            /* Thermal management interrupt on G3 */
1372 2be0071f bellard
            /* XXX: TODO */
1373 2be0071f bellard
            cpu_abort(env, "G3 thermal management exception "
1374 2be0071f bellard
                      "is not implemented yet !\n");
1375 2be0071f bellard
            goto store_next;
1376 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1377 2be0071f bellard
            /* VPU assist on 970 */
1378 2be0071f bellard
            /* XXX: TODO */
1379 2be0071f bellard
            cpu_abort(env,
1380 2be0071f bellard
                      "970 VPU assist exception is not implemented yet !\n");
1381 2be0071f bellard
            goto store_next;
1382 2be0071f bellard
        default:
1383 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1700 !\n");
1384 2be0071f bellard
            break;
1385 2be0071f bellard
        }
1386 2be0071f bellard
        return;
1387 2be0071f bellard
    case 0x1800:
1388 2be0071f bellard
        switch (PPC_EXCP(env)) {
1389 2be0071f bellard
        case PPC_FLAGS_EXCP_970:
1390 2be0071f bellard
            /* Thermal exception on 970 */
1391 2be0071f bellard
            /* XXX: TODO */
1392 2be0071f bellard
            cpu_abort(env, "970 thermal management exception "
1393 2be0071f bellard
                      "is not implemented yet !\n");
1394 2be0071f bellard
            goto store_next;
1395 2be0071f bellard
        default:
1396 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1800 !\n");
1397 2be0071f bellard
            break;
1398 2be0071f bellard
        }
1399 2be0071f bellard
        return;
1400 2be0071f bellard
    case 0x2000:
1401 2be0071f bellard
        switch (PPC_EXCP(env)) {
1402 2be0071f bellard
        case PPC_FLAGS_EXCP_40x:
1403 2be0071f bellard
            /* DEBUG on 4xx */
1404 2be0071f bellard
            /* XXX: TODO */
1405 2be0071f bellard
            cpu_abort(env, "40x debug exception is not implemented yet !\n");
1406 2be0071f bellard
            goto store_next;
1407 2be0071f bellard
        case PPC_FLAGS_EXCP_601:
1408 2be0071f bellard
            /* Run mode exception on 601 */
1409 2be0071f bellard
            /* XXX: TODO */
1410 2be0071f bellard
            cpu_abort(env,
1411 2be0071f bellard
                      "601 run mode exception is not implemented yet !\n");
1412 2be0071f bellard
            goto store_next;
1413 2be0071f bellard
        default:
1414 2be0071f bellard
            cpu_abort(env, "Invalid exception 0x1800 !\n");
1415 2be0071f bellard
            break;
1416 2be0071f bellard
        }
1417 2be0071f bellard
        return;
1418 2be0071f bellard
    /* Other exceptions */
1419 2be0071f bellard
    /* Qemu internal exceptions:
1420 2be0071f bellard
     * we should never come here with those values: abort execution
1421 2be0071f bellard
     */
1422 2be0071f bellard
    default:
1423 2be0071f bellard
        cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
1424 9a64fbe4 bellard
        return;
1425 9a64fbe4 bellard
    store_current:
1426 2be0071f bellard
        /* save current instruction location */
1427 2be0071f bellard
        *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL;
1428 9a64fbe4 bellard
        break;
1429 9a64fbe4 bellard
    store_next:
1430 2be0071f bellard
        /* save next instruction location */
1431 2be0071f bellard
        *srr_0 = env->nip & 0xFFFFFFFFULL;
1432 9a64fbe4 bellard
        break;
1433 9a64fbe4 bellard
    }
1434 2be0071f bellard
    /* Save msr */
1435 2be0071f bellard
    *srr_1 = msr;
1436 2be0071f bellard
    /* If we disactivated any translation, flush TLBs */
1437 2be0071f bellard
    if (msr_ir || msr_dr) {
1438 2be0071f bellard
        tlb_flush(env, 1);
1439 2be0071f bellard
    }
1440 9a64fbe4 bellard
    /* reload MSR with correct bits */
1441 9a64fbe4 bellard
    msr_ee = 0;
1442 9a64fbe4 bellard
    msr_pr = 0;
1443 9a64fbe4 bellard
    msr_fp = 0;
1444 9a64fbe4 bellard
    msr_fe0 = 0;
1445 9a64fbe4 bellard
    msr_se = 0;
1446 9a64fbe4 bellard
    msr_be = 0;
1447 9a64fbe4 bellard
    msr_fe1 = 0;
1448 9a64fbe4 bellard
    msr_ir = 0;
1449 9a64fbe4 bellard
    msr_dr = 0;
1450 9a64fbe4 bellard
    msr_ri = 0;
1451 9a64fbe4 bellard
    msr_le = msr_ile;
1452 2be0071f bellard
    msr_sf = msr_isf;
1453 3fc6c082 bellard
    do_compute_hflags(env);
1454 9a64fbe4 bellard
    /* Jump to handler */
1455 2be0071f bellard
    env->nip = excp;
1456 9a64fbe4 bellard
    env->exception_index = EXCP_NONE;
1457 fb0eaffc bellard
}
1458 18fba28c bellard
#endif /* !CONFIG_USER_ONLY */