~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to hw/alpha_palcode.c

  • Committer: pbrook
  • Date: 2006-10-22 00:18:54 UTC
  • Revision ID: git-v1:e6e5906b6e0a81718066ca43aef57515026c6624
ColdFire target.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2196 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Alpha emulation - PALcode emulation for qemu.
3
 
 *
4
 
 *  Copyright (c) 2007 Jocelyn Mayer
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
 */
20
 
 
21
 
#include <stdint.h>
22
 
#include <stdlib.h>
23
 
#include <stdio.h>
24
 
 
25
 
#include "qemu.h"
26
 
#include "cpu.h"
27
 
#include "exec-all.h"
28
 
 
29
 
#if !defined (CONFIG_USER_ONLY)
30
 
/* Shared handlers */
31
 
static void pal_reset (CPUState *env);
32
 
/* Console handlers */
33
 
static void pal_console_call (CPUState *env, uint32_t palcode);
34
 
/* OpenVMS handlers */
35
 
static void pal_openvms_call (CPUState *env, uint32_t palcode);
36
 
/* UNIX / Linux handlers */
37
 
static void pal_unix_call (CPUState *env, uint32_t palcode);
38
 
 
39
 
pal_handler_t pal_handlers[] = {
40
 
    /* Console handler */
41
 
    {
42
 
        .reset = &pal_reset,
43
 
        .call_pal = &pal_console_call,
44
 
    },
45
 
    /* OpenVMS handler */
46
 
    {
47
 
        .reset = &pal_reset,
48
 
        .call_pal = &pal_openvms_call,
49
 
    },
50
 
    /* UNIX / Linux handler */
51
 
    {
52
 
        .reset = &pal_reset,
53
 
        .call_pal = &pal_unix_call,
54
 
    },
55
 
};
56
 
 
57
 
#if 0
58
 
/* One must explicitly check that the TB is valid and the FOE bit is reset */
59
 
static void update_itb (void)
60
 
{
61
 
    /* This writes into a temp register, not the actual one */
62
 
    mtpr(TB_TAG);
63
 
    mtpr(TB_CTL);
64
 
    /* This commits the TB update */
65
 
    mtpr(ITB_PTE);
66
 
}
67
 
 
68
 
static void update_dtb (void);
69
 
{
70
 
    mtpr(TB_CTL);
71
 
    /* This write into a temp register, not the actual one */
72
 
    mtpr(TB_TAG);
73
 
    /* This commits the TB update */
74
 
    mtpr(DTB_PTE);
75
 
}
76
 
#endif
77
 
 
78
 
static void pal_reset (CPUState *env)
79
 
{
80
 
}
81
 
 
82
 
static void do_swappal (CPUState *env, uint64_t palid)
83
 
{
84
 
    pal_handler_t *pal_handler;
85
 
    int status;
86
 
 
87
 
    status = 0;
88
 
    switch (palid) {
89
 
    case 0 ... 2:
90
 
        pal_handler = &pal_handlers[palid];
91
 
        env->pal_handler = pal_handler;
92
 
        env->ipr[IPR_PAL_BASE] = -1ULL;
93
 
        (*pal_handler->reset)(env);
94
 
        break;
95
 
    case 3 ... 255:
96
 
        /* Unknown identifier */
97
 
        env->ir[0] = 1;
98
 
        return;
99
 
    default:
100
 
        /* We were given the entry point address */
101
 
        env->pal_handler = NULL;
102
 
        env->ipr[IPR_PAL_BASE] = palid;
103
 
        env->pc = env->ipr[IPR_PAL_BASE];
104
 
        cpu_loop_exit();
105
 
    }
106
 
}
107
 
 
108
 
static void pal_console_call (CPUState *env, uint32_t palcode)
109
 
