AlphaCPU.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  */
00025 
00322 #include "StdAfx.h"
00323 #include "AlphaCPU.h"
00324 #include "TraceEngine.h"
00325 #include "lockstep.h"
00326 #include "cpu_memory.h"
00327 #include "cpu_control.h"
00328 #include "cpu_arith.h"
00329 #include "cpu_logical.h"
00330 #include "cpu_bwx.h"
00331 #include "cpu_fp_memory.h"
00332 #include "cpu_fp_branch.h"
00333 #include "cpu_fp_operate.h"
00334 #include "cpu_misc.h"
00335 #include "cpu_vax.h"
00336 #include "cpu_mvi.h"
00337 #include "cpu_pal.h"
00338 #include "cpu_debug.h"
00339 
00340 #if !defined(HAVE_NEW_FP)
00341 #include "es40_float.h"
00342 #endif
00343 void CAlphaCPU::release_threads()
00344 {
00345   mySemaphore.set();
00346 }
00347 
00348 void CAlphaCPU::run()
00349 {
00350   try
00351   {
00352     mySemaphore.wait();
00353     for(;;)
00354     {
00355       if(StopThread)
00356         return;
00357       for(int i = 0; i < 1000000; i++)
00358         execute();
00359     }
00360   }
00361   catch(Poco::Exception & e)
00362   {
00363     printf("Exception in CPU thread: %s.\n", e.displayText().c_str());
00364 
00365     // Let the thread die...
00366   }
00367 }
00368 
00372 CAlphaCPU::CAlphaCPU(CConfigurator* cfg, CSystem* system) : CSystemComponent(cfg, system), mySemaphore(0, 1)
00373 { }
00374 
00378 void CAlphaCPU::init()
00379 {
00380   memset(&state, 0, sizeof(state));
00381 
00382   cpu_hz = myCfg->get_num_value("speed", true, 500000000);
00383 
00384   state.iProcNum = cSystem->RegisterCPU(this);
00385 
00386   icache_enabled = true;
00387   flush_icache();
00388   icache_enabled = myCfg->get_bool_value("icache", false);
00389 
00390   tbia(ACCESS_READ);
00391   tbia(ACCESS_EXEC);
00392 
00393   //  state.fpcr = U64(0x8ff0000000000000);
00394   state.fpen = true;
00395   state.i_ctl_other = U64(0x502086);
00396   state.smc = 1;
00397 
00398   // SROM imitation...
00399   add_tb(0, 0, U64(0xff61), ACCESS_READ);
00400 
00401 #if defined(IDB)
00402   bListing = false;
00403 #endif
00404   myThread = 0;
00405 
00406   cc_large = 0;
00407   prev_cc = 0;
00408   start_cc = 0;
00409   prev_time = 0;
00410   prev_icount = 0;
00411   start_icount = 0;
00412 
00413   cc_per_instruction = 70;
00414   ins_per_timer_int = cpu_hz / 1024;
00415   next_timer_int = state.iProcNum ? U64(0xFFFFFFFFFFFFFFFF) : ins_per_timer_int;  /* only on CPU 0 */
00416 
00417   state.r[22] = state.r[22 + 32] = state.iProcNum;
00418 
00419   printf("%s(%d): $Id: AlphaCPU.cpp,v 1.79 2008/03/26 19:06:49 iamcamiel Exp $\n",
00420          devid_string, state.iProcNum);
00421 }
00422 
00423 void CAlphaCPU::start_threads()
00424 {
00425   char  buffer[5];
00426   mySemaphore.tryWait(1);
00427   if(!myThread)
00428   {
00429     sprintf(buffer, "cpu%d", state.iProcNum);
00430     myThread = new Poco::Thread(buffer);
00431     printf(" %s", myThread->getName().c_str());
00432     StopThread = false;
00433     myThread->start(*this);
00434   }
00435 }
00436 
00437 void CAlphaCPU::stop_threads()
00438 {
00439   StopThread = true;
00440   if(myThread)
00441   {
00442     mySemaphore.set();
00443     printf(" %s", myThread->getName().c_str());
00444     myThread->join();
00445     delete myThread;
00446     myThread = 0;
00447   }
00448 
00449   mySemaphore.tryWait(1);
00450 }
00451 
00455 CAlphaCPU::~CAlphaCPU()
00456 {
00457   stop_threads();
00458 }
00459 
00460 #if defined(IDB)
00461 char    dbg_string[1000];
00462 #if !defined(LS_MASTER) && !defined(LS_SLAVE)
00463 char*   dbg_strptr;
00464 #endif
00465 
00474 void handle_debug_string(char* s)
00475 {
00476 #if defined(LS_SLAVE) || defined(LS_MASTER)
00477 
00478   //    lockstep_compare(s);
00479   * dbg_strptr++ = '\n';
00480   *dbg_strptr = '\0';
00481 #else
00482   if(*s)
00483     printf("%s\n", s);
00484 #endif
00485 }
00486 #endif
00487 #if defined(MIPS_ESTIMATE)
00488 
00489 // MIPS_INTERVAL must take longer than 1 second to execute
00490 // or estimate will generate a divide-by-zero error
00491 #define MIPS_INTERVAL 0xfffffff
00492 static time_t saved = 0;
00493 static u64    count;
00494 static double min_mips = 999999999999999.0;
00495 static double max_mips = 0.0;
00496 #endif
00497 
00503 void CAlphaCPU::check_state()
00504 {
00505   if(myThread && !myThread->isRunning())
00506     FAILURE(Thread, "CPU thread has died");
00507 
00508   // correct CPU timing loop...
00509   u64 icount = state.instruction_count;
00510   u64 cc = cc_large;
00511   u64 time = start_time.elapsed();
00512   s64 ce = cc_per_instruction;
00513 
00514   u64 cc_aim = time * cpu_hz / 1000000; // microsecond resolution
00515   u64 ce_aim = cc_aim / icount;
00516 
00517   s64 icount_lapse = icount - prev_icount;
00518   s64 cc_diff = cc_aim - cc;
00519   s64 ce_diff = (u64) ((float) cc_diff / (float) icount_lapse);
00520 
00521   s64 ce_new = ce_aim + ce_diff;
00522   if(ce_new < 0)
00523     ce_new = 0;
00524   if(ce_new > 200)
00525     ce_new = 200;
00526 
00527   if(ce_new != ce)
00528   {
00529 
00530     //    printf("                                     time %12" LL "d | prev %12" LL "d  \n",time,prev_time);
00531     //    printf("          count lapse %12" LL "d | curr %12" LL "d | prev %12" LL "d  \n",icount_lapse,icount,prev_icount);
00532     //    printf("cc %12" LL "d | aim %12" LL "d | diff %12" LL "d | prev %12" LL "d  \n",cc,cc_aim,cc_diff,prev_cc);
00533     //    printf("ce %12" LL "d | aim %12" LL "d | diff %12" LL "d | new  %12" LL "d  \n",ce,ce_aim,ce_diff,ce_new);
00534     //    printf("==========================================================================  \n");
00535     cc_per_instruction = ce_new;
00536   }
00537 
00538   prev_cc = cc;
00539   prev_icount = icount;
00540   prev_time = time;
00541   return;
00542 }
00543 
00553 void CAlphaCPU::execute()
00554 {
00555   u32 ins;
00556   int i;
00557   u64 phys_address;
00558   u64 temp_64;
00559   u64 temp_64_1;
00560   u64 temp_64_2;
00561   UFP ufp1;
00562   UFP ufp2;
00563 
00564   int opcode;
00565   int function;
00566 
00567 #if defined(MIPS_ESTIMATE)
00568 
00569   // Calculate simulated performance statistics
00570   if(++count >= MIPS_INTERVAL)
00571   {
00572     time_t  current;
00573     time(&current);
00574     if(saved > 0)
00575     {
00576       double  secs = difftime(current, saved);
00577       double  ips = MIPS_INTERVAL / secs;
00578       double  mips = ips / 1000000.0;
00579       if(max_mips < mips)
00580         max_mips = mips;
00581       if(min_mips > mips)
00582         min_mips = mips;
00583       printf("ES40 MIPS (%3.1f sec):: current: %5.3f, min: %5.3f, max: %5.3f\n",
00584              secs, mips, min_mips, max_mips);
00585     }
00586 
00587     saved = current;
00588     count = 0;
00589   }
00590 #endif
00591 #if defined(IDB)
00592   char*   funcname = 0;
00593   dbg_string[0] = '\0';
00594 #if !defined(LS_MASTER) && !defined(LS_SLAVE)
00595   dbg_strptr = dbg_string;
00596 #endif
00597 #endif
00598   state.current_pc = state.pc;
00599 
00600   // Service interrupts
00601   if(DO_ACTION)
00602   {
00603 
00604     // We're actually executing code. Cycle counter should be updated, interrupt and interrupt
00605     // timer status needs to be checked, and the next instruction should be fetched from the
00606     // instruction cache.
00607     // Increase the cycle counter if it is currently enabled.
00608     state.instruction_count++;
00609     cc_large += cc_per_instruction;
00610 
00611     if(cc_large > next_timer_int)
00612     {
00613       next_timer_int += ins_per_timer_int;
00614       cSystem->interrupt(-1, true);
00615     }
00616 
00617     if(state.cc_ena)
00618     {
00619       state.cc += cc_per_instruction;
00620     }
00621 
00622     if(state.check_timers)
00623     {
00624 
00625       // There are one or more active delayed irq_h interrupts. Go through the 6
00626       // irq_h timers, decrease them as needed, and set the interrupt if the timer
00627       // reaches 0.
00628       state.check_timers = false;
00629       for(int i = 0; i < 6; i++)
00630       {
00631         if(state.irq_h_timer[i])
00632         {
00633 
00634           // This timer is active. Decrease it, and check if it reached 0.
00635           state.irq_h_timer[i]--;
00636           if(state.irq_h_timer[i])
00637           {
00638 
00639             // The timer hasn't reached 0 yet; check on the timers again next clock tick.
00640             state.check_timers = true;
00641           }
00642           else
00643           {
00644 
00645             // The timer has reached 0. Set the interrupt status, and set the flag that we
00646             // need to check the interrupt status
00647             state.eir |= (U64(0x1) << i);
00648             state.check_int = true;
00649           }
00650         }
00651       }
00652     }
00653 
00654     if(state.check_int && !(state.pc & 1))
00655     {
00656 
00657       // One or more of the variables that affect interrupt status have changed, and we are not
00658       // currently inside PALmode. It is not certain that this means we hava an interrupt to
00659       // service, but we might have. This needs to be checked.
00660 
00661       /*      
00662       if (state.pal_vms) {
00663         // PALcode base is set to 0x8000; meaning OpenVMS PALcode is currently active. In this
00664         // case, our VMS PALcode replacement routines are valid, and should be used as it is
00665         // faster than using the original PALcode.
00666         
00667         if (state.eir & state.eien & 6)
00668           if (vmspal_ent_ext_int(state.eir&state.eien & 6))
00669             return;
00670 
00671         if (state.sir & state.sien & 0xfffc)
00672           if (vmspal_ent_sw_int(state.sir&state.sien))
00673             return;
00674 
00675         if (state.asten && (state.aster & state.astrr & ((1<<(state.cm+1))-1) ))
00676           if (vmspal_ent_ast_int(state.aster & state.astrr & ((1<<(state.cm+1))-1) ))
00677             return;
00678 
00679         if (state.sir & state.sien)
00680           if (vmspal_ent_sw_int(state.sir&state.sien))
00681             return;
00682       } else 
00683 */
00684       {
00685 
00686         // PALcode base is set to an unsupported value. We have no choice but to transfer control
00687         // to PALmode at the PALcode interrupt entry point.
00688         //        if (state.eir & 8)
00689         //        {
00690         //          printf("%s: IP interrupt received%s...\n",devid_string, (state.eien&8)?"(enabled)":"(masked)");
00691         //        }
00692         if((state.eien & state.eir) || (state.sien & state.sir) || (state.asten
00693          && (state.aster & state.astrr & ((1 << (state.cm + 1)) - 1))))
00694         {
00695           GO_PAL(INTERRUPT);
00696           return;
00697         }
00698       }
00699 
00700       // This point is reached only if there are no more active interrupts. We can safely set
00701       // check_int to false now to save time on the next CPU clock ticks.
00702       state.check_int = false;
00703     }
00704 
00705     // If profiling is enabled, increase the profiling counter for the current block of addresses.
00706 #if defined(PROFILE)
00707     PROFILE_DO(state.pc);
00708 #endif
00709 
00710     // Get the next instruction from the instruction cache.
00711     if(get_icache(state.pc, &ins))
00712       return;
00713   }           // if (DO_ACTION)
00714   else
00715   {
00716 
00717     // We're not really executing any code (DO_ACTION is false); that means that we're
00718     // in a debugging session, and just listing instructions at a particular address.
00719     // In this case, we treat the program counter as a physical address.
00720     ins = (u32) (cSystem->ReadMem(state.pc, 32, this));
00721   }
00722 
00723   // Increase the program counter. The current value is retained in state.current_pc.
00724   next_pc();
00725 
00726   // Clear "always zero" registers. The last instruction might have written something to
00727   // one of these registers.
00728   state.r[31] = 0;
00729   state.f[31] = 0;
00730 
00731   // Decode and dispatch opcode. This is kept very compact using the OP-macro defined in
00732   // cpu_debug.h. For the normal emulator, this simply calls the DO_<mnemonic> macro defined
00733   // in one of the other cpu_*.h files; but for the interactive debugger, it will also do
00734   // disassembly, where the second parameter to the macro (e.g. R12_R3) determines the
00735   // formatting applied to the operands. The macro ends with "return 0;".
00736 #if defined(IDB)
00737   last_instruction = ins;
00738 #endif
00739   opcode = ins >> 26;
00740   switch(opcode)
00741   {
00742   case 0x00:  // CALL_PAL
00743     function = ins & 0x1fffffff;
00744     OP(CALL_PAL, PAL);
00745 
00746   //    switch (function)
00747   //    {
00748   //      case 0x123401: OP_FNC(vmspal_int_read_ide, NOP);
00749   //      default: OP(CALL_PAL,PAL);
00750   //    }
00751   case 0x08:
00752     OP(LDA, MEM);
00753 
00754   case 0x09:
00755     OP(LDAH, MEM);
00756 
00757   case 0x0a:
00758     OP(LDBU, MEM);
00759 
00760   case 0x0b:
00761     OP(LDQ_U, MEM);
00762 
00763   case 0x0c:
00764     OP(LDWU, MEM);
00765 
00766   case 0x0d:
00767     OP(STW, MEM);
00768 
00769   case 0x0e:
00770     OP(STB, MEM);
00771 
00772   case 0x0f:
00773     OP(STQ_U, MEM);
00774 
00775   case 0x10:  // INTA* instructions
00776     function = (ins >> 5) & 0x7f;
00777     switch(function)
00778     {
00779     case 0x40:  OP(ADDL_V, R12_R3);
00780     case 0x00:  OP(ADDL, R12_R3);
00781     case 0x02:  OP(S4ADDL, R12_R3);
00782     case 0x49:  OP(SUBL_V, R12_R3);
00783     case 0x09:  OP(SUBL, R12_R3);
00784     case 0x0b:  OP(S4SUBL, R12_R3);
00785     case 0x0f:  OP(CMPBGE, R12_R3);
00786     case 0x12:  OP(S8ADDL, R12_R3);
00787     case 0x1b:  OP(S8SUBL, R12_R3);
00788     case 0x1d:  OP(CMPULT, R12_R3);
00789     case 0x60:  OP(ADDQ_V, R12_R3);
00790     case 0x20:  OP(ADDQ, R12_R3);
00791     case 0x22:  OP(S4ADDQ, R12_R3);
00792     case 0x69:  OP(SUBQ_V, R12_R3);
00793     case 0x29:  OP(SUBQ, R12_R3);
00794     case 0x2b:  OP(S4SUBQ, R12_R3);
00795     case 0x2d:  OP(CMPEQ, R12_R3);
00796     case 0x32:  OP(S8ADDQ, R12_R3);
00797     case 0x3b:  OP(S8SUBQ, R12_R3);
00798     case 0x3d:  OP(CMPULE, R12_R3);
00799     case 0x4d:  OP(CMPLT, R12_R3);
00800     case 0x6d:  OP(CMPLE, R12_R3);
00801     default:    UNKNOWN2;
00802     }
00803     break;
00804 
00805   case 0x11:  // INTL* instructions
00806     function = (ins >> 5) & 0x7f;
00807     switch(function)
00808     {
00809     case 0x00:  OP(AND, R12_R3);
00810     case 0x08:  OP(BIC, R12_R3);
00811     case 0x14:  OP(CMOVLBS, R12_R3);
00812     case 0x16:  OP(CMOVLBC, R12_R3);
00813     case 0x20:  OP(BIS, R12_R3);
00814     case 0x24:  OP(CMOVEQ, R12_R3);
00815     case 0x26:  OP(CMOVNE, R12_R3);
00816     case 0x28:  OP(ORNOT, R12_R3);
00817     case 0x40:  OP(XOR, R12_R3);
00818     case 0x44:  OP(CMOVLT, R12_R3);
00819     case 0x46:  OP(CMOVGE, R12_R3);
00820     case 0x48:  OP(EQV, R12_R3);
00821     case 0x61:  OP(AMASK, R2_R3);
00822     case 0x64:  OP(CMOVLE, R12_R3);
00823     case 0x66:  OP(CMOVGT, R12_R3);
00824     case 0x6c:  OP(IMPLVER, X_R3);
00825     default:    UNKNOWN2;
00826     }
00827     break;
00828 
00829   case 0x12:  // INTS* instructions
00830     function = (ins >> 5) & 0x7f;
00831     switch(function)
00832     {
00833     case 0x02:  OP(MSKBL, R12_R3);
00834     case 0x06:  OP(EXTBL, R12_R3);
00835     case 0x0b:  OP(INSBL, R12_R3);
00836     case 0x12:  OP(MSKWL, R12_R3);
00837     case 0x16:  OP(EXTWL, R12_R3);
00838     case 0x1b:  OP(INSWL, R12_R3);
00839     case 0x22:  OP(MSKLL, R12_R3);
00840     case 0x26:  OP(EXTLL, R12_R3);
00841     case 0x2b:  OP(INSLL, R12_R3);
00842     case 0x30:  OP(ZAP, R12_R3);
00843     case 0x31:  OP(ZAPNOT, R12_R3);
00844     case 0x32:  OP(MSKQL, R12_R3);
00845     case 0x34:  OP(SRL, R12_R3);
00846     case 0x36:  OP(EXTQL, R12_R3);
00847     case 0x39:  OP(SLL, R12_R3);
00848     case 0x3b:  OP(INSQL, R12_R3);
00849     case 0x3c:  OP(SRA, R12_R3);
00850     case 0x52:  OP(MSKWH, R12_R3);
00851     case 0x57:  OP(INSWH, R12_R3);
00852     case 0x5a:  OP(EXTWH, R12_R3);
00853     case 0x62:  OP(MSKLH, R12_R3);
00854     case 0x67:  OP(INSLH, R12_R3);
00855     case 0x6a:  OP(EXTLH, R12_R3);
00856     case 0x72:  OP(MSKQH, R12_R3);
00857     case 0x77:  OP(INSQH, R12_R3);
00858     case 0x7a:  OP(EXTQH, R12_R3);
00859     default:    UNKNOWN2;
00860     }
00861     break;
00862 
00863   case 0x13:  // INTM* instructions
00864     function = (ins >> 5) & 0x7f;
00865     switch(function)  // ignore /V for now
00866     {
00867     case 0x40:  OP(MULL_V, R12_R3);
00868     case 0x00:  OP(MULL, R12_R3);
00869     case 0x60:  OP(MULQ_V, R12_R3);
00870     case 0x20:  OP(MULQ, R12_R3);
00871     case 0x30:  OP(UMULH, R12_R3);
00872     default:    UNKNOWN2;
00873     }
00874     break;
00875 
00876   case 0x14:          // ITFP* instructions
00877     function = (ins >> 5) & 0x7ff;
00878     switch(function)
00879     {
00880     case 0x004:
00881       OP(ITOFS, R1_F3);
00882 
00883     case 0x00a:
00884     case 0x08a:
00885     case 0x10a:
00886     case 0x18a:
00887     case 0x40a:
00888     case 0x48a:
00889     case 0x50a:
00890     case 0x58a:
00891       OP(SQRTF, F2_F3);
00892 
00893     case 0x00b:
00894     case 0x04b:
00895     case 0x08b:
00896     case 0x0cb:
00897     case 0x10b:
00898     case 0x14b:
00899     case 0x18b:
00900     case 0x1cb:
00901     case 0x50b:
00902     case 0x54b:
00903     case 0x58b:
00904     case 0x5cb:
00905     case 0x70b:
00906     case 0x74b:
00907     case 0x78b:
00908     case 0x7cb:
00909       OP(SQRTS, F2_F3);
00910 
00911     case 0x014:
00912       OP(ITOFF, R1_F3);
00913 
00914     case 0x024:
00915       OP(ITOFT, R1_F3);
00916 
00917     case 0x02a:
00918     case 0x0aa:
00919     case 0x12a:
00920     case 0x1aa:
00921     case 0x42a:
00922     case 0x4aa:
00923     case 0x52a:
00924     case 0x5aa:
00925       OP(SQRTG, F2_F3);
00926 
00927     case 0x02b:
00928     case 0x06b:
00929     case 0x0ab:
00930     case 0x0eb:
00931     case 0x12b:
00932     case 0x16b:
00933     case 0x1ab:
00934     case 0x1eb:
00935     case 0x52b:
00936     case 0x56b:
00937     case 0x5ab:
00938     case 0x5eb:
00939     case 0x72b:
00940     case 0x76b:
00941     case 0x7ab:
00942     case 0x7eb:
00943       OP(SQRTT, F2_F3);
00944 
00945     default:
00946       UNKNOWN2;
00947     }
00948     break;
00949 
00950   case 0x15:          // FLTV* instructions
00951     function = (ins >> 5) & 0x7ff;
00952     switch(function)
00953     {
00954     case 0x0a5:
00955     case 0x4a5:
00956       OP(CMPGEQ, F12_F3);
00957 
00958     case 0x0a6:
00959     case 0x4a6:
00960       OP(CMPGLT, F12_F3);
00961 
00962     case 0x0a7:
00963     case 0x4a7:
00964       OP(CMPGLE, F12_F3);
00965 
00966     case 0x03c:
00967     case 0x0bc:
00968       OP(CVTQF, F2_F3);
00969 
00970     case 0x03e:
00971     case 0x0be:
00972       OP(CVTQG, F2_F3);
00973 
00974     default:
00975       if(function & 0x200)
00976       {
00977         UNKNOWN2;
00978       }
00979 
00980       switch(function & 0x7f)
00981       {
00982       case 0x000: OP(ADDF, F12_F3);
00983       case 0x001: OP(SUBF, F12_F3);
00984       case 0x002: OP(MULF, F12_F3);
00985       case 0x003: OP(DIVF, F12_F3);
00986       case 0x01e: OP(CVTDG, F2_F3);
00987       case 0x020: OP(ADDG, F12_F3);
00988       case 0x021: OP(SUBG, F12_F3);
00989       case 0x022: OP(MULG, F12_F3);
00990       case 0x023: OP(DIVG, F12_F3);
00991       case 0x02c: OP(CVTGF, F12_F3);
00992       case 0x02d: OP(CVTGD, F2_F3);
00993       case 0x02f: OP(CVTGQ, F2_F3);
00994       default:    UNKNOWN2;
00995       }
00996       break;
00997     }
00998     break;
00999 
01000   case 0x16:          // FLTI* instructions
01001     function = (ins >> 5) & 0x7ff;
01002     switch(function)
01003     {
01004     case 0x0a4:
01005     case 0x5a4:
01006       OP(CMPTUN, F12_F3);
01007 
01008     case 0x0a5:
01009     case 0x5a5:
01010       OP(CMPTEQ, F12_F3);
01011 
01012     case 0x0a6:
01013     case 0x5a6:
01014       OP(CMPTLT, F12_F3);
01015 
01016     case 0x0a7:
01017     case 0x5a7:
01018       OP(CMPTLE, F12_F3);
01019 
01020     case 0x2ac:
01021     case 0x6ac:
01022       OP(CVTST, F2_F3);
01023 
01024     default:
01025       if(((function & 0x600) == 0x200) || ((function & 0x500) == 0x400))
01026       {
01027         UNKNOWN2;
01028       }
01029 
01030       switch(function & 0x3f)
01031       {
01032       case 0x00:  OP(ADDS, F12_F3);
01033       case 0x01:  OP(SUBS, F12_F3);
01034       case 0x02:  OP(MULS, F12_F3);
01035       case 0x03:  OP(DIVS, F12_F3);
01036       case 0x20:  OP(ADDT, F12_F3);
01037       case 0x21:  OP(SUBT, F12_F3);
01038       case 0x22:  OP(MULT, F12_F3);
01039       case 0x23:  OP(DIVT, F12_F3);
01040       case 0x2c:  OP(CVTTS, F2_F3);
01041       case 0x2f:  OP(CVTTQ, F2_F3);
01042       case 0x3c:  if((function & 0x300) == 0x100){ UNKNOWN2; }OP(CVTQS, F2_F3);
01043       case 0x3e:  if((function & 0x300) == 0x100){ UNKNOWN2; }OP(CVTQT, F2_F3);
01044       default:    UNKNOWN2;
01045       }
01046       break;
01047     }
01048     break;
01049 
01050   case 0x17:          // FLTL* instructions
01051     function = (ins >> 5) & 0x7ff;
01052     switch(function)
01053     {
01054     case 0x010:
01055       OP(CVTLQ, F2_F3);
01056 
01057     case 0x020:
01058       OP(CPYS, F12_F3);
01059 
01060     case 0x021:
01061       OP(CPYSN, F12_F3);
01062 
01063     case 0x022:
01064       OP(CPYSE, F12_F3);
01065 
01066     case 0x024:
01067       OP(MT_FPCR, X_F1);
01068 
01069     case 0x025:
01070       OP(MF_FPCR, X_F1);
01071 
01072     case 0x02a:
01073       OP(FCMOVEQ, F12_F3);
01074 
01075     case 0x02b:
01076       OP(FCMOVNE, F12_F3);
01077 
01078     case 0x02c:
01079       OP(FCMOVLT, F12_F3);
01080 
01081     case 0x02d:
01082       OP(FCMOVGE, F12_F3);
01083 
01084     case 0x02e:
01085       OP(FCMOVLE, F12_F3);
01086 
01087     case 0x02f:
01088       OP(FCMOVGT, F12_F3);
01089 
01090     case 0x030:
01091     case 0x130:
01092     case 0x530:
01093       OP(CVTQL, F12_F3);
01094 
01095     default:
01096       UNKNOWN2;
01097     }
01098     break;
01099 
01100   case 0x18:          // MISC* instructions
01101     function = (ins & 0xffff);
01102     switch(function)
01103     {
01104     case 0x0000:  OP(TRAPB, NOP);
01105     case 0x0400:  OP(EXCB, NOP);
01106     case 0x4000:  OP(MB, NOP);
01107     case 0x4400:  OP(WMB, NOP);
01108     case 0x8000:  OP(FETCH, NOP);
01109     case 0xA000:  OP(FETCH_M, NOP);
01110     case 0xC000:  OP(RPCC, X_R1);
01111     case 0xE000:  OP(RC, X_R1);
01112     case 0xE800:  OP(ECB, NOP);
01113     case 0xF000:  OP(RS, X_R1);
01114     case 0xF800:  OP(WH64, NOP);
01115     case 0xFC00:  OP(WH64EN, NOP);
01116     default:      UNKNOWN2;
01117     }
01118     break;
01119 
01120   case 0x19:          // HW_MFPR
01121     function = (ins >> 8) & 0xff;
01122     OP(HW_MFPR, MFPR);
01123 
01124   case 0x1a:          // JSR* instructions
01125     OP(JMP, JMP);
01126 
01127   case 0x1b:          // PAL reserved - HW_LD
01128     function = (ins >> 12) & 0xf;
01129     if(function & 1)
01130     {
01131       OP(HW_LDQ, HW_LD);
01132     }
01133     else
01134     {
01135       OP(HW_LDL, HW_LD);
01136     }
01137 
01138   case 0x1c:          // FPTI* instructions
01139     function = (ins >> 5) & 0x7f;
01140     switch(function)
01141     {
01142     case 0x00:  OP(SEXTB, R2_R3);
01143     case 0x01:  OP(SEXTW, R2_R3);
01144     case 0x30:  OP(CTPOP, R2_R3);
01145     case 0x31:  OP(PERR, R2_R3);
01146     case 0x32:  OP(CTLZ, R2_R3);
01147     case 0x33:  OP(CTTZ, R2_R3);
01148     case 0x34:  OP(UNPKBW, R2_R3);
01149     case 0x35:  OP(UNPKBL, R2_R3);
01150     case 0x36:  OP(PKWB, R2_R3);
01151     case 0x37:  OP(PKLB, R2_R3);
01152     case 0x38:  OP(MINSB8, R12_R3);
01153     case 0x39:  OP(MINSW4, R12_R3);
01154     case 0x3a:  OP(MINUB8, R12_R3);
01155     case 0x3b:  OP(MINUW4, R12_R3);
01156     case 0x3c:  OP(MAXUB8, R12_R3);
01157     case 0x3d:  OP(MAXUW4, R12_R3);
01158     case 0x3e:  OP(MAXSB8, R12_R3);
01159     case 0x3f:  OP(MAXSW4, R12_R3);
01160     case 0x70:  OP(FTOIT, F1_R3);
01161     case 0x78:  OP(FTOIS, F1_R3);
01162     default:    UNKNOWN2;
01163     }
01164     break;
01165 
01166   case 0x1d:          // HW_MTPR
01167     function = (ins >> 8) & 0xff;
01168     OP(HW_MTPR, MTPR);
01169 
01170   case 0x1e:
01171     OP(HW_RET, RET);
01172 
01173   case 0x1f:          // HW_ST
01174     function = (ins >> 12) & 0xf;
01175     if(function & 1)
01176     {
01177       OP(HW_STQ, HW_ST);
01178     }
01179     else
01180     {
01181       OP(HW_STL, HW_ST);
01182     }
01183 
01184   case 0x20:
01185     OP(LDF, FMEM);
01186 
01187   case 0x21:
01188     OP(LDG, FMEM);
01189 
01190   case 0x22:
01191     OP(LDS, FMEM);
01192 
01193   case 0x23:
01194     OP(LDT, FMEM);
01195 
01196   case 0x24:
01197     OP(STF, FMEM);
01198 
01199   case 0x25:
01200     OP(STG, FMEM);
01201 
01202   case 0x26:
01203     OP(STS, FMEM);
01204 
01205   case 0x27:
01206     OP(STT, FMEM);
01207 
01208   case 0x28:
01209     OP(LDL, MEM);
01210 
01211   case 0x29:
01212     OP(LDQ, MEM);
01213 
01214   case 0x2a:
01215     OP(LDL_L, MEM);
01216 
01217   case 0x2b:
01218     OP(LDQ_L, MEM);
01219 
01220   case 0x2c:
01221     OP(STL, MEM);
01222 
01223   case 0x2d:
01224     OP(STQ, MEM);
01225 
01226   case 0x2e:
01227     OP(STL_C, MEM);
01228 
01229   case 0x2f:
01230     OP(STQ_C, MEM);
01231 
01232   case 0x30:
01233     OP(BR, BR);
01234 
01235   case 0x31:
01236     OP(FBEQ, FCOND);
01237 
01238   case 0x32:
01239     OP(FBLT, FCOND);
01240 
01241   case 0x33:
01242     OP(FBLE, FCOND);
01243 
01244   case 0x34:
01245     OP(BSR, BSR);
01246 
01247   case 0x35:
01248     OP(FBNE, FCOND);
01249 
01250   case 0x36:
01251     OP(FBGE, FCOND);
01252 
01253   case 0x37:
01254     OP(FBGT, FCOND);
01255 
01256   case 0x38:
01257     OP(BLBC, COND);
01258 
01259   case 0x39:
01260     OP(BEQ, COND);
01261 
01262   case 0x3a:
01263     OP(BLT, COND);
01264 
01265   case 0x3b:
01266     OP(BLE, COND);
01267 
01268   case 0x3c:
01269     OP(BLBS, COND);
01270 
01271   case 0x3d:
01272     OP(BNE, COND);
01273 
01274   case 0x3e:
01275     OP(BGE, COND);
01276 
01277   case 0x3f:
01278     OP(BGT, COND);
01279 
01280   default:
01281     UNKNOWN1;
01282   }
01283 
01284   return;
01285 }
01286 
01287 #if defined(IDB)
01288 
01296 void CAlphaCPU::listing(u64 from, u64 to)
01297 {
01298   listing(from, to, 0);
01299 }
01300 
01309 void CAlphaCPU::listing(u64 from, u64 to, u64 mark)
01310 {
01311   printf("%%CPU-I-LISTNG: Listing from %016"LL "x to %016"LL "x\n", from, to);
01312 
01313   u64   iSavedPC;
01314   bool  bSavedDebug;
01315   iSavedPC = state.pc;
01316   bSavedDebug = bDisassemble;
01317   bDisassemble = true;
01318   bListing = true;
01319   for(state.pc = from; state.pc <= to;)
01320   {
01321     execute();
01322     if(state.pc == mark)
01323       printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
01324   }
01325 
01326   bListing = false;
01327   state.pc = iSavedPC;
01328   bDisassemble = bSavedDebug;
01329 }
01330 
01331 u64 CAlphaCPU::get_instruction_count()
01332 {
01333   return state.instruction_count;
01334 }
01335 #endif
01336 static u32  cpu_magic1 = 0x2126468C;
01337 static u32  cpu_magic2 = 0xC8646212;
01338 
01342 int CAlphaCPU::SaveState(FILE* f)
01343 {
01344   long  ss = sizeof(state);
01345 
01346   fwrite(&cpu_magic1, sizeof(u32), 1, f);
01347   fwrite(&ss, sizeof(long), 1, f);
01348   fwrite(&state, sizeof(state), 1, f);
01349   fwrite(&cpu_magic2, sizeof(u32), 1, f);
01350   printf("%s: %d bytes saved.\n", devid_string, (int) ss);
01351   return 0;
01352 }
01353 
01357 int CAlphaCPU::RestoreState(FILE* f)
01358 {
01359   long    ss;
01360   u32     m1;
01361   u32     m2;
01362   size_t  r;
01363 
01364   r = fread(&m1, sizeof(u32), 1, f);
01365   if(r != 1)
01366   {
01367     printf("%s: unexpected end of file!\n", devid_string);
01368     return -1;
01369   }
01370 
01371   if(m1 != cpu_magic1)
01372   {
01373     printf("%s: MAGIC 1 does not match!\n", devid_string);
01374     return -1;
01375   }
01376 
01377   fread(&ss, sizeof(long), 1, f);
01378   if(r != 1)
01379   {
01380     printf("%s: unexpected end of file!\n", devid_string);
01381     return -1;
01382   }
01383 
01384   if(ss != sizeof(state))
01385   {
01386     printf("%s: STRUCT SIZE does not match!\n", devid_string);
01387     return -1;
01388   }
01389 
01390   fread(&state, sizeof(state), 1, f);
01391   if(r != 1)
01392   {
01393     printf("%s: unexpected end of file!\n", devid_string);
01394     return -1;
01395   }
01396 
01397   r = fread(&m2, sizeof(u32), 1, f);
01398   if(r != 1)
01399   {
01400     printf("%s: unexpected end of file!\n", devid_string);
01401     return -1;
01402   }
01403 
01404   if(m2 != cpu_magic2)
01405   {
01406     printf("%s: MAGIC 1 does not match!\n", devid_string);
01407     return -1;
01408   }
01409 
01410   printf("%s: %d bytes restored.\n", devid_string, (int) ss);
01411   return 0;
01412 }
01413 
01414 /***************************************************************************/
01415 
01421 //\{
01422 
01433 int CAlphaCPU::FindTBEntry(u64 virt, int flags)
01434 {
01435 
01436   // Use ITB (tb[1]) if ACCESS_EXEC is set, otherwise use DTB (tb[0])
01437   int t = (flags & ACCESS_EXEC) ? 1 : 0;
01438   int asn = (flags & ACCESS_EXEC) ? state.asn : state.asn0;
01439 
01440   int rw = (flags & ACCESS_WRITE) ? 1 : 0;
01441 
01442   // Try last match first; this is a good quess, especially in the ITB
01443   int i = state.last_found_tb[t][rw];
01444   if(state.tb[t][i].valid
01445    && !((state.tb[t][i].virt ^ virt) & state.tb[t][i].match_mask)
01446    && (state.tb[t][i].asm_bit || (state.tb[t][i].asn == asn))) return i;
01447 
01448   // Otherwise, loop through the TB entries to find a match.
01449   for(i = 0; i < TB_ENTRIES; i++)
01450   {
01451     if(state.tb[t][i].valid
01452      && !((state.tb[t][i].virt ^ virt) & state.tb[t][i].match_mask)
01453      && (state.tb[t][i].asm_bit || (state.tb[t][i].asn == asn)))
01454     {
01455       state.last_found_tb[t][rw] = i;
01456       return i;
01457     }
01458   }
01459 
01460   return -1;
01461 }
01462 
01505 int CAlphaCPU::virt2phys(u64 virt, u64* phys, int flags, bool* asm_bit, u32 ins)
01506 {
01507   int   t = (flags & ACCESS_EXEC) ? 1 : 0;
01508   int   i;
01509   int   res;
01510 
01511   int   spe = (flags & ACCESS_EXEC) ? state.i_ctl_spe : state.m_ctl_spe;
01512   int   asn = (flags & ACCESS_EXEC) ? state.asn : state.asn0;
01513   int   cm = (flags & ALT) ? state.alt_cm : state.cm;
01514   bool  forreal = !(flags & FAKE);
01515 
01516 #if defined IDB
01517   if(bListing)
01518   {
01519     *phys = virt;
01520     return 0;
01521   }
01522 #endif
01523 #if defined(DEBUG_TB)
01524   if(forreal)
01525 #if defined(IDB)
01526     if(bTB_Debug)
01527 #endif
01528       printf("TB %"LL "x,%x: ", virt, flags);
01529 #endif
01530 
01531   // try superpage first.
01532   if(spe && !cm)
01533   {
01534 #if defined(DEBUG_TB)
01535     if(forreal)
01536 #if defined(IDB)
01537       if(bTB_Debug)
01538 #endif
01539         printf("try spe...");
01540 #endif
01541 
01542     // HRM 5.3.9: SPE[2], when set, enables superpage mapping when VA[47:46] = 2.
01543     // In this mode, VA[43:13] are mapped directly to PA[43:13] and VA[45:44] are
01544     // ignored.
01545     if(((virt & SPE_2_MASK) == SPE_2_MATCH) && (spe & 4))
01546     {
01547       *phys = virt & SPE_2_MAP;
01548       if(asm_bit)
01549         *asm_bit = false;
01550 #if defined(DEBUG_TB)
01551       if(forreal)
01552 #if defined(IDB)
01553         if(bTB_Debug)
01554 #endif
01555           printf("SPE\n");
01556 #endif
01557       return 0;
01558     }
01559 
01560     // SPE[1], when set, enables superpage mapping when VA[47:41] = 7E. In
01561     // this mode, VA[40:13] are mapped directly to PA[40:13] and PA[43:41] are
01562     // copies of PA[40] (sign extension).
01563     else if(((virt & SPE_1_MASK) == SPE_1_MATCH) && (spe & 2))
01564     {
01565       *phys = (virt & SPE_1_MAP) | ((virt & SPE_1_TEST) ? SPE_1_ADD : 0);
01566       if(asm_bit)
01567         *asm_bit = false;
01568 #if defined(DEBUG_TB)
01569       if(forreal)
01570 #if defined(IDB)
01571         if(bTB_Debug)
01572 #endif
01573           printf("SPE\n");
01574 #endif
01575       return 0;
01576     }
01577 
01578     // SPE[0], when set, enables superpage mapping when VA[47:30] = 3FFFE.
01579     // In this mode, VA[29:13] are mapped directly to PA[29:13] and PA[43:30] are
01580     // cleared.
01581     else if(((virt & SPE_0_MASK) == SPE_0_MATCH) && (spe & 4))
01582     {
01583       *phys = virt & SPE_0_MAP;
01584       if(asm_bit)
01585         *asm_bit = false;
01586 #if defined(DEBUG_TB)
01587       if(forreal)
01588 #if defined(IDB)
01589         if(bTB_Debug)
01590 #endif
01591           printf("SPE\n");
01592 #endif
01593       return 0;
01594     }
01595   }
01596 
01597   // try to find it in the translation buffer
01598   i = FindTBEntry(virt, flags);
01599 
01600   if(i < 0)       // not found, either trap to PALcode, or try to load the TB entry and try again.
01601   {
01602     if(!forreal)  // debugger-lookup of the address
01603       return -1;  // report failure, and don't look any further
01604     if(!state.pal_vms)  // unknown PALcode
01605     {
01606 
01607       // transfer execution to PALcode
01608       state.exc_addr = state.current_pc;
01609       if(flags & VPTE)
01610       {
01611         state.fault_va = virt;
01612         state.exc_sum = (u64) REG_1 << 8;
01613         set_pc(state.pal_base + DTBM_DOUBLE_3 + 1);
01614       }
01615       else if(flags & ACCESS_EXEC)
01616       {
01617         set_pc(state.pal_base + ITB_MISS + 1);
01618       }
01619       else
01620       {
01621         state.fault_va = virt;
01622         state.exc_sum = (u64) REG_1 << 8;
01623 
01624         u32 opcode = I_GETOP(ins);
01625         state.mm_stat =
01626           (
01627             (opcode == 0x1b || opcode == 0x1f) ? opcode -
01628             0x18 : opcode
01629           ) <<
01630           4 |
01631           (flags & ACCESS_WRITE);
01632         set_pc(state.pal_base + DTBM_SINGLE + 1);
01633       }
01634 
01635       return -1;
01636     }
01637     else  // VMS PALcode
01638     {
01639       if(flags & RECUR) // we already tried this
01640       {
01641         printf("Translationbuffer RECUR lookup failed!\n");
01642         return -1;
01643       }
01644 
01645       state.exc_addr = state.current_pc;
01646       if(flags & VPTE)
01647       {
01648 
01649         // try to handle the double miss. If this needs to transfer control
01650         // to the OS, it will return non-zero value.
01651         if(res = vmspal_ent_dtbm_double_3(flags))
01652           return res;
01653 
01654         // Double miss succesfully handled. Try to get the physical address again.
01655         return virt2phys(virt, phys, flags | RECUR, asm_bit, ins);
01656       }
01657       else if(flags & ACCESS_EXEC)
01658       {
01659 
01660         // try to handle the ITB miss. If this needs to transfer control
01661         // to the OS, it will return non-zero value.
01662         if(res = vmspal_ent_itbm(flags))
01663           return res;
01664 
01665         // ITB miss succesfully handled. Try to get the physical address again.
01666         return virt2phys(virt, phys, flags | RECUR, asm_bit, ins);
01667       }
01668       else
01669       {
01670         state.fault_va = virt;
01671         state.exc_sum = (u64) REG_1 << 8;
01672 
01673         u32 opcode = I_GETOP(ins);
01674         state.mm_stat =
01675           (
01676             (opcode == 0x1b || opcode == 0x1f) ? opcode -
01677             0x18 : opcode
01678           ) <<
01679           4 |
01680           (flags & ACCESS_WRITE);
01681 
01682         // try to handle the single miss. If this needs to transfer control
01683         // to the OS, it will return non-zero value.
01684         if(res = vmspal_ent_dtbm_single(flags))
01685           return res;
01686 
01687         // Single miss succesfully handled. Try to get the physical address again.
01688         return virt2phys(virt, phys, flags | RECUR, asm_bit, ins);
01689       }
01690     }
01691   }
01692 
01693   // If we get here, the number of the matching TB entry is in i.
01694 #if defined(DEBUG_TB)
01695   else
01696   {
01697     if(forreal)
01698 #if defined(IDB)
01699       if(bTB_Debug)
01700 #endif
01701         printf("entry %d - ", i);
01702   }
01703 #endif
01704   if(!(flags & NO_CHECK))
01705   {
01706 
01707     // check if requested access is allowed
01708     if(!state.tb[t][i].access[flags & ACCESS_WRITE][cm])
01709     {
01710 #if defined(DEBUG_TB)
01711       if(forreal)
01712 #if defined(IDB)
01713         if(bTB_Debug)
01714 #endif
01715           printf("acv\n");
01716 #endif
01717       if(flags & ACCESS_EXEC)
01718       {
01719 
01720         // handle I-stream access violation
01721         state.exc_addr = state.current_pc;
01722         state.exc_sum = 0;
01723         if(state.pal_vms)
01724         {
01725           if(res = vmspal_ent_iacv(flags))
01726             return res;
01727         }
01728         else
01729         {
01730           set_pc(state.pal_base + IACV + 1);
01731           return -1;
01732         }
01733       }
01734       else
01735       {
01736 
01737         // Handle D-stream access violation
01738         state.exc_addr = state.current_pc;
01739         state.fault_va = virt;
01740         state.exc_sum = (u64) REG_1 << 8;
01741 
01742         u32 opcode = I_GETOP(ins);
01743         state.mm_stat =
01744           (
01745             (opcode == 0x1b || opcode == 0x1f) ? opcode -
01746             0x18 : opcode
01747           ) <<
01748           4 |
01749           (flags & ACCESS_WRITE) |
01750           2;
01751         if(state.pal_vms)
01752         {
01753           if(res = vmspal_ent_dfault(flags))
01754             return res;
01755         }
01756         else
01757         {
01758           set_pc(state.pal_base + DFAULT + 1);
01759           return -1;
01760         }
01761       }
01762     }
01763 
01764     // check if requested access doesn't fault
01765     if(state.tb[t][i].fault[flags & ACCESS_MODE])
01766     {
01767 #if defined(DEBUG_TB)
01768       if(forreal)
01769 #if defined(IDB)
01770         if(bTB_Debug)
01771 #endif
01772           printf("fault\n");
01773 #endif
01774       if(flags & ACCESS_EXEC)
01775       {
01776 
01777         // handle I-stream access fault
01778         state.exc_addr = state.current_pc;
01779         state.exc_sum = 0;
01780         if(state.pal_vms)
01781         {
01782           if(res = vmspal_ent_iacv(flags))
01783             return res;
01784         }
01785         else
01786         {
01787           set_pc(state.pal_base + IACV + 1);
01788           return -1;
01789         }
01790       }
01791       else
01792       {
01793 
01794         // handle D-stream access fault
01795         state.exc_addr = state.current_pc;
01796         state.fault_va = virt;
01797         state.exc_sum = (u64) REG_1 << 8;
01798 
01799         u32 opcode = I_GETOP(ins);
01800         state.mm_stat =
01801           (
01802             (opcode == 0x1b || opcode == 0x1f) ? opcode -
01803             0x18 : opcode
01804           ) <<
01805           4 |
01806           (flags & ACCESS_WRITE) |
01807           ((flags & ACCESS_WRITE) ? 8 : 4);
01808         if(state.pal_vms)
01809         {
01810           if(res = vmspal_ent_dfault(flags))
01811             return res;
01812         }
01813         else
01814         {
01815           set_pc(state.pal_base + DFAULT + 1);
01816           return -1;
01817         }
01818       }
01819     }
01820   }
01821 
01822   // No access violations or faults
01823   // Return the converted address
01824   *phys = state.tb[t][i].phys | (virt & state.tb[t][i].keep_mask);
01825   if(asm_bit)
01826     *asm_bit = state.tb[t][i].asm_bit ? true : false;
01827 
01828 #if defined(DEBUG_TB)
01829   if(forreal)
01830 #if defined(IDB)
01831     if(bTB_Debug)
01832 #endif
01833       printf("phys: %"LL "x - OK\n", *phys);
01834 #endif
01835   return 0;
01836 }
01837 
01838 #define GH_0_MATCH  U64(0x000007ffffffe000) /* <42:13> */
01839 #define GH_0_PHYS   U64(0x00000fffffffe000) /* <43:13> */
01840 #define GH_0_KEEP   U64(0x0000000000001fff) /* <12:0>  */
01841 
01842 #define GH_1_MATCH  U64(0x000007ffffff0000)
01843 #define GH_1_PHYS   U64(0x00000fffffff0000)
01844 #define GH_1_KEEP   U64(0x000000000000ffff)
01845 #define GH_2_MATCH  U64(0x000007fffff80000)
01846 #define GH_2_PHYS   U64(0x00000ffffff80000)
01847 #define GH_2_KEEP   U64(0x000000000007ffff)
01848 #define GH_3_MATCH  U64(0x000007ffffc00000)
01849 #define GH_3_PHYS   U64(0x00000fffffc00000)
01850 #define GH_3_KEEP   U64(0x00000000003fffff)
01851 
01861 void CAlphaCPU::add_tb(u64 virt, u64 pte_phys, u64 pte_flags, int flags)
01862 {
01863   int t = (flags & ACCESS_EXEC) ? 1 : 0;
01864   int rw = (flags & ACCESS_WRITE) ? 1 : 0;
01865   u64 match_mask = 0;
01866   u64 keep_mask = 0;
01867   u64 phys_mask = 0;
01868   int i;
01869   int asn = (flags & ACCESS_EXEC) ? state.asn : state.asn0;
01870 
01871   switch(pte_flags & 0x60)  // granularity hint
01872   {
01873   case 0:
01874     match_mask = GH_0_MATCH;
01875     phys_mask = GH_0_PHYS;
01876     keep_mask = GH_0_KEEP;
01877     break;
01878 
01879   case 0x20:
01880     match_mask = GH_1_MATCH;
01881     phys_mask = GH_1_PHYS;
01882     keep_mask = GH_1_KEEP;
01883     break;
01884 
01885   case 0x40:
01886     match_mask = GH_2_MATCH;
01887     phys_mask = GH_2_PHYS;
01888     keep_mask = GH_2_KEEP;
01889     break;
01890 
01891   case 0x60:
01892     match_mask = GH_3_MATCH;
01893     phys_mask = GH_3_PHYS;
01894     keep_mask = GH_3_KEEP;
01895     break;
01896   }
01897 
01898   i = FindTBEntry(virt, flags);
01899 
01900   if(i < 0)
01901   {
01902     i = state.next_tb[t];
01903     state.next_tb[t]++;
01904     if(state.next_tb[t] == TB_ENTRIES)
01905       state.next_tb[t] = 0;
01906   }
01907 
01908   state.tb[t][i].match_mask = match_mask;
01909   state.tb[t][i].keep_mask = keep_mask;
01910   state.tb[t][i].virt = virt & match_mask;
01911   state.tb[t][i].phys = pte_phys & phys_mask;
01912   state.tb[t][i].fault[0] = (int) pte_flags & 2;
01913   state.tb[t][i].fault[1] = (int) pte_flags & 4;
01914   state.tb[t][i].fault[2] = (int) pte_flags & 8;
01915   state.tb[t][i].access[0][0] = (int) pte_flags & 0x100;
01916   state.tb[t][i].access[1][0] = (int) pte_flags & 0x1000;
01917   state.tb[t][i].access[0][1] = (int) pte_flags & 0x200;
01918   state.tb[t][i].access[1][1] = (int) pte_flags & 0x2000;
01919   state.tb[t][i].access[0][2] = (int) pte_flags & 0x400;
01920   state.tb[t][i].access[1][2] = (int) pte_flags & 0x4000;
01921   state.tb[t][i].access[0][3] = (int) pte_flags & 0x800;
01922   state.tb[t][i].access[1][3] = (int) pte_flags & 0x8000;
01923   state.tb[t][i].asm_bit = (int) pte_flags & 0x10;
01924   state.tb[t][i].asn = asn;
01925   state.tb[t][i].valid = true;
01926   state.last_found_tb[t][rw] = i;
01927 
01928 #if defined(DEBUG_TB_)
01929 #if defined(IDB)
01930   if(bTB_Debug)
01931 #endif
01932   {
01933     printf("Add TB---------------------------------------\n");
01934     printf("Map VIRT    %016"LL "x\n", state.tb[i].virt);
01935     printf("Matching    %016"LL "x\n", state.tb[i].match_mask);
01936     printf("And keeping %016"LL "x\n", state.tb[i].keep_mask);
01937     printf("To PHYS     %016"LL "x\n", state.tb[i].phys);
01938     printf("Read : %c%c%c%c %c\n", state.tb[i].access[0][0] ? 'K' : '-',
01939            state.tb[i].access[0][1] ? 'E' : '-',
01940            state.tb[i].access[0][2] ? 'S' : '-',
01941            state.tb[i].access[0][3] ? 'U' : '-', state.tb[i].fault[0] ? 'F' : '-');
01942     printf("Write: %c%c%c%c %c\n", state.tb[i].access[1][0] ? 'K' : '-',
01943            state.tb[i].access[1][1] ? 'E' : '-',
01944            state.tb[i].access[1][2] ? 'S' : '-',
01945            state.tb[i].access[1][3] ? 'U' : '-', state.tb[i].fault[1] ? 'F' : '-');
01946     printf("Exec : %c%c%c%c %c\n", state.tb[i].access[1][0] ? 'K' : '-',
01947            state.tb[i].access[1][1] ? 'E' : '-',
01948            state.tb[i].access[1][2] ? 'S' : '-',
01949            state.tb[i].access[1][3] ? 'U' : '-', state.tb[i].fault[1] ? 'F' : '-');
01950   }
01951 #endif
01952 }
01953 
01974 void CAlphaCPU::add_tb_d(u64 virt, u64 pte)
01975 {
01976   add_tb(virt, pte >> (32 - 13), pte, ACCESS_READ);
01977 }
01978 
01999 void CAlphaCPU::add_tb_i(u64 virt, u64 pte)
02000 {
02001   add_tb(virt, pte, pte & 0xf70, ACCESS_EXEC);
02002 }
02003 
02011 void CAlphaCPU::tbia(int flags)
02012 {
02013   int t = (flags & ACCESS_EXEC) ? 1 : 0;
02014   int i;
02015   for(i = 0; i < TB_ENTRIES; i++)
02016     state.tb[t][i].valid = false;
02017   state.last_found_tb[t][0] = 0;
02018   state.last_found_tb[t][1] = 0;
02019   state.next_tb[t] = 0;
02020 }
02021 
02030 void CAlphaCPU::tbiap(int flags)
02031 {
02032   int t = (flags & ACCESS_EXEC) ? 1 : 0;
02033   int i;
02034   for(i = 0; i < TB_ENTRIES; i++)
02035     if(!state.tb[t][i].asm_bit)
02036       state.tb[t][i].valid = false;
02037 }
02038 
02045 void CAlphaCPU::tbis(u64 virt, int flags)
02046 {
02047   int t = (flags & ACCESS_EXEC) ? 1 : 0;
02048   int i = FindTBEntry(virt, flags);
02049   if(i >= 0)
02050     state.tb[t][i].valid = false;
02051 }
02052 
02053 //\}
02054 
02060 void CAlphaCPU::enable_icache()
02061 {
02062   icache_enabled = true;
02063 }
02064 
02068 void CAlphaCPU::restore_icache()
02069 {
02070   bool  newval;
02071 
02072   newval = myCfg->get_bool_value("icache", false);
02073 
02074   if(!newval)
02075     flush_icache();
02076 
02077   icache_enabled = newval;
02078 }
02079 
02080 #if defined(IDB)
02081 const char*   PAL_NAME[] = {
02082   "HALT", "CFLUSH", "DRAINA", "LDQP", "STQP", "SWPCTX", "MFPR_ASN",
02083   "MTPR_ASTEN",
02084   "MTPR_ASTSR", "CSERVE", "SWPPAL", "MFPR_FEN", "MTPR_FEN", "MTPR_IPIR",
02085   "MFPR_IPL", "MTPR_IPL",
02086   "MFPR_MCES", "MTPR_MCES", "MFPR_PCBB", "MFPR_PRBR", "MTPR_PRBR",
02087   "MFPR_PTBR", "MFPR_SCBB", "MTPR_SCBB",
02088   "MTPR_SIRR", "MFPR_SISR", "MFPR_TBCHK", "MTPR_TBIA", "MTPR_TBIAP",
02089   "MTPR_TBIS", "MFPR_ESP", "MTPR_ESP",
02090   "MFPR_SSP", "MTPR_SSP", "MFPR_USP", "MTPR_USP", "MTPR_TBISD", "MTPR_TBISI",
02091   "MFPR_ASTEN", "MFPR_ASTSR",
02092   "28", "MFPR_VPTB", "MTPR_VPTB", "MTPR_PERFMON", "2C", "2D", "MTPR_DATFX",
02093   "2F",
02094   "30", "31", "32", "33", "34", "35", "36", "37",
02095   "38", "39", "3A", "3B", "3C", "3D", "WTINT", "MFPR_WHAMI",
02096   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
02097   "-",
02098   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
02099   "-",
02100   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
02101   "-",
02102   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
02103   "-",
02104   "BPT", "BUGCHK", "CHME", "CHMK", "CHMS", "CHMU", "IMB", "INSQHIL",
02105   "INSQTIL", "INSQHIQ", "INSQTIQ", "INSQUEL", "INSQUEQ", "INSQUEL/D",
02106   "INSQUEQ/D", "PROBER",
02107   "PROBEW", "RD_PS", "REI", "REMQHIL", "REMQTIL", "REMQHIQ", "REMQTIQ",
02108   "REMQUEL",
02109   "REMQUEQ", "REMQUEL/D", "REMQUEQ/D", "SWASTEN", "WR_PS_SW", "RSCC",
02110   "READ_UNQ", "WRITE_UNQ",
02111   "AMOVRR", "AMOVRM", "INSQHILR", "INSQTILR", "INSQHIQR", "INSQTIQR",
02112   "REMQHILR", "REMQTILR",
02113   "REMQHIQR", "REMQTIQR", "GENTRAP", "AB", "AC", "AD", "CLRFEN", "AF",
02114   "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB",
02115   "BC", "BD", "BE", "BF"
02116 };
02117 
02118 const char*   IPR_NAME[] = {
02119   "ITB_TAG", "ITB_PTE", "ITB_IAP", "ITB_IA", "ITB_IS", "PMPC", "EXC_ADDR",
02120   "IVA_FORM",
02121   "IER_CM", "CM", "IER", "IER_CM", "SIRR", "ISUM", "HW_INT_CLR", "EXC_SUM",
02122   "PAL_BASE", "I_CTL", "IC_FLUSH_ASM", "IC_FLUSH", "PCTR_CTL", "CLR_MAP",
02123   "I_STAT", "SLEEP",
02124   "?0001.1000?", "?0001.1001?", "?0001.1010?", "?0001.1011?", "?0001.1100?",
02125   "?0001.1101?", "?0001.1110?", "?0001.1111?",
02126   "DTB_TAG0", "DTB_PTE0", "?0010.0010?", "?0010.0011?", "DTB_IS0", "DTB_ASN0",
02127   "DTB_ALTMODE", "MM_STAT",
02128   "M_CTL", "DC_CTL", "DC_STAT", "C_DATA", "C_SHFT", "M_FIX", "?0010.1110?",
02129   "?0010.1111?",
02130   "?0011.0000?", "?0011.0001?", "?0011.0010?", "?0011.0011?", "?0011.0100?",
02131   "?0010.0101?", "?0010.0110?", "?0010.0111?",
02132   "?0011.1000?", "?0011.1001?", "?0011.1010?", "?0011.1011?", "?0011.1100?",
02133   "?0010.1101?", "?0010.1110?", "?0010.1111?",
02134   "PCTX.00000", "PCTX.00001", "PCTX.00010", "PCTX.00011", "PCTX.00100",
02135   "PCTX.00101", "PCTX.00110", "PCTX.00111",
02136   "PCTX.01000", "PCTX.01001", "PCTX.01010", "PCTX.01011", "PCTX.01100",
02137   "PCTX.01101", "PCTX.01110", "PCTX.01111",
02138   "PCTX.10000", "PCTX.10001", "PCTX.10010", "PCTX.10011", "PCTX.10100",
02139   "PCTX.10101", "PCTX.10110", "PCTX.10111",
02140   "PCTX.11000", "PCTX.11001", "PCTX.11010", "PCTX.11011", "PCTX.11100",
02141   "PCTX.11101", "PCTX.11110", "PCTX.11111",
02142   "PCTX.00000", "PCTX.00001", "PCTX.00010", "PCTX.00011", "PCTX.00100",
02143   "PCTX.00101", "PCTX.00110", "PCTX.00111",
02144   "PCTX.01000", "PCTX.01001", "PCTX.01010", "PCTX.01011", "PCTX.01100",
02145   "PCTX.01101", "PCTX.01110", "PCTX.01111",
02146   "PCTX.10000", "PCTX.10001", "PCTX.10010", "PCTX.10011", "PCTX.10100",
02147   "PCTX.10101", "PCTX.10110", "PCTX.10111",
02148   "PCTX.11000", "PCTX.11001", "PCTX.11010", "PCTX.11011", "PCTX.11100",
02149   "PCTX.11101", "PCTX.11110", "PCTX.11111",
02150   "?1000.0000?", "?1000.0001?", "?1000.0010?", "?1000.0011?", "?1000.0100?",
02151   "?1000.0101?", "?1000.0110?", "?1000.0111?",
02152   "?1000.1000?", "?1000.1001?", "?1000.1010?", "?1000.1011?", "?1000.1100?",
02153   "?1000.1101?", "?1000.1110?", "?1000.1111?",
02154   "?1001.0000?", "?1001.0001?", "?1001.0010?", "?1001.0011?", "?1001.0100?",
02155   "?1001.0101?", "?1001.0110?", "?1001.0111?",
02156   "?1001.1000?", "?1001.1001?", "?1001.1010?", "?1001.1011?", "?1001.1100?",
02157   "?1001.1101?", "?1001.1110?", "?1001.1111?",
02158   "DTB_TAG1", "DTB_PTE1", "DTB_IAP", "DTB_IA", "DTB_IS1", "DTB_ASN1",
02159   "?1010.0110?", "?1010.0111?",
02160   "?1010.1000?", "?1010.1001?", "?1010.1010?", "?1010.1011?", "?1010.1100?",
02161   "?1010.1101?", "?1010.1110?", "?1010.1111?",
02162   "?1011.0000?", "?1011.0001?", "?1011.0010?", "?1011.0011?", "?1011.0100?",
02163   "?1011.0101?", "?1011.0110?", "?1011.0111?",
02164   "?1011.1000?", "?1011.1001?", "?1011.1010?", "?1011.1011?", "?1011.1100?",
02165   "?1011.1101?", "?1011.1110?", "?1011.1111?",
02166   "CC", "CC_CTL", "VA", "VA_FORM", "VA_CTL", "?1100.0101?", "?1100.0110?",
02167   "?1100.0111?",
02168   "?1100.1000?", "?1100.1001?", "?1100.1010?", "?1100.1011?", "?1100.1100?",
02169   "?1100.1101?", "?1100.1110?", "?1100.1111?",
02170   "?1101.0000?", "?1101.0001?", "?1101.0010?", "?1101.0011?", "?1101.0100?",
02171   "?1101.0101?", "?1101.0110?", "?1101.0111?",
02172   "?1101.1000?", "?1101.1001?", "?1101.1010?", "?1101.1011?", "?1101.1100?",
02173   "?1101.1101?", "?1101.1110?", "?1101.1111?",
02174   "?1110.0000?", "?1110.0001?", "?1110.0010?", "?1110.0011?", "?1110.0100?",
02175   "?1110.0101?", "?1110.0110?", "?1110.0111?",
02176   "?1110.1000?", "?1110.1001?", "?1110.1010?", "?1110.1011?", "?1110.1100?",
02177   "?1110.1101?", "?1110.1110?", "?1110.1111?",
02178   "?1111.0000?", "?1111.0001?", "?1111.0010?", "?1111.0011?", "?1111.0100?",
02179   "?1111.0101?", "?1111.0110?", "?1111.0111?",
02180   "?1111.1000?", "?1111.1001?", "?1111.1010?", "?1111.1011?", "?1111.1100?",
02181   "?1111.1101?", "?1111.1110?", "?1111.1111?",
02182 };
02183 #endif

SourceForge.net Logo
Project space on SourceForge.net