Statistics
| Branch: | Revision:

root / hw / alpha_palcode.c @ 6049f4f8

History | View | Annotate | Download (25.4 kB)

1 b82945bc j_mayer
/*
2 b82945bc j_mayer
 *  Alpha emulation - PALcode emulation for qemu.
3 5fafdf24 ths
 *
4 b82945bc j_mayer
 *  Copyright (c) 2007 Jocelyn Mayer
5 b82945bc j_mayer
 *
6 b82945bc j_mayer
 * This library is free software; you can redistribute it and/or
7 b82945bc j_mayer
 * modify it under the terms of the GNU Lesser General Public
8 b82945bc j_mayer
 * License as published by the Free Software Foundation; either
9 b82945bc j_mayer
 * version 2 of the License, or (at your option) any later version.
10 b82945bc j_mayer
 *
11 b82945bc j_mayer
 * This library is distributed in the hope that it will be useful,
12 b82945bc j_mayer
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 b82945bc j_mayer
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 b82945bc j_mayer
 * Lesser General Public License for more details.
15 b82945bc j_mayer
 *
16 b82945bc j_mayer
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 b82945bc j_mayer
 */
19 b82945bc j_mayer
20 b82945bc j_mayer
#include <stdint.h>
21 b82945bc j_mayer
#include <stdlib.h>
22 b82945bc j_mayer
#include <stdio.h>
23 b82945bc j_mayer
24 b82945bc j_mayer
#include "cpu.h"
25 b82945bc j_mayer
#include "exec-all.h"
26 b82945bc j_mayer
27 b82945bc j_mayer
/* Shared handlers */
28 b82945bc j_mayer
static void pal_reset (CPUState *env);
29 b82945bc j_mayer
/* Console handlers */
30 b82945bc j_mayer
static void pal_console_call (CPUState *env, uint32_t palcode);
31 b82945bc j_mayer
/* OpenVMS handlers */
32 b82945bc j_mayer
static void pal_openvms_call (CPUState *env, uint32_t palcode);
33 b82945bc j_mayer
/* UNIX / Linux handlers */
34 b82945bc j_mayer
static void pal_unix_call (CPUState *env, uint32_t palcode);
35 b82945bc j_mayer
36 b82945bc j_mayer
pal_handler_t pal_handlers[] = {
37 b82945bc j_mayer
    /* Console handler */
38 b82945bc j_mayer
    {
39 b82945bc j_mayer
        .reset = &pal_reset,
40 b82945bc j_mayer
        .call_pal = &pal_console_call,
41 b82945bc j_mayer
    },
42 b82945bc j_mayer
    /* OpenVMS handler */
43 b82945bc j_mayer
    {
44 b82945bc j_mayer
        .reset = &pal_reset,
45 b82945bc j_mayer
        .call_pal = &pal_openvms_call,
46 b82945bc j_mayer
    },
47 b82945bc j_mayer
    /* UNIX / Linux handler */
48 b82945bc j_mayer
    {
49 b82945bc j_mayer
        .reset = &pal_reset,
50 b82945bc j_mayer
        .call_pal = &pal_unix_call,
51 b82945bc j_mayer
    },
52 b82945bc j_mayer
};
53 b82945bc j_mayer
54 b82945bc j_mayer
#if 0
55 1235fc06 ths
/* One must explicitly check that the TB is valid and the FOE bit is reset */
56 3f47aa8c blueswir1
static void update_itb (void)
57 b82945bc j_mayer
{
58 b82945bc j_mayer
    /* This writes into a temp register, not the actual one */
59 b82945bc j_mayer
    mtpr(TB_TAG);
60 b82945bc j_mayer
    mtpr(TB_CTL);
61 b82945bc j_mayer
    /* This commits the TB update */
62 5fafdf24 ths
    mtpr(ITB_PTE);
63 b82945bc j_mayer
}
64 b82945bc j_mayer