{
110
 
    uint64_t palid;
111
 
 
112
 
    if (palcode < 0x00000080) {
113
 
        /* Privileged palcodes */
114
 
        if (!(env->ps >> 3)) {
115
 
            /* TODO: generate privilege exception */
116
 
        }
117
 
    }
118
 
    switch (palcode) {
119
 
    case 0x00000000:
120
 
        /* HALT */
121
 
        /* REQUIRED */
122
 
        break;
123
 
    case 0x00000001:
124
 
        /* CFLUSH */
125
 
        break;
126
 
    case 0x00000002:
127
 
        /* DRAINA */
128
 
        /* REQUIRED */
129
 
        /* Implemented as no-op */
130
 
        break;
131
 
    case 0x00000009:
132
 
        /* CSERVE */
133
 
        /* REQUIRED */
134
 
        break;
135
 
    case 0x0000000A:
136
 
        /* SWPPAL */
137
 
        /* REQUIRED */
138
 
        palid = env->ir[16];
139
 
        do_swappal(env, palid);
140
 
        break;
141
 
    case 0x00000080:
142
 
        /* BPT */
143
 
        /* REQUIRED */
144
 
        break;
145
 
    case 0x00000081:
146
 
        /* BUGCHK */
147
 
        /* REQUIRED */
148
 
        break;
149
 
    case 0x00000086:
150
 
        /* IMB */
151
 
        /* REQUIRED */
152
 
        /* Implemented as no-op */
153
 
        break;
154
 
    case 0x0000009E:
155
 
        /* RDUNIQUE */
156
 
        /* REQUIRED */
157
 
        break;
158
 
    case 0x0000009F:
159
 
        /* WRUNIQUE */
160
 
        /* REQUIRED */
161
 
        break;
162
 
    case 0x000000AA:
163
 
        /* GENTRAP */
164
 
        /* REQUIRED */
165
 
        break;
166
 
    default:
167
 
        break;
168
 
    }
169
 
}
170
 
 
171
 
static void pal_openvms_call (CPUState *env, uint32_t palcode)
172
 
