Statistics
| Branch: | Revision:

root / hw / alpha_palcode.c @ 1b4e8f73

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

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

798 b82945bc j_mayer
    return ptbr;
799 b82945bc j_mayer
}
800 b82945bc j_mayer

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

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

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

866 b82945bc j_mayer
    return ret;
867 b82945bc j_mayer
}
868 b82945bc j_mayer

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

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

938 b82945bc j_mayer
    return 0;
939 b82945bc j_mayer
}
940 b82945bc j_mayer

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

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

986 b82945bc j_mayer
    return ret;
987 b82945bc j_mayer
}
988 b82945bc j_mayer

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

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

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