Дополнительные тесты позволили выявить несколько ошибок и неточностей в первой версии алгоритма.

Вот новая версия алгоритма, ещё более точно (как я полагаю) эмулирующая работу встроенного таймера процессора 1801ВМ1:

Код:
typedef unsigned long long QWORD;
typedef unsigned long      DWORD;
typedef unsigned short     word;

#define WORD(a) (*(unsigned short *)&aMemory[a])

PowerON()
{
  WORD(0177706) = wCPU_ID;
  wVE_Timer_Counter = 0177777;
  WORD(0177710) = wVE_Timer_Counter;
  WORD(0177712) = 0177400;
  nVE_MonitoredExpiryCount = 0;
  bVE_Expiry = false;
  bVE_Go = false;
}

Reset()
{
  WORD(0177712) = 0;
  Last_IO_Mode = IO_WRITE;
  wLast_IO_Addr =  0177712;
  Make_IO();
}

Make_IO()
{
  switch( wLast_IO_Addr )
  {
    // VE-Timer Counter Initial Value
    case 0177706:
    {
      if( Last_IO_Mode == IO_WRITE )
      {
        Last_IO_Mode = IO_READ;
        wLast_IO_Addr =  0177710;
        Make_IO();
        Last_IO_Mode = IO_WRITE;
        wLast_IO_Addr =  0177706;

        if( bVE_Go && !bVE_NoReload && !bVE_NoRestart )
        {
          QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
          qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
          QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
          
          if( qwCurrentCPU_Clocks >= qwNextVE_TimerStart_CPU_Clocks )
          {
            qwPrevVE_TimerStart_CPU_Clocks = qwNextVE_TimerStart_CPU_Clocks;
            dwPrevInitialVE_CounterVal     = dwNextInitialVE_CounterVal;
            
            QWORD qwUsedCPU_Clocks = qwCurrentCPU_Clocks - qwPrevVE_TimerStart_CPU_Clocks;
            QWORD qwCurrentVE_Timer_Clocks = qwUsedCPU_Clocks/nVE_CPU_Clock_Divider;
          
            DWORD dwTimerClocksLow = qwCurrentVE_Timer_Clocks % dwPrevInitialVE_CounterVal;
            
            qwNextVE_TimerStart_CPU_Clocks = qwPrevVE_TimerStart_CPU_Clocks;
            qwNextVE_TimerStart_CPU_Clocks += ( dwPrevInitialVE_CounterVal - dwTimerClocksLow ) * nVE_CPU_Clock_Divider;
          }
          
          dwNextInitialVE_CounterVal = WORD(0177706);
          if( !dwNextInitialVE_CounterVal ) { dwNextInitialVE_CounterVal = 0x10000; }
        }
      }
    }
    break;
    
    // VE-Timer Counter
    case 0177710:
    {
      if( Last_IO_Mode == IO_WRITE )
      {
        WORD(0177710) = wVE_Timer_Counter;
      }
      else
      {
        if( bVE_Go )
        {
          QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
          qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
          QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
          
          QWORD qwVE_TimerStart_CPU_Clocks = qwPrevVE_TimerStart_CPU_Clocks;
          DWORD dwInitialVE_CounterVal     = dwPrevInitialVE_CounterVal;
          
          if( qwCurrentCPU_Clocks >= qwNextVE_TimerStart_CPU_Clocks )
          {
            bVE_Expiry = true;
            
            if( !bVE_NoRestart )
            {
              qwVE_TimerStart_CPU_Clocks = qwNextVE_TimerStart_CPU_Clocks;
              dwInitialVE_CounterVal     = dwNextInitialVE_CounterVal;
            }
          }
          
          QWORD qwUsedCPU_Clocks = qwCurrentCPU_Clocks - qwVE_TimerStart_CPU_Clocks;
          QWORD qwCurrentVE_Timer_Clocks = qwUsedCPU_Clocks/nVE_CPU_Clock_Divider;
          
          DWORD dwTimerClocksHi  = qwCurrentVE_Timer_Clocks / dwInitialVE_CounterVal;
          DWORD dwTimerClocksLow = qwCurrentVE_Timer_Clocks % dwInitialVE_CounterVal;

          if( bVE_Expiry )
          {
            if( bVE_Monitor && (dwTimerClocksHi > nVE_MonitoredExpiryCount) )
            {
              nVE_MonitoredExpiryCount = dwTimerClocksHi;
            }
            
            if( bVE_NoReload )
            {
              wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
            }
            else if( bVE_NoRestart )
            {
              bVE_Go = false;
              
              wVE_Timer_Counter = WORD(0177706);

              if( dwTimerClocksHi == 1 && !dwTimerClocksLow )
              {
                if( qwCurrentCPU_Clocks%128 < 5 )
                {
                  wVE_Timer_Counter = 0;
                }
              }            
            }
            else
            {
              wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
              
              if( !dwTimerClocksLow )
              {
                if( qwCurrentCPU_Clocks%128 < 5 )
                {
                  wVE_Timer_Counter = 0;
                }
              }
            }
          }
          else
          { // !bVE_Expiry
            wVE_Timer_Counter = dwInitialVE_CounterVal - dwTimerClocksLow;
          }
          
          WORD(0177710) = wVE_Timer_Counter;
        }
      }
    }
    break;
    
    // VE-Timer CSR
    case 0177712:
    {
      IO_ModeType IO_Mode = Last_IO_Mode;
      
      Last_IO_Mode = IO_READ;
      wLast_IO_Addr =  0177710;
      Make_IO();
      wLast_IO_Addr =  0177712;
      Last_IO_Mode = IO_Mode;

      word wVE_Timer_CSR = WORD(0177712);

      if( Last_IO_Mode == IO_READ )
      {
        if( bVE_Expiry )
        {
          if( bVE_Monitor && nVE_MonitoredExpiryCount > 1 )
          {
            wVE_Timer_CSR |= BIT_7;
          }
          
          if( bVE_NoRestart && !bVE_NoReload )
          {
            wVE_Timer_CSR &= ~BIT_4;
          }
        }
        WORD(0177712) = wVE_Timer_CSR|0xFF00;
      }
      else
      { // Last_IO_Mode == IO_WRITE
      
        if( nVE_MonitoredExpiryCount )
        {
          nVE_MonitoredExpiryCount = 2;
        }
      
        bVE_Expiry = false;
        
        bVE_Go = wVE_Timer_CSR & BIT_4;

        if( wVE_Timer_CSR & BIT_0 )
        {
          bVE_Go = false;
        }

        bVE_NoReload  = wVE_Timer_CSR & BIT_1;
        bVE_Monitor   = wVE_Timer_CSR & BIT_2;
        bVE_NoRestart = wVE_Timer_CSR & BIT_3;

        nVE_CPU_Clock_Divider = 128;
        
        if( wVE_Timer_CSR & BIT_5 )
        {
          nVE_CPU_Clock_Divider *= 16;
        }

        if( wVE_Timer_CSR & BIT_6 )
        {
          nVE_CPU_Clock_Divider *= 4;
        }

        
        if( bVE_Go )
        {
          QWORD qwCurrentCPU_RunTimeNS = qwCPU_TotalRunTimeNS;
          qwCurrentCPU_RunTimeNS += dwCurrentStepsLatencyNS;
          QWORD qwCurrentCPU_Clocks = qwCurrentCPU_RunTimeNS/uCPU_CycleNS;
          
          QWORD qwVE_TimerStart_CPU_Clocks = qwCurrentCPU_Clocks;
          qwVE_TimerStart_CPU_Clocks -= qwVE_TimerStart_CPU_Clocks%128;

          QWORD dwInitialVE_CounterVal = WORD(0177706);
          if( !dwInitialVE_CounterVal ) { dwInitialVE_CounterVal = 0x10000; }
          
          dwPrevInitialVE_CounterVal = dwInitialVE_CounterVal;
          dwNextInitialVE_CounterVal = dwInitialVE_CounterVal;
          
          if( bVE_NoReload )
          {
            dwNextInitialVE_CounterVal = 0x10000;
          }

          qwPrevVE_TimerStart_CPU_Clocks = qwVE_TimerStart_CPU_Clocks;
          qwNextVE_TimerStart_CPU_Clocks = qwVE_TimerStart_CPU_Clocks;
          qwNextVE_TimerStart_CPU_Clocks += dwInitialVE_CounterVal * nVE_CPU_Clock_Divider;
        }

        wVE_Timer_Counter = WORD(0177706);
        
        WORD(0177710) = wVE_Timer_Counter;
        WORD(0177712) = wVE_Timer_CSR|0xFF00;
      }
    }
    break;
  }
}