{
173
 
    uint64_t palid, val, oldval;
174
 
 
175
 
    if (palcode < 0x00000080) {
176
 
        /* Privileged palcodes */
177
 
        if (!(env->ps >> 3)) {
178
 
            /* TODO: generate privilege exception */
179
 
        }
180
 
    }
181
 
    switch (palcode) {
182
 
    case 0x00000000:
183
 
        /* HALT */
184
 
        /* REQUIRED */
185
 
        break;
186
 
    case 0x00000001:
187
 
        /* CFLUSH */
188
 
        break;
189
 
    case 0x00000002:
190
 
        /* DRAINA */
191
 
        /* REQUIRED */
192
 
        /* Implemented as no-op */
193
 
        break;
194
 
    case 0x00000003:
195
 
        /* LDQP */
196
 
        break;
197
 
    case 0x00000004:
198
 
        /* STQP */
199
 
        break;
200
 
    case 0x00000005:
201
 
        /* SWPCTX */
202
 
        break;
203
 
    case 0x00000006:
204
 
        /* MFPR_ASN */
205
 
        if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
206
 
            env->ir[0] = val;
207
 
        break;
208
 
    case 0x00000007:
209
 
        /* MTPR_ASTEN */
210
 
        val = env->ir[16];
211
 
        if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
212
 
            env->ir[0] = val;
213
 
        break;
214
 
    case 0x00000008:
215
 
        /* MTPR_ASTSR */
216
 
        val = env->ir[16];
217
 
        if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
218
 
            env->ir[0] = val;
219
 
        break;
220
 
    case 0x00000009:
221
 
        /* CSERVE */
222
 
        /* REQUIRED */
223
 
        break;
224
 
    case 0x0000000A:
225
 
        /* SWPPAL */
226
 
        /* REQUIRED */
227
 
        palid = env->ir[16];
228
 
        do_swappal(env, palid);
229
 
        break;
230
 
    case 0x0000000B:
231
 
        /* MFPR_FEN */
232
 
        if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
233
 
            env->ir[0] = val;
234
 
        break;
235
 
    case 0x0000000C:
236
 
        /* MTPR_FEN */
237
 
        val = env->ir[16];
238
 
        if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
239
 
            env->ir[0] = val;
240
 
        break;
241
 
    case 0x0000000D:
242
 
        /* MTPR_IPIR */
243
 
        val = env->ir[16];
244
 
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
245
 
            env->ir[0] = val;
246
 
        break;
247
 
    case 0x0000000E:
248
 
        /* MFPR_IPL */
249
 
        if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
250
 
            env->ir[0] = val;
251
 
        break;
252
 
    case 0x0000000F:
253
 
        /* MTPR_IPL */
254
 
        val = env->ir[16];
255
 
        if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
256
 
            env->ir[0] = val;
257
 
        break;
258
 
    case 0x00000010:
259
 
        /* MFPR_MCES */
260
 
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
261
 
            env->ir[0] = val;
262
 
        break;
263
 
    case 0x00000011:
264
 
        /* MTPR_MCES */
265
 
        val = env->ir[16];
266
 
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
267
 
            env->ir[0] = val;
268
 
        break;
269
 
    case 0x00000012:
270
 
        /* MFPR_PCBB */
271
 
        if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
272
 
            env->ir[0] = val;
273
 
        break;
274
 
    case 0x00000013:
275
 
        /* MFPR_PRBR */
276
 
        if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
277
 
            env->ir[0] = val;
278
 
        break;
279
 
    case 0x00000014:
280
 
        /* MTPR_PRBR */
281
 
        val = env->ir[16];
282
 
        if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
283
 
            env->ir[0] = val;
284
 
        break;
285
 
    case 0x00000015:
286
 
        /* MFPR_PTBR */
287
 
        if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
288
 
            env->ir[0] = val;
289
 
        break;
290
 
    case 0x00000016:
291
 
        /* MFPR_SCBB */
292
 
        if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
293
 
            env->ir[0] = val;
294
 
        break;
295
 
    case 0x00000017:
296
 
        /* MTPR_SCBB */
297
 
        val = env->ir[16];
298
 
        if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
299
 
            env->ir[0] = val;
300
 
        break;
301
 
    case 0x00000018:
302
 
        /* MTPR_SIRR */
303
 
        val = env->ir[16];
304
 
        if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
305
 
            env->ir[0] = val;
306
 
        break;
307
 
    case 0x00000019:
308
 
        /* MFPR_SISR */
309
 
        if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
310
 
            env->ir[0] = val;
311
 
        break;
312
 
    case 0x0000001A:
313
 
        /* MFPR_TBCHK */
314
 
        if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
315
 
            env->ir[0] = val;
316
 
        break;
317
 
    case 0x0000001B:
318
 
        /* MTPR_TBIA */
319
 
        val = env->ir[16];
320
 
        if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
321
 
            env->ir[0] = val;
322
 
        break;
323
 
    case 0x0000001C:
324
 
        /* MTPR_TBIAP */
325
 
        val = env->ir[16];
326
 
        if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
327
 
            env->ir[0] = val;
328
 
        break;
329
 
    case 0x0000001D:
330
 
        /* MTPR_TBIS */
331
 
        val = env->ir[16];
332
 
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
333
 
            env->ir[0] = val;
334
 
        break;
335
 
    case 0x0000001E:
336
 
        /* MFPR_ESP */
337
 
        if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
338
 
            env->ir[0] = val;
339
 
        break;
340
 
    case 0x0000001F:
341
 
        /* MTPR_ESP */
342
 
        val = env->ir[16];
343
 
        if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
344
 
            env->ir[0] = val;
345
 
        break;
346
 
    case 0x00000020:
347
 
        /* MFPR_SSP */
348
 
        if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
349
 
            env->ir[0] = val;
350
 
        break;
351
 
    case 0x00000021:
352
 
        /* MTPR_SSP */
353
 
        val = env->ir[16];
354
 
        if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
355
 
            env->ir[0] = val;
356
 
        break;
357
 
    case 0x00000022:
358
 
        /* MFPR_USP */
359
 
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
360
 
            env->ir[0] = val;
361
 
        break;
362
 
    case 0x00000023:
363
 
        /* MTPR_USP */
364
 
        val = env->ir[16];
365
 
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
366
 
            env->ir[0] = val;
367
 
        break;
368
 
    case 0x00000024:
369
 
        /* MTPR_TBISD */
370
 
        val = env->ir[16];
371
 
        if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
372
 
            env->ir[0] = val;
373
 
        break;
374
 
    case 0x00000025:
375
 
        /* MTPR_TBISI */
376
 
        val = env->ir[16];
377
 
        if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
378
 
            env->ir[0] = val;
379
 
        break;
380
 
    case 0x00000026:
381
 
        /* MFPR_ASTEN */
382
 
        if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
383
 
            env->ir[0] = val;
384
 
        break;
385
 
    case 0x00000027:
386
 
        /* MFPR_ASTSR */
387
 
        if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
388
 
            env->ir[0] = val;
389
 
        break;
390
 
    case 0x00000029:
391
 
        /* MFPR_VPTB */
392
 
        if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
393
 
            env->ir[0] = val;
394
 
        break;
395
 
    case 0x0000002A:
396
 
        /* MTPR_VPTB */
397
 
        val = env->ir[16];
398
 
        if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
399
 
            env->ir[0] = val;
400
 
        break;
401
 
    case 0x0000002B:
402
 
        /* MTPR_PERFMON */
403
 
        val = env->ir[16];
404
 
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
405
 
            env->ir[0] = val;
406
 
        break;
407
 
    case 0x0000002E:
408
 
        /* MTPR_DATFX */
409
 
        val = env->ir[16];
410
 
        if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
411
 
            env->ir[0] = val;
412
 
        break;
413
 
    case 0x0000003E:
414
 
        /* WTINT */
415
 
        break;
416
 
    case 0x0000003F:
417
 
        /* MFPR_WHAMI */
418
 
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
419
 
            env->ir[0] = val;
420
 
        break;
421
 
    case 0x00000080:
422
 
        /* BPT */
423
 
        /* REQUIRED */
424
 
        break;
425
 
    case 0x00000081:
426
 
        /* BUGCHK */
427
 
        /* REQUIRED */
428
 
        break;
429
 
    case 0x00000082:
430
 
        /* CHME */
431
 
        break;
432
 
    case 0x00000083:
433
 
        /* CHMK */
434
 
        break;
435
 
    case 0x00000084:
436
 
        /* CHMS */
437
 
        break;
438
 
    case 0x00000085:
439
 
        /* CHMU */
440
 
        break;
441
 
    case 0x00000086:
442
 
        /* IMB */
443
 
        /* REQUIRED */
444
 
        /* Implemented as no-op */
445
 
        break;
446
 
    case 0x00000087:
447
 
        /* INSQHIL */
448
 
        break;
449
 
    case 0x00000088:
450
 
        /* INSQTIL */
451
 
        break;
452
 
    case 0x00000089:
453
 
        /* INSQHIQ */
454
 
        break;
455
 
    case 0x0000008A:
456
 
        /* INSQTIQ */
457
 
        break;
458
 
    case 0x0000008B:
459
 
        /* INSQUEL */
460
 
        break;
461
 
    case 0x0000008C:
462
 
        /* INSQUEQ */
463
 
        break;
464
 
    case 0x0000008D:
465
 
        /* INSQUEL/D */
466
 
        break;
467
 
    case 0x0000008E:
468
 
        /* INSQUEQ/D */
469
 
        break;
470
 
    case 0x0000008F:
471
 
        /* PROBER */
472
 
        break;
473
 
    case 0x00000090:
474
 
        /* PROBEW */
475
 
        break;
476
 
    case 0x00000091:
477
 
        /* RD_PS */
478
 
        break;
479
 
    case 0x00000092:
480
 
        /* REI */
481
 
        break;
482
 
    case 0x00000093:
483
 
        /* REMQHIL */
484
 
        break;
485
 
    case 0x00000094:
486
 
        /* REMQTIL */
487
 
        break;
488
 
    case 0x00000095:
489
 
        /* REMQHIQ */
490
 
        break;
491
 
    case 0x00000096:
492
 
        /* REMQTIQ */
493
 
        break;
494
 
    case 0x00000097:
495
 
        /* REMQUEL */
496
 
        break;
497
 
    case 0x00000098:
498
 
        /* REMQUEQ */
499
 
        break;
500
 
    case 0x00000099:
501
 
        /* REMQUEL/D */
502
 
        break;
503
 
    case 0x0000009A:
504
 
        /* REMQUEQ/D */
505
 
        break;
506
 
    case 0x0000009B:
507
 
        /* SWASTEN */
508
 
        break;
509
 
    case 0x0000009C:
510
 
        /* WR_PS_SW */
511
 
        break;
512
 
    case 0x0000009D:
513
 
        /* RSCC */
514
 
        break;
515
 
    case 0x0000009E:
516
 
        /* READ_UNQ */
517
 
        /* REQUIRED */
518
 
        break;
519
 
    case 0x0000009F:
520
 
        /* WRITE_UNQ */
521
 
        /* REQUIRED */
522
 
        break;
523
 
    case 0x000000A0:
524
 
        /* AMOVRR */
525
 
        break;
526
 
    case 0x000000A1:
527
 
        /* AMOVRM */
528
 
        break;
529
 
    case 0x000000A2:
530
 
        /* INSQHILR */
531
 
        break;
532
 
    case 0x000000A3:
533
 
        /* INSQTILR */
534
 
        break;
535
 
    case 0x000000A4:
536
 
        /* INSQHIQR */
537
 
        break;
538
 
    case 0x000000A5:
539
 
        /* INSQTIQR */
540
 
        break;
541
 
    case 0x000000A6:
542
 
        /* REMQHILR */
543
 
        break;
544
 
    case 0x000000A7:
545
 
        /* REMQTILR */
546
 
        break;
547
 
    case 0x000000A8:
548
 
        /* REMQHIQR */
549
 
        break;
550
 
    case 0x000000A9:
551
 
        /* REMQTIQR */
552
 
        break;
553
 
    case 0x000000AA:
554
 
        /* GENTRAP */
555
 
        /* REQUIRED */
556
 
        break;
557
 
    case 0x000000AE:
558
 
        /* CLRFEN */
559
 
        break;
560
 
    default:
561
 
        break;
562
 
    }
563
 
}
564
 
 
565
 
