Statistics
| Branch: | Revision:

root / hw / alpha_palcode.c @ f3519986

History | View | Annotate | Download (26.7 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 "qemu.h"
25 b82945bc j_mayer
#include "cpu.h"
26 b82945bc j_mayer
#include "exec-all.h"
27 b82945bc j_mayer
28 b82945bc j_mayer
#if !defined (CONFIG_USER_ONLY)
29 b82945bc j_mayer
/* Shared handlers */
30 b82945bc j_mayer
static void pal_reset (CPUState *env);
31 b82945bc j_mayer
/* Console handlers */
32 b82945bc j_mayer
static void pal_console_call (CPUState *env, uint32_t palcode);
33 b82945bc j_mayer
/* OpenVMS handlers */
34 b82945bc j_mayer
static void pal_openvms_call (CPUState *env, uint32_t palcode);
35 b82945bc j_mayer
/* UNIX / Linux handlers */
36 b82945bc j_mayer
static void pal_unix_call (CPUState *env, uint32_t palcode);
37 b82945bc j_mayer
38 b82945bc j_mayer
pal_handler_t pal_handlers[] = {
39 b82945bc j_mayer
    /* Console handler */
40 b82945bc j_mayer
    {
41 b82945bc j_mayer
        .reset = &pal_reset,
42 b82945bc j_mayer
        .call_pal = &pal_console_call,
43 b82945bc j_mayer
    },
44 b82945bc j_mayer
    /* OpenVMS handler */
45 b82945bc j_mayer
    {
46 b82945bc j_mayer
        .reset = &pal_reset,
47 b82945bc j_mayer
        .call_pal = &pal_openvms_call,
48 b82945bc j_mayer
    },
49 b82945bc j_mayer
    /* UNIX / Linux handler */
50 b82945bc j_mayer
    {
51 b82945bc j_mayer
        .reset = &pal_reset,
52 b82945bc j_mayer
        .call_pal = &pal_unix_call,
53 b82945bc j_mayer
    },
54 b82945bc j_mayer
};
55 b82945bc j_mayer
56 b82945bc j_mayer
#if 0
57 1235fc06 ths
/* One must explicitly check that the TB is valid and the FOE bit is reset */
58 3f47aa8c blueswir1
static void update_itb (void)
59 b82945bc j_mayer
{
60 b82945bc j_mayer
    /* This writes into a temp register, not the actual one */
61 b82945bc j_mayer
    mtpr(TB_TAG);
62 b82945bc j_mayer
    mtpr(TB_CTL);
63 b82945bc j_mayer
    /* This commits the TB update */
64 5fafdf24 ths
    mtpr(ITB_PTE);
65 b82945bc j_mayer
}
66 b82945bc j_mayer

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

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

802 b82945bc j_mayer
    return ptbr;
803 b82945bc j_mayer
}
804 b82945bc j_mayer

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

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

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

870 b82945bc j_mayer
    return ret;
871 b82945bc j_mayer
}
872 b82945bc j_mayer

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

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

942 b82945bc j_mayer
    return 0;
943 b82945bc j_mayer
}
944 b82945bc j_mayer

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

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

990 b82945bc j_mayer
    return ret;
991 b82945bc j_mayer
}
992 b82945bc j_mayer

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

1000 f48c144e aurel32
#if defined(CONFIG_USER_ONLY)
1001 b82945bc j_mayer
        ret = 2;
1002 f48c144e aurel32
#else
1003 b82945bc j_mayer
        ret = virtual_to_physical(env, &physical, &zbits, &prot,
1004 6ebbf390 j_mayer
                                  address, mmu_idx, rw);