65 3f47aa8c blueswir1
static void update_dtb (void);
66 b82945bc j_mayer
{
67 b82945bc j_mayer
    mtpr(TB_CTL);
68 b82945bc j_mayer
    /* This write into a temp register, not the actual one */
69 b82945bc j_mayer
    mtpr(TB_TAG);
70 b82945bc j_mayer
    /* This commits the TB update */
71 b82945bc j_mayer
    mtpr(DTB_PTE);
72 b82945bc j_mayer
}
73 b82945bc j_mayer
#endif
74 b82945bc j_mayer
75 b82945bc j_mayer
static void pal_reset (CPUState *env)
76 b82945bc j_mayer
{
77 b82945bc j_mayer
}
78 b82945bc j_mayer
79 b82945bc j_mayer
static void do_swappal (CPUState *env, uint64_t palid)
80 b82945bc j_mayer
{
81 b82945bc j_mayer
    pal_handler_t *pal_handler;
82 b82945bc j_mayer
    int status;
83 b82945bc j_mayer
84 b82945bc j_mayer
    status = 0;
85 b82945bc j_mayer
    switch (palid) {
86 b82945bc j_mayer
    case 0 ... 2:
87 b82945bc j_mayer
        pal_handler = &pal_handlers[palid];
88 b82945bc j_mayer
        env->pal_handler = pal_handler;
89 b82945bc j_mayer
        env->ipr[IPR_PAL_BASE] = -1ULL;
90 b82945bc j_mayer
        (*pal_handler->reset)(env);
91 b82945bc j_mayer
        break;
92 b82945bc j_mayer
    case 3 ... 255:
93 b82945bc j_mayer
        /* Unknown identifier */
94 b82945bc j_mayer
        env->ir[0] = 1;
95 b82945bc j_mayer
        return;
96 b82945bc j_mayer
    default:
97 b82945bc j_mayer
        /* We were given the entry point address */
98 b82945bc j_mayer
        env->pal_handler = NULL;
99 b82945bc j_mayer
        env->ipr[IPR_PAL_BASE] = palid;
100 b82945bc j_mayer
        env->pc = env->ipr[IPR_PAL_BASE];
101 b82945bc j_mayer
        cpu_loop_exit();
102 b82945bc j_mayer
    }
103 b82945bc j_mayer
}
104 b82945bc j_mayer
105 b82945bc j_mayer
static void pal_console_call (CPUState *env, uint32_t palcode)
106 b82945bc j_mayer
{
107 b82945bc j_mayer
    uint64_t palid;
108 b82945bc j_mayer
109 b82945bc j_mayer
    if (palcode < 0x00000080) {
110 b82945bc j_mayer
        /* Privileged palcodes */
111 b82945bc j_mayer
        if (!(env->ps >> 3)) {
112 b82945bc j_mayer
            /* TODO: generate privilege exception */
113 b82945bc j_mayer
        }
114 b82945bc j_mayer
    }
115 b82945bc j_mayer
    switch (palcode) {
116 b82945bc j_mayer
    case 0x00000000:
117 b82945bc j_mayer
        /* HALT */
118 b82945bc j_mayer
        /* REQUIRED */
119 b82945bc j_mayer
        break;
120 b82945bc j_mayer
    case 0x00000001:
121 b82945bc j_mayer
        /* CFLUSH */
122 b82945bc j_mayer
        break;
123 b82945bc j_mayer
    case 0x00000002:
124 b82945bc j_mayer
        /* DRAINA */
125 b82945bc j_mayer
        /* REQUIRED */
126 b82945bc j_mayer
        /* Implemented as no-op */
127 b82945bc j_mayer
        break;
128 b82945bc j_mayer
    case 0x00000009:
129 b82945bc j_mayer
        /* CSERVE */
130 b82945bc j_mayer
        /* REQUIRED */
131 b82945bc j_mayer
        break;
132 b82945bc j_mayer
    case 0x0000000A:
133 b82945bc j_mayer
        /* SWPPAL */
134 b82945bc j_mayer
        /* REQUIRED */
135 b82945bc j_mayer
        palid = env->ir[16];
136 b82945bc j_mayer
        do_swappal(env, palid);
137 b82945bc j_mayer
        break;
138 b82945bc j_mayer
    case 0x00000080:
139 b82945bc j_mayer
        /* BPT */
140 b82945bc j_mayer
        /* REQUIRED */
141 b82945bc j_mayer
        break;
142 b82945bc j_mayer
    case 0x00000081:
143 b82945bc j_mayer
        /* BUGCHK */
144 b82945bc j_mayer
        /* REQUIRED */
145 b82945bc j_mayer
        break;
146 b82945bc j_mayer
    case 0x00000086:
147 b82945bc j_mayer
        /* IMB */
148 b82945bc j_mayer
        /* REQUIRED */
149 b82945bc j_mayer
        /* Implemented as no-op */
150 b82945bc j_mayer
        break;
151 b82945bc j_mayer
    case 0x0000009E:
152 b82945bc j_mayer
        /* RDUNIQUE */
153 b82945bc j_mayer
        /* REQUIRED */
154 b82945bc j_mayer
        break;
155 b82945bc j_mayer
    case 0x0000009F:
156 b82945bc j_mayer
        /* WRUNIQUE */
157 b82945bc j_mayer
        /* REQUIRED */
158 b82945bc j_mayer
        break;
159 b82945bc j_mayer
    case 0x000000AA:
160 b82945bc j_mayer
        /* GENTRAP */
161 b82945bc j_mayer
        /* REQUIRED */
162 b82945bc j_mayer
        break;
163 b82945bc j_mayer
    default:
164 b82945bc j_mayer
        break;
165 b82945bc j_mayer
    }
166 b82945bc j_mayer
}
167 b82945bc j_mayer
168 b82945bc j_mayer
static void pal_openvms_call (CPUState *env, uint32_t palcode)
169 b82945bc j_mayer
{
170 b82945bc j_mayer
    uint64_t palid, val, oldval;
171 b82945bc j_mayer
172 b82945bc j_mayer
    if (palcode < 0x00000080) {
173 b82945bc j_mayer
        /* Privileged palcodes */
174 b82945bc j_mayer
        if (!(env->ps >> 3)) {
175 b82945bc j_mayer
            /* TODO: generate privilege exception */
176 b82945bc j_mayer
        }
177 b82945bc j_mayer
    }
178 b82945bc j_mayer
    switch (palcode) {
179 b82945bc j_mayer
    case 0x00000000:
180 b82945bc j_mayer
        /* HALT */
181 b82945bc j_mayer
        /* REQUIRED */
182 b82945bc j_mayer
        break;
183 b82945bc j_mayer
    case 0x00000001:
184 b82945bc j_mayer
        /* CFLUSH */
185 b82945bc j_mayer
        break;
186 b82945bc j_mayer
    case 0x00000002:
187 b82945bc j_mayer
        /* DRAINA */
188 b82945bc j_mayer
        /* REQUIRED */
189 b82945bc j_mayer
        /* Implemented as no-op */
190 b82945bc j_mayer
        break;
191 b82945bc j_mayer
    case 0x00000003:
192 b82945bc j_mayer
        /* LDQP */
193 b82945bc j_mayer
        break;
194 b82945bc j_mayer
    case 0x00000004:
195 b82945bc j_mayer
        /* STQP */
196 b82945bc j_mayer
        break;
197 b82945bc j_mayer
    case 0x00000005:
198 b82945bc j_mayer
        /* SWPCTX */
199 b82945bc j_mayer
        break;
200 b82945bc j_mayer
    case 0x00000006:
201 b82945bc j_mayer
        /* MFPR_ASN */
202 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
203 b82945bc j_mayer
            env->ir[0] = val;
204 b82945bc j_mayer
        break;
205 b82945bc j_mayer
    case 0x00000007:
206 b82945bc j_mayer
        /* MTPR_ASTEN */
207 b82945bc j_mayer
        val = env->ir[16];
208 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
209 b82945bc j_mayer
            env->ir[0] = val;
210 b82945bc j_mayer
        break;
211 b82945bc j_mayer
    case 0x00000008:
212 b82945bc j_mayer
        /* MTPR_ASTSR */
213 b82945bc j_mayer
        val = env->ir[16];
214 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
215 b82945bc j_mayer
            env->ir[0] = val;
216 b82945bc j_mayer
        break;
217 b82945bc j_mayer
    case 0x00000009:
218 b82945bc j_mayer
        /* CSERVE */
219 b82945bc j_mayer
        /* REQUIRED */
220 b82945bc j_mayer
        break;
221 b82945bc j_mayer
    case 0x0000000A:
222 b82945bc j_mayer
        /* SWPPAL */
223 b82945bc j_mayer
        /* REQUIRED */
224 b82945bc j_mayer
        palid = env->ir[16];
225 b82945bc j_mayer
        do_swappal(env, palid);
226 b82945bc j_mayer
        break;
227 b82945bc j_mayer
    case 0x0000000B:
228 b82945bc j_mayer
        /* MFPR_FEN */
229 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
230 b82945bc j_mayer
            env->ir[0] = val;
231 b82945bc j_mayer
        break;
232 b82945bc j_mayer
    case 0x0000000C:
233 b82945bc j_mayer
        /* MTPR_FEN */
234 b82945bc j_mayer
        val = env->ir[16];
235 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
236 b82945bc j_mayer
            env->ir[0] = val;
237 b82945bc j_mayer
        break;
238 b82945bc j_mayer
    case 0x0000000D:
239 b82945bc j_mayer
        /* MTPR_IPIR */
240 b82945bc j_mayer
        val = env->ir[16];
241 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
242 b82945bc j_mayer
            env->ir[0] = val;
243 b82945bc j_mayer
        break;
244 b82945bc j_mayer
    case 0x0000000E:
245 b82945bc j_mayer
        /* MFPR_IPL */
246 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
247 b82945bc j_mayer
            env->ir[0] = val;
248 b82945bc j_mayer
        break;
249 b82945bc j_mayer
    case 0x0000000F:
250 b82945bc j_mayer
        /* MTPR_IPL */
251 b82945bc j_mayer
        val = env->ir[16];
252 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
253 b82945bc j_mayer
            env->ir[0] = val;
254 b82945bc j_mayer
        break;
255 b82945bc j_mayer
    case 0x00000010:
256 b82945bc j_mayer
        /* MFPR_MCES */
257 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
258 b82945bc j_mayer
            env->ir[0] = val;
259 b82945bc j_mayer
        break;
260 b82945bc j_mayer
    case 0x00000011:
261 b82945bc j_mayer
        /* MTPR_MCES */
262 b82945bc j_mayer
        val = env->ir[16];
263 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
264 b82945bc j_mayer
            env->ir[0] = val;
265 b82945bc j_mayer
        break;
266 b82945bc j_mayer
    case 0x00000012:
267 b82945bc j_mayer
        /* MFPR_PCBB */
268 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
269 b82945bc j_mayer
            env->ir[0] = val;
270 b82945bc j_mayer
        break;
271 b82945bc j_mayer
    case 0x00000013:
272 b82945bc j_mayer
        /* MFPR_PRBR */
273 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
274 b82945bc j_mayer
            env->ir[0] = val;
275 b82945bc j_mayer
        break;
276 b82945bc j_mayer
    case 0x00000014:
277 b82945bc j_mayer
        /* MTPR_PRBR */
278 b82945bc j_mayer
        val = env->ir[16];
279 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
280 b82945bc j_mayer
            env->ir[0] = val;
281 b82945bc j_mayer
        break;
282 b82945bc j_mayer
    case 0x00000015:
283 b82945bc j_mayer
        /* MFPR_PTBR */
284 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
285 b82945bc j_mayer
            env->ir[0] = val;
286 b82945bc j_mayer
        break;
287 b82945bc j_mayer
    case 0x00000016:
288 b82945bc j_mayer
        /* MFPR_SCBB */
289 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
290 b82945bc j_mayer
            env->ir[0] = val;
291 b82945bc j_mayer
        break;
292 b82945bc j_mayer
    case 0x00000017:
293 b82945bc j_mayer
        /* MTPR_SCBB */
294 b82945bc j_mayer
        val = env->ir[16];
295 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
296 b82945bc j_mayer
            env->ir[0] = val;
297 b82945bc j_mayer
        break;
298 b82945bc j_mayer
    case 0x00000018:
299 b82945bc j_mayer
        /* MTPR_SIRR */
300 b82945bc j_mayer
        val = env->ir[16];
301 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
302 b82945bc j_mayer
            env->ir[0] = val;
303 b82945bc j_mayer
        break;
304 b82945bc j_mayer
    case 0x00000019:
305 b82945bc j_mayer
        /* MFPR_SISR */
306 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
307 b82945bc j_mayer
            env->ir[0] = val;
308 b82945bc j_mayer
        break;
309 b82945bc j_mayer
    case 0x0000001A:
310 b82945bc j_mayer
        /* MFPR_TBCHK */
311 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
312 b82945bc j_mayer
            env->ir[0] = val;
313 b82945bc j_mayer
        break;
314 b82945bc j_mayer
    case 0x0000001B:
315 b82945bc j_mayer
        /* MTPR_TBIA */
316 b82945bc j_mayer
        val = env->ir[16];
317 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
318 b82945bc j_mayer
            env->ir[0] = val;
319 b82945bc j_mayer
        break;
320 b82945bc j_mayer
    case 0x0000001C:
321 b82945bc j_mayer
        /* MTPR_TBIAP */
322 b82945bc j_mayer
        val = env->ir[16];
323 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
324 b82945bc j_mayer
            env->ir[0] = val;
325 b82945bc j_mayer
        break;
326 b82945bc j_mayer
    case 0x0000001D:
327 b82945bc j_mayer
        /* MTPR_TBIS */
328 b82945bc j_mayer
        val = env->ir[16];
329 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
330 b82945bc j_mayer
            env->ir[0] = val;
331 b82945bc j_mayer
        break;
332 b82945bc j_mayer
    case 0x0000001E:
333 b82945bc j_mayer
        /* MFPR_ESP */
334 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
335 b82945bc j_mayer
            env->ir[0] = val;
336 b82945bc j_mayer
        break;
337 b82945bc j_mayer
    case 0x0000001F:
338 b82945bc j_mayer
        /* MTPR_ESP */
339 b82945bc j_mayer
        val = env->ir[16];
340 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
341 b82945bc j_mayer
            env->ir[0] = val;
342 b82945bc j_mayer
        break;
343 b82945bc j_mayer
    case 0x00000020:
344 b82945bc j_mayer
        /* MFPR_SSP */
345 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
346 b82945bc j_mayer
            env->ir[0] = val;
347 b82945bc j_mayer
        break;
348 b82945bc j_mayer
    case 0x00000021:
349 b82945bc j_mayer
        /* MTPR_SSP */
350 b82945bc j_mayer
        val = env->ir[16];
351 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
352 b82945bc j_mayer
            env->ir[0] = val;
353 b82945bc j_mayer
        break;
354 b82945bc j_mayer
    case 0x00000022:
355 b82945bc j_mayer
        /* MFPR_USP */
356 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
357 b82945bc j_mayer
            env->ir[0] = val;
358 b82945bc j_mayer
        break;
359 b82945bc j_mayer
    case 0x00000023:
360 b82945bc j_mayer
        /* MTPR_USP */
361 b82945bc j_mayer
        val = env->ir[16];
362 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
363 b82945bc j_mayer
            env->ir[0] = val;
364 b82945bc j_mayer
        break;
365 b82945bc j_mayer
    case 0x00000024:
366 b82945bc j_mayer
        /* MTPR_TBISD */
367 b82945bc j_mayer
        val = env->ir[16];
368 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
369 b82945bc j_mayer
            env->ir[0] = val;
370 b82945bc j_mayer
        break;
371 b82945bc j_mayer
    case 0x00000025:
372 b82945bc j_mayer
        /* MTPR_TBISI */
373 b82945bc j_mayer
        val = env->ir[16];
374 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
375 b82945bc j_mayer
            env->ir[0] = val;
376 b82945bc j_mayer
        break;
377 b82945bc j_mayer
    case 0x00000026:
378 b82945bc j_mayer
        /* MFPR_ASTEN */
379 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
380 b82945bc j_mayer
            env->ir[0] = val;
381 b82945bc j_mayer
        break;
382 b82945bc j_mayer
    case 0x00000027:
383 b82945bc j_mayer
        /* MFPR_ASTSR */
384 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
385 b82945bc j_mayer
            env->ir[0] = val;
386 b82945bc j_mayer
        break;
387 b82945bc j_mayer
    case 0x00000029:
388 b82945bc j_mayer
        /* MFPR_VPTB */
389 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
390 b82945bc j_mayer
            env->ir[0] = val;
391 b82945bc j_mayer
        break;
392 b82945bc j_mayer
    case 0x0000002A:
393 b82945bc j_mayer
        /* MTPR_VPTB */
394 b82945bc j_mayer
        val = env->ir[16];
395 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
396 b82945bc j_mayer
            env->ir[0] = val;
397 b82945bc j_mayer
        break;
398 b82945bc j_mayer
    case 0x0000002B:
399 b82945bc j_mayer
        /* MTPR_PERFMON */
400 b82945bc j_mayer
        val = env->ir[16];
401 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
402 b82945bc j_mayer
            env->ir[0] = val;
403 b82945bc j_mayer
        break;
404 b82945bc j_mayer
    case 0x0000002E:
405 b82945bc j_mayer
        /* MTPR_DATFX */
406 b82945bc j_mayer
        val = env->ir[16];
407 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
408 b82945bc j_mayer
            env->ir[0] = val;
409 b82945bc j_mayer
        break;
410 b82945bc j_mayer
    case 0x0000003E:
411 b82945bc j_mayer
        /* WTINT */
412 b82945bc j_mayer
        break;
413 b82945bc j_mayer
    case 0x0000003F:
414 b82945bc j_mayer
        /* MFPR_WHAMI */
415 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
416 b82945bc j_mayer
            env->ir[0] = val;
417 b82945bc j_mayer
        break;
418 b82945bc j_mayer
    case 0x00000080:
419 b82945bc j_mayer
        /* BPT */
420 b82945bc j_mayer
        /* REQUIRED */
421 b82945bc j_mayer
        break;
422 b82945bc j_mayer
    case 0x00000081:
423 b82945bc j_mayer
        /* BUGCHK */
424 b82945bc j_mayer
        /* REQUIRED */
425 b82945bc j_mayer
        break;
426 b82945bc j_mayer
    case 0x00000082:
427 b82945bc j_mayer
        /* CHME */
428 b82945bc j_mayer
        break;
429 b82945bc j_mayer
    case 0x00000083:
430 b82945bc j_mayer
        /* CHMK */
431 b82945bc j_mayer
        break;
432 b82945bc j_mayer
    case 0x00000084:
433 b82945bc j_mayer
        /* CHMS */
434 b82945bc j_mayer
        break;
435 b82945bc j_mayer
    case 0x00000085:
436 b82945bc j_mayer
        /* CHMU */
437 b82945bc j_mayer
        break;
438 b82945bc j_mayer
    case 0x00000086:
439 b82945bc j_mayer
        /* IMB */
440 b82945bc j_mayer
        /* REQUIRED */
441 b82945bc j_mayer
        /* Implemented as no-op */
442 b82945bc j_mayer
        break;
443 b82945bc j_mayer
    case 0x00000087:
444 b82945bc j_mayer
        /* INSQHIL */
445 b82945bc j_mayer
        break;
446 b82945bc j_mayer
    case 0x00000088:
447 b82945bc j_mayer
        /* INSQTIL */
448 b82945bc j_mayer
        break;
449 b82945bc j_mayer
    case 0x00000089:
450 b82945bc j_mayer
        /* INSQHIQ */
451 b82945bc j_mayer
        break;
452 b82945bc j_mayer
    case 0x0000008A:
453 b82945bc j_mayer
        /* INSQTIQ */
454 b82945bc j_mayer
        break;
455 b82945bc j_mayer
    case 0x0000008B:
456 b82945bc j_mayer
        /* INSQUEL */
457 b82945bc j_mayer
        break;
458 b82945bc j_mayer
    case 0x0000008C:
459 b82945bc j_mayer
        /* INSQUEQ */
460 b82945bc j_mayer
        break;
461 b82945bc j_mayer
    case 0x0000008D:
462 b82945bc j_mayer
        /* INSQUEL/D */
463 b82945bc j_mayer
        break;
464 b82945bc j_mayer
    case 0x0000008E:
465 b82945bc j_mayer
        /* INSQUEQ/D */
466 b82945bc j_mayer
        break;
467 b82945bc j_mayer
    case 0x0000008F:
468 b82945bc j_mayer
        /* PROBER */
469 b82945bc j_mayer
        break;
470 b82945bc j_mayer
    case 0x00000090:
471 b82945bc j_mayer
        /* PROBEW */
472 b82945bc j_mayer
        break;
473 b82945bc j_mayer
    case 0x00000091:
474 b82945bc j_mayer
        /* RD_PS */
475 b82945bc j_mayer
        break;
476 b82945bc j_mayer
    case 0x00000092:
477 b82945bc j_mayer
        /* REI */
478 b82945bc j_mayer
        break;
479 b82945bc j_mayer
    case 0x00000093:
480 b82945bc j_mayer
        /* REMQHIL */
481 b82945bc j_mayer
        break;
482 b82945bc j_mayer
    case 0x00000094:
483 b82945bc j_mayer
        /* REMQTIL */
484 b82945bc j_mayer
        break;
485 b82945bc j_mayer
    case 0x00000095:
486 b82945bc j_mayer
        /* REMQHIQ */
487 b82945bc j_mayer
        break;
488 b82945bc j_mayer
    case 0x00000096:
489 b82945bc j_mayer
        /* REMQTIQ */
490 b82945bc j_mayer
        break;
491 b82945bc j_mayer
    case 0x00000097:
492 b82945bc j_mayer
        /* REMQUEL */
493 b82945bc j_mayer
        break;
494 b82945bc j_mayer
    case 0x00000098:
495 b82945bc j_mayer
        /* REMQUEQ */
496 b82945bc j_mayer
        break;
497 b82945bc j_mayer
    case 0x00000099:
498 b82945bc j_mayer
        /* REMQUEL/D */
499 b82945bc j_mayer
        break;
500 b82945bc j_mayer
    case 0x0000009A:
501 b82945bc j_mayer
        /* REMQUEQ/D */
502 b82945bc j_mayer
        break;
503 b82945bc j_mayer
    case 0x0000009B:
504 b82945bc j_mayer
        /* SWASTEN */
505 b82945bc j_mayer
        break;
506 b82945bc j_mayer
    case 0x0000009C:
507 b82945bc j_mayer
        /* WR_PS_SW */
508 b82945bc j_mayer
        break;
509 b82945bc j_mayer
    case 0x0000009D:
510 b82945bc j_mayer
        /* RSCC */
511 b82945bc j_mayer
        break;
512 b82945bc j_mayer
    case 0x0000009E:
513 b82945bc j_mayer
        /* READ_UNQ */
514 b82945bc j_mayer
        /* REQUIRED */
515 b82945bc j_mayer
        break;
516 b82945bc j_mayer
    case 0x0000009F:
517 b82945bc j_mayer
        /* WRITE_UNQ */
518 b82945bc j_mayer
        /* REQUIRED */
519 b82945bc j_mayer
        break;
520 b82945bc j_mayer
    case 0x000000A0:
521 b82945bc j_mayer
        /* AMOVRR */
522 b82945bc j_mayer
        break;
523 b82945bc j_mayer
    case 0x000000A1:
524 b82945bc j_mayer
        /* AMOVRM */
525 b82945bc j_mayer
        break;
526 b82945bc j_mayer
    case 0x000000A2:
527 b82945bc j_mayer
        /* INSQHILR */
528 b82945bc j_mayer
        break;
529 b82945bc j_mayer
    case 0x000000A3:
530 b82945bc j_mayer
        /* INSQTILR */
531 b82945bc j_mayer
        break;
532 b82945bc j_mayer
    case 0x000000A4:
533 b82945bc j_mayer
        /* INSQHIQR */
534 b82945bc j_mayer
        break;
535 b82945bc j_mayer
    case 0x000000A5:
536 b82945bc j_mayer
        /* INSQTIQR */
537 b82945bc j_mayer
        break;
538 b82945bc j_mayer
    case 0x000000A6:
539 b82945bc j_mayer
        /* REMQHILR */
540 b82945bc j_mayer
        break;
541 b82945bc j_mayer
    case 0x000000A7:
542 b82945bc j_mayer
        /* REMQTILR */
543 b82945bc j_mayer
        break;
544 b82945bc j_mayer
    case 0x000000A8:
545 b82945bc j_mayer
        /* REMQHIQR */
546 b82945bc j_mayer
        break;
547 b82945bc j_mayer
    case 0x000000A9:
548 b82945bc j_mayer
        /* REMQTIQR */
549 b82945bc j_mayer
        break;
550 b82945bc j_mayer
    case 0x000000AA:
551 b82945bc j_mayer
        /* GENTRAP */
552 b82945bc j_mayer
        /* REQUIRED */
553 b82945bc j_mayer
        break;
554 b82945bc j_mayer
    case 0x000000AE:
555 b82945bc j_mayer
        /* CLRFEN */
556 b82945bc j_mayer
        break;
557 b82945bc j_mayer
    default:
558 b82945bc j_mayer
        break;
559 b82945bc j_mayer
    }
560 b82945bc j_mayer
}
561 b82945bc j_mayer
562 b82945bc j_mayer
static void pal_unix_call (CPUState *env, uint32_t palcode)
563 b82945bc j_mayer
{
564 b82945bc j_mayer
    uint64_t palid, val, oldval;
565 b82945bc j_mayer
566 b82945bc j_mayer
    if (palcode < 0x00000080) {
567 b82945bc j_mayer
        /* Privileged palcodes */
568 b82945bc j_mayer
        if (!(env->ps >> 3)) {
569 b82945bc j_mayer
            /* TODO: generate privilege exception */
570 b82945bc j_mayer
        }
571 b82945bc j_mayer
    }
572 b82945bc j_mayer
    switch (palcode) {
573 b82945bc j_mayer
    case 0x00000000:
574 b82945bc j_mayer
        /* HALT */
575 b82945bc j_mayer
        /* REQUIRED */
576 b82945bc j_mayer
        break;
577 b82945bc j_mayer
    case 0x00000001:
578 b82945bc j_mayer
        /* CFLUSH */
579 b82945bc j_mayer
        break;
580 b82945bc j_mayer
    case 0x00000002:
581 b82945bc j_mayer
        /* DRAINA */
582 b82945bc j_mayer
        /* REQUIRED */
583 b82945bc j_mayer
        /* Implemented as no-op */
584 b82945bc j_mayer
        break;
585 b82945bc j_mayer
    case 0x00000009:
586 b82945bc j_mayer
        /* CSERVE */
587 b82945bc j_mayer
        /* REQUIRED */
588 b82945bc j_mayer
        break;
589 b82945bc j_mayer
    case 0x0000000A:
590 b82945bc j_mayer
        /* SWPPAL */
591 b82945bc j_mayer
        /* REQUIRED */
592 b82945bc j_mayer
        palid = env->ir[16];
593 b82945bc j_mayer
        do_swappal(env, palid);
594 b82945bc j_mayer
        break;
595 b82945bc j_mayer
    case 0x0000000D:
596 b82945bc j_mayer
        /* WRIPIR */
597 b82945bc j_mayer
        val = env->ir[16];
598 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
599 b82945bc j_mayer
            env->ir[0] = val;
600 b82945bc j_mayer
        break;
601 b82945bc j_mayer
    case 0x00000010:
602 b82945bc j_mayer
        /* RDMCES */
603 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
604 b82945bc j_mayer
            env->ir[0] = val;
605 b82945bc j_mayer
        break;
606 b82945bc j_mayer
    case 0x00000011:
607 b82945bc j_mayer
        /* WRMCES */
608 b82945bc j_mayer
        val = env->ir[16];
609 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
610 b82945bc j_mayer
            env->ir[0] = val;
611 b82945bc j_mayer
        break;
612 b82945bc j_mayer
    case 0x0000002B:
613 b82945bc j_mayer
        /* WRFEN */
614 b82945bc j_mayer
        val = env->ir[16];
615 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
616 b82945bc j_mayer
            env->ir[0] = val;
617 b82945bc j_mayer
        break;
618 b82945bc j_mayer
    case 0x0000002D:
619 b82945bc j_mayer
        /* WRVPTPTR */
620 b82945bc j_mayer
        break;
621 b82945bc j_mayer
    case 0x00000030:
622 b82945bc j_mayer
        /* SWPCTX */
623 b82945bc j_mayer
        break;
624 b82945bc j_mayer
    case 0x00000031:
625 b82945bc j_mayer
        /* WRVAL */
626 b82945bc j_mayer
        break;
627 b82945bc j_mayer
    case 0x00000032:
628 b82945bc j_mayer
        /* RDVAL */
629 b82945bc j_mayer
        break;
630 b82945bc j_mayer
    case 0x00000033:
631 b82945bc j_mayer
        /* TBI */
632 b82945bc j_mayer
        val = env->ir[16];
633 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
634 b82945bc j_mayer
            env->ir[0] = val;
635 b82945bc j_mayer
        break;
636 b82945bc j_mayer
    case 0x00000034:
637 b82945bc j_mayer
        /* WRENT */
638 b82945bc j_mayer
        break;
639 b82945bc j_mayer
    case 0x00000035:
640 b82945bc j_mayer
        /* SWPIPL */
641 b82945bc j_mayer
        break;
642 b82945bc j_mayer
    case 0x00000036:
643 b82945bc j_mayer
        /* RDPS */
644 b82945bc j_mayer
        break;
645 b82945bc j_mayer
    case 0x00000037:
646 b82945bc j_mayer
        /* WRKGP */
647 b82945bc j_mayer
        break;
648 b82945bc j_mayer
    case 0x00000038:
649 b82945bc j_mayer
        /* WRUSP */
650 b82945bc j_mayer
        val = env->ir[16];
651 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
652 b82945bc j_mayer
            env->ir[0] = val;
653 b82945bc j_mayer
        break;
654 b82945bc j_mayer
    case 0x00000039:
655 b82945bc j_mayer
        /* WRPERFMON */
656 b82945bc j_mayer
        val = env->ir[16];
657 b82945bc j_mayer
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
658 b82945bc j_mayer
            env->ir[0] = val;
659 b82945bc j_mayer
        break;
660 b82945bc j_mayer
    case 0x0000003A:
661 b82945bc j_mayer
        /* RDUSP */
662 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
663 b82945bc j_mayer
            env->ir[0] = val;
664 b82945bc j_mayer
        break;
665 b82945bc j_mayer
    case 0x0000003C:
666 b82945bc j_mayer
        /* WHAMI */
667 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
668 b82945bc j_mayer
            env->ir[0] = val;
669 b82945bc j_mayer
        break;
670 b82945bc j_mayer
    case 0x0000003D:
671 b82945bc j_mayer
        /* RETSYS */
672 b82945bc j_mayer
        break;
673 b82945bc j_mayer
    case 0x0000003E:
674 b82945bc j_mayer
        /* WTINT */
675 b82945bc j_mayer
        break;
676 b82945bc j_mayer
    case 0x0000003F:
677 b82945bc j_mayer
        /* RTI */
678 b82945bc j_mayer
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
679 b82945bc j_mayer
            env->ir[0] = val;
680 b82945bc j_mayer
        break;
681 b82945bc j_mayer
    case 0x00000080:
682 b82945bc j_mayer
        /* BPT */
683 b82945bc j_mayer
        /* REQUIRED */
684 b82945bc j_mayer
        break;
685 b82945bc j_mayer
    case 0x00000081:
686 b82945bc j_mayer
        /* BUGCHK */
687 b82945bc j_mayer
        /* REQUIRED */
688 b82945bc j_mayer
        break;
689 b82945bc j_mayer
    case 0x00000083:
690 b82945bc j_mayer
        /* CALLSYS */
691 b82945bc j_mayer
        break;
692 b82945bc j_mayer
    case 0x00000086:
693 b82945bc j_mayer
        /* IMB */
694 b82945bc j_mayer
        /* REQUIRED */
695 b82945bc j_mayer
        /* Implemented as no-op */
696 b82945bc j_mayer
        break;
697 b82945bc j_mayer
    case 0x00000092:
698 b82945bc j_mayer
        /* URTI */
699 b82945bc j_mayer
        break;
700 b82945bc j_mayer
    case 0x0000009E:
701 b82945bc j_mayer
        /* RDUNIQUE */
702 b82945bc j_mayer
        /* REQUIRED */
703 b82945bc j_mayer
        break;
704 b82945bc j_mayer
    case 0x0000009F:
705 b82945bc j_mayer
        /* WRUNIQUE */
706 b82945bc j_mayer
        /* REQUIRED */
707 b82945bc j_mayer
        break;
708 b82945bc j_mayer
    case 0x000000AA:
709 b82945bc j_mayer
        /* GENTRAP */
710 b82945bc j_mayer
        /* REQUIRED */
711 b82945bc j_mayer
        break;
712 b82945bc j_mayer
    case 0x000000AE:
713 b82945bc j_mayer
        /* CLRFEN */
714 b82945bc j_mayer
        break;
715 b82945bc j_mayer
    default:
716 b82945bc j_mayer
        break;
717 b82945bc j_mayer
    }
718 b82945bc j_mayer
}
719 b82945bc j_mayer
720 b82945bc j_mayer
void call_pal (CPUState *env)
721 b82945bc j_mayer
{
722 b82945bc j_mayer
    pal_handler_t *pal_handler = env->pal_handler;
723 b82945bc j_mayer
724 b82945bc j_mayer
    switch (env->exception_index) {
725 b82945bc j_mayer
    case EXCP_RESET:
726 b82945bc j_mayer
        (*pal_handler->reset)(env);
727 b82945bc j_mayer
        break;
728 b82945bc j_mayer
    case EXCP_MCHK:
729 b82945bc j_mayer
        (*pal_handler->machine_check)(env);
730 b82945bc j_mayer
        break;
731 b82945bc j_mayer
    case EXCP_ARITH:
732 b82945bc j_mayer
        (*pal_handler->arithmetic)(env);
733 b82945bc j_mayer
        break;
734 b82945bc j_mayer
    case EXCP_INTERRUPT:
735 b82945bc j_mayer
        (*pal_handler->interrupt)(env);
736 b82945bc j_mayer
        break;
737 b82945bc j_mayer
    case EXCP_DFAULT:
738 b82945bc j_mayer
        (*pal_handler->dfault)(env);
739 b82945bc j_mayer
        break;
740 b82945bc j_mayer
    case EXCP_DTB_MISS_PAL:
741 b82945bc j_mayer
        (*pal_handler->dtb_miss_pal)(env);
742 b82945bc j_mayer
        break;
743 b82945bc j_mayer
    case EXCP_DTB_MISS_NATIVE:
744 b82945bc j_mayer
        (*pal_handler->dtb_miss_native)(env);
745 b82945bc j_mayer
        break;
746 b82945bc j_mayer
    case EXCP_UNALIGN:
747 b82945bc j_mayer
        (*pal_handler->unalign)(env);
748 b82945bc j_mayer
        break;
749 b82945bc j_mayer
    case EXCP_ITB_MISS:
750 b82945bc j_mayer
        (*pal_handler->itb_miss)(env);
751 b82945bc j_mayer
        break;
752 b82945bc j_mayer
    case EXCP_ITB_ACV:
753 b82945bc j_mayer
        (*pal_handler->itb_acv)(env);
754 b82945bc j_mayer
        break;
755 b82945bc j_mayer
    case EXCP_OPCDEC:
756 b82945bc j_mayer
        (*pal_handler->opcdec)(env);
757 b82945bc j_mayer
        break;
758 b82945bc j_mayer
    case EXCP_FEN:
759 b82945bc j_mayer
        (*pal_handler->fen)(env);
760 b82945bc j_mayer
        break;
761 b82945bc j_mayer
    default:
762 b82945bc j_mayer
        if (env->exception_index >= EXCP_CALL_PAL &&
763 b82945bc j_mayer
            env->exception_index < EXCP_CALL_PALP) {
764 b82945bc j_mayer
            /* Unprivileged PAL call */
765 b82945bc j_mayer
            (*pal_handler->call_pal)
766 b82945bc j_mayer
                (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
767 b82945bc j_mayer
        } else if (env->exception_index >= EXCP_CALL_PALP &&
768 b82945bc j_mayer
                   env->exception_index < EXCP_CALL_PALE) {
769 b82945bc j_mayer
            /* Privileged PAL call */
770 b82945bc j_mayer
            (*pal_handler->call_pal)
771 b82945bc j_mayer
                (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
772 b82945bc j_mayer
        } else {
773 b82945bc j_mayer
            /* Should never happen */
774 b82945bc j_mayer
        }
775 b82945bc j_mayer
        break;
776 b82945bc j_mayer
    }
777 b82945bc j_mayer
    env->ipr[IPR_EXC_ADDR] &= ~1;
778 b82945bc j_mayer
}
779 b82945bc j_mayer
780 b82945bc j_mayer
void pal_init (CPUState *env)
781 b82945bc j_mayer
{
782 b82945bc j_mayer
    do_swappal(env, 0);
783 b82945bc j_mayer
}
784 b82945bc j_mayer
785 b82945bc j_mayer
#if 0
786 b82945bc j_mayer
static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
787 b82945bc j_mayer
{
788 b82945bc j_mayer
    uint64_t virbnd, ptbr;
789 b82945bc j_mayer

790 b82945bc j_mayer
    if ((env->features & FEATURE_VIRBND)) {
791 b82945bc j_mayer
        cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
792 b82945bc j_mayer
        if (vaddr >= virbnd)
793 b82945bc j_mayer
            cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
794 b82945bc j_mayer
        else
795 b82945bc j_mayer
            cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
796 b82945bc j_mayer
    } else {
797 b82945bc j_mayer
        cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
798 b82945bc j_mayer
    }
799 b82945bc j_mayer

800 b82945bc j_mayer
    return ptbr;
801 b82945bc j_mayer
}
802 b82945bc j_mayer

803 b82945bc j_mayer
static int get_page_bits (CPUState *env)
804 b82945bc j_mayer
{
805 b82945bc j_mayer
    /* XXX */
806 b82945bc j_mayer
    return 13;
807 b82945bc j_mayer
}
808 b82945bc j_mayer

809 b82945bc j_mayer
static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
810 b82945bc j_mayer
                    uint64_t ptebase, int page_bits, uint64_t level,
811 6ebbf390 j_mayer
                    int mmu_idx, int rw)
812 b82945bc j_mayer
{
813 b82945bc j_mayer
    uint64_t pteaddr, pte, pfn;
814 b82945bc j_mayer
    uint8_t gh;
815 6ebbf390 j_mayer
    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
816 b82945bc j_mayer

817 6ebbf390 j_mayer
    /* XXX: TOFIX */
818 6ebbf390 j_mayer
    is_user = mmu_idx == MMU_USER_IDX;
819 b82945bc j_mayer
    pteaddr = (ptebase << page_bits) + (8 * level);
820 b82945bc j_mayer
    pte = ldq_raw(pteaddr);
821 b82945bc j_mayer
    /* Decode all interresting PTE fields */
822 b82945bc j_mayer
    pfn = pte >> 32;
823 b82945bc j_mayer
    uwe = (pte >> 13) & 1;
824 b82945bc j_mayer
    kwe = (pte >> 12) & 1;
825 b82945bc j_mayer
    ure = (pte >> 9) & 1;
826 b82945bc j_mayer
    kre = (pte >> 8) & 1;
827 b82945bc j_mayer
    gh = (pte >> 5) & 3;
828 b82945bc j_mayer
    foE = (pte >> 3) & 1;
829 b82945bc j_mayer
    foW = (pte >> 2) & 1;
830 b82945bc j_mayer
    foR = (pte >> 1) & 1;
831 b82945bc j_mayer
    v = pte & 1;
832 b82945bc j_mayer
    ret = 0;
833 b82945bc j_mayer
    if (!v)
834 b82945bc j_mayer
        ret = 0x1;
835 b82945bc j_mayer
    /* Check access rights */
836 b82945bc j_mayer
    ar = 0;
837 b82945bc j_mayer
    if (is_user) {
838 b82945bc j_mayer
        if (ure)
839 b82945bc j_mayer
            ar |= PAGE_READ;
840 b82945bc j_mayer
        if (uwe)
841 b82945bc j_mayer
            ar |= PAGE_WRITE;
842 b82945bc j_mayer
        if (rw == 1 && !uwe)
843 b82945bc j_mayer
            ret |= 0x2;
844 b82945bc j_mayer
        if (rw != 1 && !ure)
845 b82945bc j_mayer
            ret |= 0x2;
846 b82945bc j_mayer
    } else {
847 b82945bc j_mayer
        if (kre)
848 b82945bc j_mayer
            ar |= PAGE_READ;
849 b82945bc j_mayer
        if (kwe)
850 b82945bc j_mayer
            ar |= PAGE_WRITE;
851 b82945bc j_mayer
        if (rw == 1 && !kwe)
852 b82945bc j_mayer
            ret |= 0x2;
853 b82945bc j_mayer
        if (rw != 1 && !kre)
854 b82945bc j_mayer
            ret |= 0x2;
855 b82945bc j_mayer
    }
856 b82945bc j_mayer
    if (rw == 0 && foR)
857 b82945bc j_mayer
        ret |= 0x4;
858 b82945bc j_mayer
    if (rw == 2 && foE)
859 b82945bc j_mayer
        ret |= 0x8;
860 b82945bc j_mayer
    if (rw == 1 && foW)
861 b82945bc j_mayer
        ret |= 0xC;
862 b82945bc j_mayer
    *pfnp = pfn;
863 b82945bc j_mayer
    if (zbitsp != NULL)
864 b82945bc j_mayer
        *zbitsp = page_bits + (3 * gh);
865 b82945bc j_mayer
    if (protp != NULL)
866 b82945bc j_mayer
        *protp = ar;
867 b82945bc j_mayer

868 b82945bc j_mayer
    return ret;
869 b82945bc j_mayer
}
870 b82945bc j_mayer

871 b82945bc j_mayer
static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
872 b82945bc j_mayer
                           uint64_t ptebase, int page_bits,
873 6ebbf390 j_mayer
                           uint64_t vaddr, int mmu_idx, int rw)