static void pal_unix_call (CPUState *env, uint32_t palcode)
566
 
{
567
 
    uint64_t palid, val, oldval;
568
 
 
569
 
    if (palcode < 0x00000080) {
570
 
        /* Privileged palcodes */
571
 
        if (!(env->ps >> 3)) {
572
 
            /* TODO: generate privilege exception */
573
 
        }
574
 
    }
575
 
    switch (palcode) {
576
 
    case 0x00000000:
577
 
        /* HALT */
578
 
        /* REQUIRED */
579
 
        break;
580
 
    case 0x00000001:
581
 
        /* CFLUSH */
582
 
        break;
583
 
    case 0x00000002:
584
 
        /* DRAINA */
585
 
        /* REQUIRED */
586
 
        /* Implemented as no-op */
587
 
        break;
588
 
    case 0x00000009:
589
 
        /* CSERVE */
590
 
        /* REQUIRED */
591
 
        break;
592
 
    case 0x0000000A:
593
 
        /* SWPPAL */
594
 
        /* REQUIRED */
595
 
        palid = env->ir[16];
596
 
        do_swappal(env, palid);
597
 
        break;
598
 
    case 0x0000000D:
599
 
        /* WRIPIR */
600
 
        val = env->ir[16];
601
 
        if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
602
 
            env->ir[0] = val;
603
 
        break;
604
 
    case 0x00000010:
605
 
        /* RDMCES */
606
 
        if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
607
 
            env->ir[0] = val;
608
 
        break;
609
 
    case 0x00000011:
610
 
        /* WRMCES */
611
 
        val = env->ir[16];
612
 
        if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
613
 
            env->ir[0] = val;
614
 
        break;
615
 
    case 0x0000002B:
616
 
        /* WRFEN */
617
 
        val = env->ir[16];
618
 
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
619
 
            env->ir[0] = val;
620
 
        break;
621
 
    case 0x0000002D:
622
 
        /* WRVPTPTR */
623
 
        break;
624
 
    case 0x00000030:
625
 
        /* SWPCTX */
626
 
        break;
627
 
    case 0x00000031:
628
 
        /* WRVAL */
629
 
        break;
630
 
    case 0x00000032:
631
 
        /* RDVAL */
632
 
        break;
633
 
    case 0x00000033:
634
 
        /* TBI */
635
 
        val = env->ir[16];
636
 
        if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
637
 
            env->ir[0] = val;
638
 
        break;
639
 
    case 0x00000034:
640
 
        /* WRENT */
641
 
        break;
642
 
    case 0x00000035:
643
 
        /* SWPIPL */
644
 
        break;
645
 
    case 0x00000036:
646
 
        /* RDPS */
647
 
        break;
648
 
    case 0x00000037:
649
 
        /* WRKGP */
650
 
        break;
651
 
    case 0x00000038:
652
 
        /* WRUSP */
653
 
        val = env->ir[16];
654
 
        if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
655
 
            env->ir[0] = val;
656
 
        break;
657
 
    case 0x00000039:
658
 
        /* WRPERFMON */
659
 
        val = env->ir[16];
660
 
        if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
661
 
            env->ir[0] = val;
662
 
        break;
663
 
    case 0x0000003A:
664
 
        /* RDUSP */
665
 
        if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
666
 
            env->ir[0] = val;
667
 
        break;
668
 
    case 0x0000003C:
669
 
        /* WHAMI */
670
 
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
671
 
            env->ir[0] = val;
672
 
        break;
673
 
    case 0x0000003D:
674
 
        /* RETSYS */
675
 
        break;
676
 
    case 0x0000003E:
677
 
        /* WTINT */
678
 
        break;
679
 
    case 0x0000003F:
680
 
        /* RTI */
681
 
        if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
682
 
            env->ir[0] = val;
683
 
        break;
684
 
    case 0x00000080:
685
 
        /* BPT */
686
 
        /* REQUIRED */
687
 
        break;
688
 
    case 0x00000081:
689
 
        /* BUGCHK */
690
 
        /* REQUIRED */
691
 
        break;
692
 
    case 0x00000083:
693
 
        /* CALLSYS */
694
 
        break;
695
 
    case 0x00000086:
696
 
        /* IMB */
697
 
        /* REQUIRED */
698
 
        /* Implemented as no-op */
699
 
        break;
700
 
    case 0x00000092:
701
 
        /* URTI */
702
 
        break;
703
 
    case 0x0000009E:
704
 
        /* RDUNIQUE */
705
 
        /* REQUIRED */
706
 
        break;
707
 
    case 0x0000009F:
708
 
        /* WRUNIQUE */
709
 
        /* REQUIRED */
710
 
        break;
711
 
    case 0x000000AA:
712
 
        /* GENTRAP */
713
 
        /* REQUIRED */
714
 
        break;
715
 
    case 0x000000AE:
716
 
        /* CLRFEN */
717
 
        break;
718
 
    default:
719
 
        break;
720
 
    }
721
 
}
722
 
 
723
 
