cpu_interface.c 4.19 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * cpu_interface.c
 *****************************************************************/

#include "mips_arch.h"
#include "simtypes.h"
#include "cpu_interface.h"
#include "cpu.h"
#include "mipsy.h"
#include "checkpoint.h"
#include "addr_layout.h"
#include "cp0.h"
#include "tcl_init.h"
#include "machine_params.h"
#include "memif.h"
#include "scache.h"

extern void HandleDebugSignal(int cpuid, int sigusr); /* Defined in debug.c */
extern Result MipsyGetReg(int cpunum, int regnum, Reg *val);
extern Result MipsyPutReg(int cpunum, int regnum, Reg val);
extern Result MipsyGetMem(int cpunum, VA vAddr, uint nbytes, char *buf);
extern Result MipsyPutMem(int cpunum, VA vAddr, uint nbytes, char *buf);
extern Result MipsyTranslateVirtualNoSE(int cpunum, VA vAddr, PA *pAddr);
extern CPUStatus MipsyCPUStatus(int);

static void MipsyDoCheckpoint(int cpuNum);
bool tookCheckpoint = FALSE;

static void 
MipsyDMAInval(int machine, PA* k0list)
{
/* the memory system handles cache coherence for DMA, so this routine
   is a nop for mipsy */
}

extern void MipsyFinishMemRequests(void);

void 
MipsyDoCheckpoint(int cpuNum)
{
#ifndef SOLO
   int i;

   MipsyFinishMemRequests();

#ifdef DATA_HANDLING
   /* if running with DH on, we MUST flush all caches
    * before taking the checkpoint.
    */
   for (i = 0; i < TOTAL_CPUS; i++) {
     FlushEntireCache(i, TRUE);
   }
#endif

   /* This fixes the problem that arrived when we went to Post-PC
      annotations. The PC that the checkpoint annotation was set on
      would be the first one to execute when the checkpoint was
      restored, thus executing it twice... that's bad. 
      */

   for (i=0; i < TOTAL_CPUS; i++) {         
      CPUState *P = &PE[i];

      if (AnnFMLookup(P->PC, ANNFM_PC_TYPE)) {
         CPUWarning("MIPSY: Checkpoint from post-pc ann %#x on cpu %d\n",
                    P->PC, i);
         /* BAD HACK: The main loop checks this to see if it should
            move forward the PC since we need it to move forward
            before the checkpoint is taken. */
         tookCheckpoint = TRUE;
         P->PC = P->nPC;
         if (P->branchStatus == BranchStatus_taken) {
            P->nPC = P->branchTarget;
            P->branchStatus = BranchStatus_nottaken;
         } else {
            P->nPC += INST_SIZE;
         }
         CPUWarning("MIPSY:  changed PC to %#x\n", P->PC);
      }
   }
   Simcpt_Checkpoint(CPT_SAVE, NULL);
#endif
}

VA
MipsyCurrentPC(int cpu)
{
   return pePtr[cpu]->PC;
}

char *
MipsyPAToHostAddr(int cpu, PA pAddr, VA vAddr) 
{
#ifdef SOLO
   return (char *)(vAddr);
#else
   return (PHYS_TO_MEMADDR(M_FROM_CPU(cpu),pAddr) +
           (IS_REMAPPED_PADDR(pAddr,cpu) ? remapVec->NodeAddr[cpu] : 0));
#endif
}
/*****************************************************************
 * CPUVectorInit
 *****************************************************************/
void 
CPUVectorInit(void)
{
   CPUVec.Handle_Debug_Signal  = HandleDebugSignal;
   CPUVec.GetRegister          = MipsyGetReg;
   CPUVec.PutRegister          = MipsyPutReg;
   CPUVec.GetMemory            = MipsyGetMem;
   CPUVec.PutMemory            = MipsyPutMem;
   CPUVec.TranslateVirtualNoSE = MipsyTranslateVirtualNoSE;
   CPUVec.Unstall              = MipsyUnstall;
   CPUVec.CycleCount           = MipsyCycleCount;
   CPUVec.DMAInval             = MipsyDMAInval;
   CPUVec.CurrentCpuNum        = MipsyCurrentCpuNum;
   CPUVec.CurrentPC            = MipsyCurrentPC;
   CPUVec.InstrCount           = MipsyInstructionCount;
   CPUVec.DoCheckpoint         = MipsyDoCheckpoint;
   CPUVec.InstallMemAnnotation = MipsyInstallMemAnnotation;
   CPUVec.TakeBusError         = MipsyTakeBusError;
   CPUVec.useMemRef            = TRUE;
   CPUVec.PAToHostAddr         = MipsyPAToHostAddr;
   CPUVec.ReissueUncachedOp    = MipsyReissueUncachedOp;
   CPUVec.ClearLockFlag        = MipsyClearLockFlag;
   CPUVec.GetLockFlag          = MipsyGetLockFlag;
   CPUVec.GetLockAddr          = MipsyGetLockAddr;
   CPUVec.CPUstatus            = MipsyCPUStatus;

}