874 b82945bc j_mayer
{
875 b82945bc j_mayer
    uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
876 b82945bc j_mayer
    int lvl_bits, ret;
877 b82945bc j_mayer

878 b82945bc j_mayer
    page_mask = (1ULL << page_bits) - 1ULL;
879 b82945bc j_mayer
    lvl_bits = page_bits - 3;
880 b82945bc j_mayer
    lvl_mask = (1ULL << lvl_bits) - 1ULL;
881 b82945bc j_mayer
    level3 = (vaddr >> page_bits) & lvl_mask;
882 b82945bc j_mayer
    level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
883 b82945bc j_mayer
    level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
884 b82945bc j_mayer
    /* Level 1 PTE */
885 b82945bc j_mayer
    ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
886 b82945bc j_mayer
    switch (ret) {
887 b82945bc j_mayer
    case 3:
888 b82945bc j_mayer
        /* Access violation */
889 b82945bc j_mayer
        return 2;
890 b82945bc j_mayer
    case 2:
891 b82945bc j_mayer
        /* translation not valid */
892 b82945bc j_mayer
        return 1;
893 b82945bc j_mayer
    default:
894 b82945bc j_mayer
        /* OK */
895 b82945bc j_mayer
        break;
896 b82945bc j_mayer
    }
897 b82945bc j_mayer
    /* Level 2 PTE */
898 b82945bc j_mayer
    ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
899 b82945bc j_mayer
    switch (ret) {
900 b82945bc j_mayer
    case 3:
901 b82945bc j_mayer
        /* Access violation */
902 b82945bc j_mayer
        return 2;
903 b82945bc j_mayer
    case 2:
904 b82945bc j_mayer
        /* translation not valid */
905 b82945bc j_mayer
        return 1;
906 b82945bc j_mayer
    default:
907 b82945bc j_mayer
        /* OK */
908 b82945bc j_mayer
        break;
909 b82945bc j_mayer
    }
910 b82945bc j_mayer
    /* Level 3 PTE */
911 6ebbf390 j_mayer
    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
912 b82945bc j_mayer
    if (ret & 0x1) {
913 b82945bc j_mayer
        /* Translation not valid */
914 b82945bc j_mayer
        ret = 1;
915 b82945bc j_mayer
    } else if (ret & 2) {
916 b82945bc j_mayer
        /* Access violation */
917 b82945bc j_mayer
        ret = 2;
918 b82945bc j_mayer
    } else {
919 b82945bc j_mayer
        switch (ret & 0xC) {
920 b82945bc j_mayer
        case 0:
921 b82945bc j_mayer
            /* OK */
922 b82945bc j_mayer
            ret = 0;
923 b82945bc j_mayer
            break;
924 b82945bc j_mayer
        case 0x4:
925 b82945bc j_mayer
            /* Fault on read */
926 b82945bc j_mayer
            ret = 3;
927 b82945bc j_mayer
            break;
928 b82945bc j_mayer
        case 0x8:
929 b82945bc j_mayer
            /* Fault on execute */
930 b82945bc j_mayer
            ret = 4;
931 b82945bc j_mayer
            break;
932 b82945bc j_mayer
        case 0xC:
933 b82945bc j_mayer
            /* Fault on write */
934 b82945bc j_mayer
            ret = 5;
935 b82945bc j_mayer
            break;
936 b82945bc j_mayer
        }
937 b82945bc j_mayer
    }
938 b82945bc j_mayer
    *paddr = (pfn << page_bits) | (vaddr & page_mask);
939 3b46e624 ths

940 b82945bc j_mayer
    return 0;
941 b82945bc j_mayer
}
942 b82945bc j_mayer