void call_pal (CPUState *env)
724
 
{
725
 
    pal_handler_t *pal_handler = env->pal_handler;
726
 
 
727
 
    switch (env->exception_index) {
728
 
    case EXCP_RESET:
729
 
        (*pal_handler->reset)(env);
730
 
        break;
731
 
    case EXCP_MCHK:
732
 
        (*pal_handler->machine_check)(env);
733
 
        break;
734
 
    case EXCP_ARITH:
735
 
        (*pal_handler->arithmetic)(env);
736
 
        break;
737
 
    case EXCP_INTERRUPT:
738
 
        (*pal_handler->interrupt)(env);
739
 
        break;
740
 
    case EXCP_DFAULT:
741
 
        (*pal_handler->dfault)(env);
742
 
        break;
743
 
    case EXCP_DTB_MISS_PAL:
744
 
        (*pal_handler->dtb_miss_pal)(env);
745
 
        break;
746
 
    case EXCP_DTB_MISS_NATIVE:
747
 
        (*pal_handler->dtb_miss_native)(env);
748
 
        break;
749
 
    case EXCP_UNALIGN:
750
 
        (*pal_handler->unalign)(env);
751
 
        break;
752
 
    case EXCP_ITB_MISS:
753
 
        (*pal_handler->itb_miss)(env);
754
 
        break;
755
 
    case EXCP_ITB_ACV:
756
 
        (*pal_handler->itb_acv)(env);
757
 
        break;
758
 
    case EXCP_OPCDEC:
759
 
        (*pal_handler->opcdec)(env);
760
 
        break;
761
 
    case EXCP_FEN:
762
 
        (*pal_handler->fen)(env);
763
 
        break;
764
 
    default:
765
 
        if (env->exception_index >= EXCP_CALL_PAL &&
766
 
            env->exception_index < EXCP_CALL_PALP) {
767
 
            /* Unprivileged PAL call */
768
 
            (*pal_handler->call_pal)
769
 
                (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
770
 
        } else if (env->exception_index >= EXCP_CALL_PALP &&
771
 
                   env->exception_index < EXCP_CALL_PALE) {
772
 
            /* Privileged PAL call */
773
 
            (*pal_handler->call_pal)
774
 
                (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
775
 
        } else {
776
 
            /* Should never happen */
777
 
        }
778
 
        break;
779
 
    }
780
 
    env->ipr[IPR_EXC_ADDR] &= ~1;
781
 
}
782
 
 
783
 
void pal_init (CPUState *env)
784
 
{
785
 
    do_swappal(env, 0);
786
 
}
787
 
 
788
 
#if 0
789
 
static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
790
 
{
791
 
    uint64_t virbnd, ptbr;
792
 
 
793
 
    if ((env->features & FEATURE_VIRBND)) {
794
 
        cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
795
 
        if (vaddr >= virbnd)
796
 
            cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
797
 
        else
798
 
            cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
799
 
    } else {
800
 
        cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
801
 
    }
802
 
 
803
 
    return ptbr;
804
 
}
805
 
 
806
 
static int get_page_bits (CPUState *env)
807
 
{
808
 
    /* XXX */
809
 
    return 13;
810
 
}
811
 
 
812
 
static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
813
 
                    uint64_t ptebase, int page_bits, uint64_t level,
814
 
                    int mmu_idx, int rw)
815
 
{
816
 
    uint64_t pteaddr, pte, pfn;
817
 
    uint8_t gh;
818
 
    int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
819
 
 
820
 
    /* XXX: TOFIX */
821
 
    is_user = mmu_idx == MMU_USER_IDX;
822
 
    pteaddr = (ptebase << page_bits) + (8 * level);
823
 
    pte = ldq_raw(pteaddr);
824
 
    /* Decode all interresting PTE fields */
825
 
    pfn = pte >> 32;
826
 
    uwe = (pte >> 13) & 1;
827
 
    kwe = (pte >> 12) & 1;
828
 
    ure = (pte >> 9) & 1;
829
 
    kre = (pte >> 8) & 1;
830
 
    gh = (pte >> 5) & 3;
831
 
    foE = (pte >> 3) & 1;
832
 
    foW = (pte >> 2) & 1;
833
 
    foR = (pte >> 1) & 1;
834
 
    v = pte & 1;
835
 
    ret = 0;
836
 
    if (!v)
837
 
        ret = 0x1;
838
 
    /* Check access rights */
839
 
    ar = 0;
840
 
    if (is_user) {
841
 
        if (ure)
842
 
            ar |= PAGE_READ;
843
 
        if (uwe)
844
 
            ar |= PAGE_WRITE;
845
 
        if (rw == 1 && !uwe)
846
 
            ret |= 0x2;
847
 
        if (rw != 1 && !ure)
848
 
            ret |= 0x2;
849
 
    } else {
850
 
        if (kre)
851
 
            ar |= PAGE_READ;
852
 
        if (kwe)
853
 
            ar |= PAGE_WRITE;
854
 
        if (rw == 1 && !kwe)
855
 
            ret |= 0x2;
856
 
        if (rw != 1 && !kre)
857
 
            ret |= 0x2;
858
 
    }
859
 
    if (rw == 0 && foR)
860
 
        ret |= 0x4;
861
 
    if (rw == 2 && foE)
862
 
        ret |= 0x8;
863
 
    if (rw == 1 && foW)
864
 
        ret |= 0xC;
865
 
    *pfnp = pfn;
866
 
    if (zbitsp != NULL)
867
 
        *zbitsp = page_bits + (3 * gh);
868
 
    if (protp != NULL)
869
 
        *protp = ar;
870
 
 
871
 
    return ret;
872
 
}
873
 
 
874
 
static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
875
 
                           uint64_t ptebase, int page_bits,
876
 
                           uint64_t vaddr, int mmu_idx, int rw)
