Statistics
| Branch: | Revision:

root / hw / alpha_palcode.c @ 5fafdf24

History | View | Annotate | Download (26.9 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 b82945bc j_mayer
 * License along with this library; if not, write to the Free Software
18 b82945bc j_mayer
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 b82945bc j_mayer
 */
20 b82945bc j_mayer
21 b82945bc j_mayer
#include <stdint.h>
22 b82945bc j_mayer
#include <stdlib.h>
23 b82945bc j_mayer
#include <stdio.h>
24 b82945bc j_mayer
25 b82945bc j_mayer
#include "qemu.h"
26 b82945bc j_mayer
#include "cpu.h"
27 b82945bc j_mayer
#include "exec-all.h"
28 b82945bc j_mayer
29 b82945bc j_mayer
#if !defined (CONFIG_USER_ONLY)
30 b82945bc j_mayer
/* Shared handlers */
31 b82945bc j_mayer
static void pal_reset (CPUState *env);
32 b82945bc j_mayer
/* Console handlers */
33 b82945bc j_mayer
static void pal_console_call (CPUState *env, uint32_t palcode);
34 b82945bc j_mayer
/* OpenVMS handlers */
35 b82945bc j_mayer
static void pal_openvms_call (CPUState *env, uint32_t palcode);
36 b82945bc j_mayer
/* UNIX / Linux handlers */
37 b82945bc j_mayer
static void pal_unix_call (CPUState *env, uint32_t palcode);
38 b82945bc j_mayer
39 b82945bc j_mayer
pal_handler_t pal_handlers[] = {
40 b82945bc j_mayer
    /* Console handler */
41 b82945bc j_mayer
    {
42 b82945bc j_mayer
        .reset = &pal_reset,
43 b82945bc j_mayer
        .call_pal = &pal_console_call,
44 b82945bc j_mayer
    },
45 b82945bc j_mayer
    /* OpenVMS handler */
46 b82945bc j_mayer
    {
47 b82945bc j_mayer
        .reset = &pal_reset,
48 b82945bc j_mayer
        .call_pal = &pal_openvms_call,
49 b82945bc j_mayer
    },
50 b82945bc j_mayer
    /* UNIX / Linux handler */
51 b82945bc j_mayer
    {
52 b82945bc j_mayer
        .reset = &pal_reset,
53 b82945bc j_mayer
        .call_pal = &pal_unix_call,
54 b82945bc j_mayer
    },
55 b82945bc j_mayer
};
56 b82945bc j_mayer
57 b82945bc j_mayer
#if 0
58 b82945bc j_mayer
/* One must explicitely check that the TB is valid and the FOE bit is reset */
59 b82945bc j_mayer
static void update_itb ()
60 b82945bc j_mayer
{
61 b82945bc j_mayer
    /* This writes into a temp register, not the actual one */
62 b82945bc j_mayer
    mtpr(TB_TAG);
63 b82945bc j_mayer
    mtpr(TB_CTL);
64 b82945bc j_mayer
    /* This commits the TB update */
65 5fafdf24 ths
    mtpr(ITB_PTE);
66 b82945bc j_mayer
}
67 b82945bc j_mayer

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

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

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

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

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

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

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

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

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

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

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

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

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

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