1005 f48c144e aurel32
#endif
1006 b82945bc j_mayer
    switch (ret) {
1007 b82945bc j_mayer
    case 0:
1008 b82945bc j_mayer
        /* No fault */
1009 b82945bc j_mayer
        page_size = 1ULL << zbits;
1010 b82945bc j_mayer
        address &= ~(page_size - 1);
1011 b82945bc j_mayer
        for (end = physical + page_size; physical < end; physical += 0x1000) {
1012 b82945bc j_mayer
            ret = tlb_set_page(env, address, physical, prot,
1013 6ebbf390 j_mayer
                               mmu_idx, is_softmmu);
1014 b82945bc j_mayer
            address += 0x1000;
1015 b82945bc j_mayer
        }
1016 b82945bc j_mayer
        break;
1017 b82945bc j_mayer
#if 0
1018 b82945bc j_mayer
    case 1:
1019 b82945bc j_mayer
        env->exception_index = EXCP_DFAULT;
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 2:
1024 b82945bc j_mayer
        env->exception_index = EXCP_ACCESS_VIOLATION;
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 3:
1029 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_READ;
1030 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1031 b82945bc j_mayer
        ret = 1;
1032 b82945bc j_mayer
        break;
1033 b82945bc j_mayer
    case 4:
1034 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_EXECUTE;
1035 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1036 b82945bc j_mayer
        ret = 1;
1037 b82945bc j_mayer
    case 5:
1038 b82945bc j_mayer
        env->exception_index = EXCP_FAULT_ON_WRITE;
1039 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1040 b82945bc j_mayer
        ret = 1;
1041 b82945bc j_mayer
#endif
1042 b82945bc j_mayer
    default:
1043 b82945bc j_mayer
        /* Should never happen */
1044 b82945bc j_mayer
        env->exception_index = EXCP_MCHK;
1045 b82945bc j_mayer
        env->ipr[IPR_EXC_ADDR] = address;
1046 b82945bc j_mayer
        ret = 1;
1047 b82945bc j_mayer
        break;
1048 b82945bc j_mayer
    }
1049 b82945bc j_mayer
1050 b82945bc j_mayer
    return ret;
1051 b82945bc j_mayer
}
1052 b82945bc j_mayer
#endif
1053 b82945bc j_mayer
1054 b82945bc j_mayer
#else /* !defined (CONFIG_USER_ONLY) */
1055 b82945bc j_mayer
void pal_init (CPUState *env)
1056 b82945bc j_mayer
{
1057 b82945bc j_mayer
}
1058 b82945bc j_mayer
1059 b82945bc j_mayer
void call_pal (CPUState *env, int palcode)
1060 b82945bc j_mayer
{
1061 d9e147ad aurel32
    target_long ret;
1062 b82945bc j_mayer
1063 93fcfe39 aliguori
    qemu_log("%s: palcode %02x\n", __func__, palcode);
1064 b82945bc j_mayer
    switch (palcode) {
1065 b82945bc j_mayer
    case 0x83:
1066 b82945bc j_mayer
        /* CALLSYS */
1067 93fcfe39 aliguori
        qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
1068 b82945bc j_mayer
        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
1069 b82945bc j_mayer
                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
1070 b82945bc j_mayer
                         env->ir[IR_A5]);
1071 d74e3b12 aurel32
        if (ret >= 0) {
1072 d74e3b12 aurel32
            env->ir[IR_A3] = 0;
1073 d74e3b12 aurel32
            env->ir[IR_V0] = ret;
1074 b82945bc j_mayer
        } else {
1075 d74e3b12 aurel32
            env->ir[IR_A3] = 1;
1076 d74e3b12 aurel32
            env->ir[IR_V0] = -ret;
1077 b82945bc j_mayer
        }
1078 b82945bc j_mayer
        break;
1079 b82945bc j_mayer
    case 0x9E:
1080 b82945bc j_mayer
        /* RDUNIQUE */
1081 b82945bc j_mayer
        env->ir[IR_V0] = env->unique;
1082 93fcfe39 aliguori
        qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1083 b82945bc j_mayer
        break;
1084 b82945bc j_mayer
    case 0x9F:
1085 b82945bc j_mayer
        /* WRUNIQUE */
1086 b82945bc j_mayer
        env->unique = env->ir[IR_A0];
1087 93fcfe39 aliguori
        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1088 b82945bc j_mayer
        break;
1089 b82945bc j_mayer
    default:
1090 93fcfe39 aliguori
        qemu_log("%s: unhandled palcode %02x\n",
1091 b82945bc j_mayer
                    __func__, palcode);
1092 b82945bc j_mayer
        exit(1);
1093 b82945bc j_mayer
    }
1094 b82945bc j_mayer
}
1095 b82945bc j_mayer
#endif