877
 
{
878
 
    uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
879
 
    int lvl_bits, ret;
880
 
 
881
 
    page_mask = (1ULL << page_bits) - 1ULL;
882
 
    lvl_bits = page_bits - 3;
883
 
    lvl_mask = (1ULL << lvl_bits) - 1ULL;
884
 
    level3 = (vaddr >> page_bits) & lvl_mask;
885
 
    level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
886
 
    level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
887
 
    /* Level 1 PTE */
888
 
    ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
889
 
    switch (ret) {
890
 
    case 3:
891
 
        /* Access violation */
892
 
        return 2;
893
 
    case 2:
894
 
        /* translation not valid */
895
 
        return 1;
896
 
    default:
897
 
        /* OK */
898
 
        break;
899
 
    }
900
 
    /* Level 2 PTE */
901
 
    ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
902
 
    switch (ret) {
903
 
    case 3:
904
 
        /* Access violation */
905
 
        return 2;
906
 
    case 2:
907
 
        /* translation not valid */
908
 
        return 1;
909
 
    default:
910
 
        /* OK */
911
 
        break;
912
 
    }
913
 
    /* Level 3 PTE */
914
 
    ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
915
 
    if (ret & 0x1) {
916
 
        /* Translation not valid */
917
 
        ret = 1;
918
 
    } else if (ret & 2) {
919
 
        /* Access violation */
920
 
        ret = 2;
921
 
    } else {
922
 
        switch (ret & 0xC) {
923
 
        case 0:
924
 
            /* OK */
925
 
            ret = 0;
926
 
            break;
927
 
        case 0x4:
928
 
            /* Fault on read */
929
 
            ret = 3;
930
 
            break;
931
 
        case 0x8:
932
 
            /* Fault on execute */
933
 
            ret = 4;
934
 
            break;
935
 
        case 0xC:
936
 
            /* Fault on write */
937
 
            ret = 5;
938
 
            break;
939
 
        }
940
 
    }
941
 
    *paddr = (pfn << page_bits) | (vaddr & page_mask);
942
 
 
943
 
    return 0;
944
 
}
945
 
 
946
 