943 b82945bc j_mayer
static int virtual_to_physical (CPUState *env, uint64_t *physp,
944 b82945bc j_mayer
                                int *zbitsp, int *protp,
945 6ebbf390 j_mayer
                                uint64_t virtual, int mmu_idx, int rw)
946 b82945bc j_mayer
{
947 b82945bc j_mayer
    uint64_t sva, ptebase;
948 b82945bc j_mayer
    int seg, page_bits, ret;
949 b82945bc j_mayer

950 b82945bc j_mayer
    sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
951 b82945bc j_mayer
    if (sva != virtual)
952 b82945bc j_mayer
        seg = -1;
953 b82945bc j_mayer
    else
954 b82945bc j_mayer
        seg = sva >> (VA_BITS - 2);
955 b82945bc j_mayer
    virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
956 b82945bc j_mayer
    ptebase = get_ptebase(env, virtual);
957 b82945bc j_mayer
    page_bits = get_page_bits(env);
958 b82945bc j_mayer
    ret = 0;
959 b82945bc j_mayer
    switch (seg) {
960 b82945bc j_mayer
    case 0:
961 b82945bc j_mayer
        /* seg1: 3 levels of PTE */
962 b82945bc j_mayer
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
963 6ebbf390 j_mayer
                             virtual, mmu_idx, rw);
964 b82945bc j_mayer
        break;
965 b82945bc j_mayer
    case 1:
966 b82945bc j_mayer
        /* seg1: 2 levels of PTE */
967 b82945bc j_mayer
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
968 6ebbf390 j_mayer
                             virtual, mmu_idx, rw);
