symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/alpha_palcode.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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_long ret;
       
  1063 
       
  1064     if (logfile != NULL)
       
  1065         fprintf(logfile, "%s: palcode %02x\n", __func__, palcode);
       
  1066     switch (palcode) {
       
  1067     case 0x83:
       
  1068         /* CALLSYS */
       
  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         if (ret >= 0) {
       
  1075             env->ir[IR_A3] = 0;
       
  1076             env->ir[IR_V0] = ret;
       
  1077         } else {
       
  1078             env->ir[IR_A3] = 1;
       
  1079             env->ir[IR_V0] = -ret;
       
  1080         }
       
  1081         break;
       
  1082     case 0x9E:
       
  1083         /* RDUNIQUE */
       
  1084         env->ir[IR_V0] = env->unique;
       
  1085         if (logfile != NULL)
       
  1086             fprintf(logfile, "RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
       
  1087         break;
       
  1088     case 0x9F:
       
  1089         /* WRUNIQUE */
       
  1090         env->unique = env->ir[IR_A0];
       
  1091         if (logfile != NULL)
       
  1092             fprintf(logfile, "WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
       
  1093         break;
       
  1094     default:
       
  1095         if (logfile != NULL)
       
  1096             fprintf(logfile, "%s: unhandled palcode %02x\n",
       
  1097                     __func__, palcode);
       
  1098         exit(1);
       
  1099     }
       
  1100 }
       
  1101 #endif