Commit b82945bcdbf4468327b29b8547bc12b0f07062f0

Authored by j_mayer
1 parent 4c9649a9

Alpha CPU palcode emulation. Only usable in user mode for now with

code provision for full emulation support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2598 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 1099 additions and 0 deletions
hw/alpha_palcode.c 0 → 100644
  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 explicitely check that the TB is valid and the FOE bit is reset */
  59 +static void update_itb ()
  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 ();
  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 is_user, 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;
  819 +
  820 + pteaddr = (ptebase << page_bits) + (8 * level);
  821 + pte = ldq_raw(pteaddr);
  822 + /* Decode all interresting PTE fields */
  823 + pfn = pte >> 32;
  824 + uwe = (pte >> 13) & 1;
  825 + kwe = (pte >> 12) & 1;
  826 + ure = (pte >> 9) & 1;
  827 + kre = (pte >> 8) & 1;
  828 + gh = (pte >> 5) & 3;
  829 + foE = (pte >> 3) & 1;
  830 + foW = (pte >> 2) & 1;
  831 + foR = (pte >> 1) & 1;
  832 + v = pte & 1;
  833 + ret = 0;
  834 + if (!v)
  835 + ret = 0x1;
  836 + /* Check access rights */
  837 + ar = 0;
  838 + if (is_user) {
  839 + if (ure)
  840 + ar |= PAGE_READ;
  841 + if (uwe)
  842 + ar |= PAGE_WRITE;
  843 + if (rw == 1 && !uwe)
  844 + ret |= 0x2;
  845 + if (rw != 1 && !ure)
  846 + ret |= 0x2;
  847 + } else {
  848 + if (kre)
  849 + ar |= PAGE_READ;
  850 + if (kwe)
  851 + ar |= PAGE_WRITE;
  852 + if (rw == 1 && !kwe)
  853 + ret |= 0x2;
  854 + if (rw != 1 && !kre)
  855 + ret |= 0x2;
  856 + }
  857 + if (rw == 0 && foR)
  858 + ret |= 0x4;
  859 + if (rw == 2 && foE)
  860 + ret |= 0x8;
  861 + if (rw == 1 && foW)
  862 + ret |= 0xC;
  863 + *pfnp = pfn;
  864 + if (zbitsp != NULL)
  865 + *zbitsp = page_bits + (3 * gh);
  866 + if (protp != NULL)
  867 + *protp = ar;
  868 +
  869 + return ret;
  870 +}
  871 +
  872 +static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
  873 + uint64_t ptebase, int page_bits,
  874 + uint64_t vaddr, int is_user, int rw)
  875 +{
  876 + uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
  877 + int lvl_bits, ret;
  878 +
  879 + page_mask = (1ULL << page_bits) - 1ULL;
  880 + lvl_bits = page_bits - 3;
  881 + lvl_mask = (1ULL << lvl_bits) - 1ULL;
  882 + level3 = (vaddr >> page_bits) & lvl_mask;
  883 + level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
  884 + level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
  885 + /* Level 1 PTE */
  886 + ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
  887 + switch (ret) {
  888 + case 3:
  889 + /* Access violation */
  890 + return 2;
  891 + case 2:
  892 + /* translation not valid */
  893 + return 1;
  894 + default:
  895 + /* OK */
  896 + break;
  897 + }
  898 + /* Level 2 PTE */
  899 + ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
  900 + switch (ret) {
  901 + case 3:
  902 + /* Access violation */
  903 + return 2;
  904 + case 2:
  905 + /* translation not valid */
  906 + return 1;
  907 + default:
  908 + /* OK */
  909 + break;
  910 + }
  911 + /* Level 3 PTE */
  912 + ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, is_user, rw);
  913 + if (ret & 0x1) {
  914 + /* Translation not valid */
  915 + ret = 1;
  916 + } else if (ret & 2) {
  917 + /* Access violation */
  918 + ret = 2;
  919 + } else {
  920 + switch (ret & 0xC) {
  921 + case 0:
  922 + /* OK */
  923 + ret = 0;
  924 + break;
  925 + case 0x4:
  926 + /* Fault on read */
  927 + ret = 3;
  928 + break;
  929 + case 0x8:
  930 + /* Fault on execute */
  931 + ret = 4;
  932 + break;
  933 + case 0xC:
  934 + /* Fault on write */
  935 + ret = 5;
  936 + break;
  937 + }
  938 + }
  939 + *paddr = (pfn << page_bits) | (vaddr & page_mask);
  940 +
  941 + return 0;
  942 +}
  943 +
  944 +static int virtual_to_physical (CPUState *env, uint64_t *physp,
  945 + int *zbitsp, int *protp,
  946 + uint64_t virtual, int is_user, int rw)
  947 +{
  948 + uint64_t sva, ptebase;
  949 + int seg, page_bits, ret;
  950 +
  951 + sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
  952 + if (sva != virtual)
  953 + seg = -1;
  954 + else
  955 + seg = sva >> (VA_BITS - 2);
  956 + virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
  957 + ptebase = get_ptebase(env, virtual);
  958 + page_bits = get_page_bits(env);
  959 + ret = 0;
  960 + switch (seg) {
  961 + case 0:
  962 + /* seg1: 3 levels of PTE */
  963 + ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
  964 + virtual, is_user, rw);
  965 + break;
  966 + case 1:
  967 + /* seg1: 2 levels of PTE */
  968 + ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
  969 + virtual, is_user, rw);
  970 + break;
  971 + case 2:
  972 + /* kernel segment */
  973 + if (is_user) {
  974 + ret = 2;
  975 + } else {
  976 + *physp = virtual;
  977 + }
  978 + break;
  979 + case 3:
  980 + /* seg1: TB mapped */
  981 + ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
  982 + virtual, is_user, rw);
  983 + break;
  984 + default:
  985 + ret = 1;
  986 + break;
  987 + }
  988 +
  989 + return ret;
  990 +}
  991 +
  992 +/* XXX: code provision */
  993 +int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
  994 + int is_user, int is_softmmu)
  995 +{
  996 + uint64_t physical, page_size, end;
  997 + int prot, zbits, ret;
  998 +
  999 + if (env->user_mode_only) {
  1000 + ret = 2;
  1001 + } else {
  1002 + ret = virtual_to_physical(env, &physical, &zbits, &prot,
  1003 + address, is_user, rw);
  1004 + }
  1005 + switch (ret) {
  1006 + case 0:
  1007 + /* No fault */
  1008 + page_size = 1ULL << zbits;
  1009 + address &= ~(page_size - 1);
  1010 + for (end = physical + page_size; physical < end; physical += 0x1000) {
  1011 + ret = tlb_set_page(env, address, physical, prot,
  1012 + is_user, is_softmmu);
  1013 + address += 0x1000;
  1014 + }
  1015 + break;
  1016 +#if 0
  1017 + case 1:
  1018 + env->exception_index = EXCP_DFAULT;
  1019 + env->ipr[IPR_EXC_ADDR] = address;
  1020 + ret = 1;
  1021 + break;
  1022 + case 2:
  1023 + env->exception_index = EXCP_ACCESS_VIOLATION;
  1024 + env->ipr[IPR_EXC_ADDR] = address;
  1025 + ret = 1;
  1026 + break;
  1027 + case 3:
  1028 + env->exception_index = EXCP_FAULT_ON_READ;
  1029 + env->ipr[IPR_EXC_ADDR] = address;
  1030 + ret = 1;
  1031 + break;
  1032 + case 4:
  1033 + env->exception_index = EXCP_FAULT_ON_EXECUTE;
  1034 + env->ipr[IPR_EXC_ADDR] = address;
  1035 + ret = 1;
  1036 + case 5:
  1037 + env->exception_index = EXCP_FAULT_ON_WRITE;
  1038 + env->ipr[IPR_EXC_ADDR] = address;
  1039 + ret = 1;
  1040 +#endif
  1041 + default:
  1042 + /* Should never happen */
  1043 + env->exception_index = EXCP_MCHK;
  1044 + env->ipr[IPR_EXC_ADDR] = address;
  1045 + ret = 1;
  1046 + break;
  1047 + }
  1048 +
  1049 + return ret;
  1050 +}
  1051 +#endif
  1052 +
  1053 +#else /* !defined (CONFIG_USER_ONLY) */
  1054 +void pal_init (CPUState *env)
  1055 +{
  1056 +}
  1057 +
  1058 +void call_pal (CPUState *env, int palcode)
  1059 +{
  1060 + target_ulong ret;
  1061 +
  1062 + printf("%s: palcode %02x\n", __func__, palcode);
  1063 + if (logfile != NULL)
  1064 + fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
  1065 + switch (palcode) {
  1066 + case 0x83:
  1067 + /* CALLSYS */
  1068 + printf("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
  1069 + if (logfile != NULL)
  1070 + fprintf(logfile, "CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
  1071 + ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
  1072 + env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
  1073 + env->ir[IR_A5]);
  1074 + env->ir[IR_A3] = ret;
  1075 + if (ret > (target_ulong)(-515)) {
  1076 + env->ir[IR_V0] = 1;
  1077 + } else {
  1078 + env->ir[IR_V0] = 0;
  1079 + }
  1080 + break;
  1081 + case 0x9E:
  1082 + /* RDUNIQUE */
  1083 + env->ir[IR_V0] = env->unique;
  1084 + printf("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
  1085 + break;
  1086 + case 0x9F:
  1087 + /* WRUNIQUE */
  1088 + env->unique = env->ir[IR_A0];
  1089 + printf("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
  1090 + break;
  1091 + default:
  1092 + printf("%s: unhandled palcode %02x\n", __func__, palcode);
  1093 + if (logfile != NULL)
  1094 + fprintf(logfile, "%s: unhandled palcode %02x\n",
  1095 + __func__, palcode);
  1096 + exit(1);
  1097 + }
  1098 +}
  1099 +#endif
... ...