static int virtual_to_physical (CPUState *env, uint64_t *physp,
947
 
                                int *zbitsp, int *protp,
948
 
                                uint64_t virtual, int mmu_idx, int rw)
949
 
{
950
 
    uint64_t sva, ptebase;
951
 
    int seg, page_bits, ret;
952
 
 
953
 
    sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
954
 
    if (sva != virtual)
955
 
        seg = -1;
956
 
    else
957
 
        seg = sva >> (VA_BITS - 2);
958
 
    virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
959
 
    ptebase = get_ptebase(env, virtual);
960
 
    page_bits = get_page_bits(env);
961
 
    ret = 0;
962
 
    switch (seg) {
963
 
    case 0:
964
 
        /* seg1: 3 levels of PTE */
965
 
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
966
 
                             virtual, mmu_idx, rw);
967
 
        break;
968
 
    case 1:
969
 
        /* seg1: 2 levels of PTE */
970
 
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
971
 
                             virtual, mmu_idx, rw);
972
 
        break;
973
 
    case 2:
974
 
        /* kernel segment */
975
 
        if (mmu_idx != 0) {
976
 
            ret = 2;
977
 
        } else {
978
 
            *physp = virtual;
979
 
        }
980
 
        break;
981
 
    case 3:
982
 
        /* seg1: TB mapped */