969 b82945bc j_mayer
        break;
970 b82945bc j_mayer
    case 2:
971 b82945bc j_mayer
        /* kernel segment */
972 6ebbf390 j_mayer
        if (mmu_idx != 0) {
973 b82945bc j_mayer
            ret = 2;
974 b82945bc j_mayer
        } else {
975 b82945bc j_mayer
            *physp = virtual;
976 b82945bc j_mayer
        }
977 b82945bc j_mayer
        break;
978 b82945bc j_mayer
    case 3:
979 b82945bc j_mayer
        /* seg1: TB mapped */
980 b82945bc j_mayer
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
981 6ebbf390 j_mayer
                             virtual, mmu_idx, rw);
982 b82945bc j_mayer
        break;
983 b82945bc j_mayer
    default:
984 b82945bc j_mayer
        ret = 1;
985 b82945bc j_mayer
        break;
986 b82945bc j_mayer
    }
987 b82945bc j_mayer

988 b82945bc j_mayer
    return ret;
989 b82945bc j_mayer
}
990 b82945bc j_mayer

991 b82945bc j_mayer
/* XXX: code provision */
992 b82945bc j_mayer
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
993 6ebbf390 j_mayer
                              int mmu_idx, int is_softmmu)
994 b82945bc j_mayer
{
995 b82945bc j_mayer
    uint64_t physical, page_size, end;
996 b82945bc j_mayer
    int prot, zbits, ret;
997 b82945bc j_mayer

998 6049f4f8 Richard Henderson
    ret = virtual_to_physical(env, &physical, &zbits, &prot,
999 6049f4f8 Richard Henderson
                              address, mmu_idx, rw);
1000 6049f4f8 Richard Henderson

1001 b82945bc j_mayer
    switch (ret) {
1002 b82945bc j_mayer
    case 0:
1003 b82945bc j_mayer
        /* No fault */
1004 b82945bc j_mayer
        page_size = 1ULL << zbits;
1005 b82945bc j_mayer
        address &= ~(page_size - 1);
1006 b82945bc j_mayer
        for (end = physical + page_size; physical < end; physical += 0x1000) {
1007 b82945bc j_mayer
            ret = tlb_set_page(env, address, physical, prot,
1008 6ebbf390 j_mayer
                               mmu_idx, is_softmmu);
1009 b82945bc j_mayer
            address += 0x1000;
1010 b82945bc j_mayer
        }
1011 b82945bc j_mayer
        break;
1012 b82945bc j_mayer
#if 0
1013 b82945bc j_mayer
    case 1:
1014 b82945bc j_mayer
        env->exception_index = EXCP_DFAULT;
1015 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1016 b82945bc j_mayer
        ret = 1;
1017 b82945bc j_mayer
        break;
1018 b82945bc j_mayer
    case 2:
1019 b82945bc j_mayer
        env->exception_index = EXCP_ACCESS_VIOLATION;
1020 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1021 b82945bc j_mayer
        ret = 1;
1022 b82945bc j_mayer
        break;
1023 b82945bc j_mayer
    case 3:
1024 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_READ;
1025 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1026 b82945bc j_mayer
        ret = 1;
1027 b82945bc j_mayer
        break;
1028 b82945bc j_mayer
    case 4:
1029 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_EXECUTE;
1030 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1031 b82945bc j_mayer
        ret = 1;
1032 b82945bc j_mayer
    case 5:
1033 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_WRITE;
1034 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1035 b82945bc j_mayer
        ret = 1;
1036 b82945bc j_mayer
#endif
1037 b82945bc j_mayer
    default:
1038 b82945bc j_mayer
        /* Should never happen */
1039 b82945bc j_mayer
        env->exception_index = EXCP_MCHK;
1040 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1041 b82945bc j_mayer
        ret = 1;
1042 b82945bc j_mayer
        break;
1043 b82945bc j_mayer
    }
1044 b82945bc j_mayer
1045 b82945bc j_mayer
    return ret;
1046 b82945bc j_mayer
}
1047 b82945bc j_mayer
#endif