983
 
        ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
984
 
                             virtual, mmu_idx, rw);
985
 
        break;
986
 
    default:
987
 
        ret = 1;
988
 
        break;
989
 
    }
990
 
 
991
 
    return ret;
992
 
}
993
 
 
994
 
/* XXX: code provision */
995
 
int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
996
 
                              int mmu_idx, int is_softmmu)
997
 
{
998
 
    uint64_t physical, page_size, end;
999
 
    int prot, zbits, ret;
1000
 
 
1001
 
    if (env->user_mode_only) {
1002
 
        ret = 2;
1003
 
    } else {
1004
 
        ret = virtual_to_physical(env, &physical, &zbits, &prot,
1005
 
                                  address, mmu_idx, rw);
1006
 
    }
1007
 
    switch (ret) {
1008
 
    case 0:
1009
 
        /* No fault */
1010
 
        page_size = 1ULL << zbits;
1011
 
        address &= ~(page_size - 1);
1012
 
        for (end = physical + page_size; physical < end; physical += 0x1000) {
1013
 
            ret = tlb_set_page(env, address, physical, prot,
1014
 
                               mmu_idx, is_softmmu);
1015
 
            address += 0x1000;
1016
 
        }
1017
 
        break;
1018
 
#if 0
1019
 
    case 1:
1020
 
        env->exception_index = EXCP_DFAULT;
1021
 
        env->ipr[IPR_EXC_ADDR] = address;
1022
 
        ret = 1;
1023
 
        break;
1024
 
    case 2:
1025
 
        env->exception_index = EXCP_ACCESS_VIOLATION;
1026
 
        env->ipr[IPR_EXC_ADDR] = address;
1027
 
        ret = 1;
1028
 
        break;
1029
 
    case 3:
1030
 
        env->exception_index = EXCP_FAULT_ON_READ;
1031
 
        env->ipr[IPR_EXC_ADDR] = address;
1032
 
        ret = 1;
1033
 
        break;
1034
 
    case 4:
1035
 
        env->exception_index = EXCP_FAULT_ON_EXECUTE;
1036
 
        env->ipr[IPR_EXC_ADDR] = address;
1037
 
        ret = 1;
1038
 
    case 5:
1039
 
        env->exception_index = EXCP_FAULT_ON_WRITE;
1040
 
        env->ipr[IPR_EXC_ADDR] = address;
1041
 
        ret = 1;
1042
 
#endif
1043
 
    default:
1044
 
        /* Should never happen */
1045
 
        env->exception_index = EXCP_MCHK;
1046
 
        env->ipr[IPR_EXC_ADDR] = address;
1047
 
        ret = 1;
1048
 
        break;
1049
 
    }
1050
 
 
1051
 
    return ret;
1052
 
}
1053
 
#endif
1054
 
 
1055
 
#else /* !defined (CONFIG_USER_ONLY) */
1056
 
void pal_init (CPUState *env)
1057
 
{
1058
 
}
1059
 
 
1060
 
void call_pal (CPUState *env, int palcode)
1061
 
{
1062
 
    target_ulong ret;
1063
 
 
1064
 
    printf("%s: palcode %02x\n", __func__, palcode);
1065
 
    if (logfile != NULL)
1066
 
        fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
1067
 
    switch (palcode) {
1068
 
    case 0x83:
1069
 
        /* CALLSYS */
1070
 
        printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
1071
 
        if (logfile != NULL)
1072
 
            fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
1073
 
        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
1074
 
                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
1075
 
                         env->ir[IR_A5]);
1076
 
        env->ir[IR_A3] = ret;
1077
 
        if (ret > (target_ulong)(-515)) {
1078
 
            env->ir[IR_V0] = 1;
1079
 
        } else {
1080
 
            env->ir[IR_V0] = 0;
1081
 
        }
1082
 
        break;
1083
 
    case 0x9E:
1084
 
        /* RDUNIQUE */
1085
 
        env->ir[IR_V0] = env->unique;
1086
 
        printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1087
 
        break;
1088
 
    case 0x9F:
1089
 
        /* WRUNIQUE */
1090
 
        env->unique = env->ir[IR_A0];
1091
 
        printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
1092
 
        break;
1093
 
    default:
1094
 
        printf("%s: unhandled palcode %02x\n", __func__, palcode);
1095
 
        if (logfile != NULL)
1096
 
            fprintf(logfile, "%s: unhandled palcode %02x\n",
1097
 
                    __func__, palcode);
1098
 
        exit(1);
1099
 
    }
1100
 
}
1101
 
#endif