⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms_grad.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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.  * */	/*	 *  ms_grad.c  -  Handle instruction graduation for the MXS simulator	 *	 *	Only needed to implement precise interrupts	 *	Also handles exceptions for the MIPSY version of MXS	 *	 *	Jim Bennett	 *	1994, 1995	 */#ifdef MIPSY_MXS#include <sys/types.h>#endif#include "ms.h"#ifdef MIPSY_MXS#include "mipsy.h"#include "cpu_state.h"#include "cpu_interface.h"#include "cp0.h"#include "hw_events.h"#include "machine_defs.h"#endif#define COHERENCY_EXCEPTION -1#define SWITCH2MIPSY_EXCEPTION -2static void RecordExceptionStats(struct s_cpu_state *st);static int InstIsInterruptable(struct s_cpu_state *st);	/*	 *  ms_graduate  -  Graduate instructions at the tail of the	 *		    graduation queue that have been freed.	 *	 *	This routine maintains the state of the processor at	 *	the graduation point, which is the only point at which	 *	consistency is assured.	 */void ms_graduate (struct s_cpu_state *st)	{#ifdef PRECISE	int	inum, flush_inst;	int	i;	THREAD	*th;	INST	*ip;	int	lreg, halfreg;	AddToStat (ST_GRADS_TRIED, GRAD_WIDTH);	if (st->exception_pending) {	    AddToStat (ST_GRAD_EXPEND, GRAD_WIDTH);            record_pipeline_stall(st, st->grad.pc,GRAD_WIDTH);	    return;	}	th = &st->grad;	for (i=0; i<GRAD_WIDTH; i++)		{		inum = st->iwin_headgrad;		if ((inum >= 0) && ((st->iwin_flags[inum] & IWIN_FREED) ||		                    ((st->iwin_flags[inum] & IWIN_FAULT) && 		                     !(st->iwin_flags[inum] & IWIN_SPEC))))		    {		    if (st->iwin_br_node [inum] == 0)			{#ifdef BANREMOVE              if ((th->pc != st->iwin_pc[inum]) &&                              (th->pc < SIMBASEADDR)) {                             ms_break(st, NULL, "pc error");                          }#endif		/* If the instruction at the head of the graduation	*/		/* queue caused an exception, then bail out now.	*/			if (st->iwin_flags[inum] & IWIN_FAULT)			    {			    st->exception_pending = 1;			    st->except = st->iwin_except [inum];			    AddToStat (ST_GRAD_EXPEND, GRAD_WIDTH-i);                            record_pipeline_stall(st, th->pc,GRAD_WIDTH-i);			    return;			    }		/* Retire stores out of the store buffer, if we can,	*/		/* bail out if we can't.				*/			if (st->iwin_flags[inum] & IWIN_LDST) { 			    if (st->iwin_flags[inum] & IWIN_LDSTBUF) {				int ret = ldst_buffer_retire(st,inum);				if (ret != 0) {				/* Line hasn't come back to cache - try again later */				    if (ret > 0) {                                        if (st->iwin_flags[inum] & IWIN_STORE) {                                           AddToStat (ST_GRAD_STSTALL, GRAD_WIDTH-i);                                       } else {                                          AddToStat (ST_GRAD_LDSTALL, GRAD_WIDTH-i);                                       }                                       record_ldst_stall(st, inum, GRAD_WIDTH-i);				       return; 				    }				/* Line was nuked from the cache -  backup and retry */				    st->exception_pending = 1;				    st->except = COHERENCY_EXCEPTION;				    AddToStat (ST_GRAD_EXPEND, GRAD_WIDTH-i);                                    record_pipeline_stall(st, th->pc,GRAD_WIDTH-i);				    return;				}			    }                            flush_inst = (st->iwin_flags[inum] & IWIN_FLUSH);			    IncStat(ST_GRAD_INST_LDST);			    if (is_sc(st->iwin[inum].op)) {				THREAD *sth = &st->threads[st->branch_tree[0].thread];				/* Continue the instruction fetcher after an SC */				sth->stall_sc = 0;				UpdateStallFetch (sth);			    }			} else {                            flush_inst = (st->iwin_flags[inum] & IWIN_FLUSH);                        }			if (st->iwin_flags[inum] & IWIN_ANNOTATED) {#ifdef MIPSY_MXS			   int cpuNum = ((CPUState *) (st->mipsyPtr))->myNum;#if 0               /*                            * Make sure to check the instruction sampling before                            * executing the annotation.                            */                                                      if (PE[cpuNum].numInstructions >= PE[cpuNum].nextInstrSample) {                              INST_SAMPLE_EVENT(MipsyReadTime(cpuNum), cpuNum, PE[cpuNum].PC);                              PE[cpuNum].nextInstrSample += MS_SAMPLE_INSTR_INTERVAL;                           }#endif                           #ifdef NOTDEF if(IS_KUSEG(st->iwin_pc[inum])) {    PE[cpuNum].lastUserAnnotation = st->iwin_pc[inum]; }                           AnnExec(AnnFMLookup(st->iwin_pc[inum],                                                ANNFM_PC_TYPE));#endif#endif /* MIPSY_MXS */                           st->iwin_flags[inum] &= ~IWIN_ANNOTATED;                        }                        /*                        if (st->iwin_pc[inum] == 0x80004294) {                           int foo = 1;                           CPUWarning("LOOPING");                           while (foo) ;                        }                         */		/* We've got an instruction that is all done, so	*/		/* graduate it.						*/			if (th->thread_st & TH_BRANCH)				{				th->pc = th->branch_pc;				th->thread_st &= ~TH_BRANCH;				}			else				th->pc = th->pc + PC_INC;			if (st->iwin_flags[inum] & IWIN_BRANCH)				{                                if (is_likely(st->iwin[inum].op) &&                                     !(st->iwin_flags[inum] & IWIN_TAKENBR)) {                                   /* The next PC of a not taken branch likely                                     * instruction skips over the delay slot. */                                    th->pc = st->iwin_branch_pc[inum];                                } else {                                  /* Regular branches update after delay slot inst */                                  th->thread_st |= TH_BRANCH;                                  th->branch_pc = st->iwin_branch_pc [inum];                                }				}#ifndef R3K                        if ((st->iwin[inum].op == OPCP0) &&                            (st->iwin[inum].imm == 0x42000018)) {                           /* R4K eret doesn't have a delay slot either. */                           th->pc = st->iwin_branch_pc[inum];                        }#endif                        IncStat(ST_GRAD_INST);#ifdef MIPSY_MXS                        {#ifdef BANREMOVE                          CPUState *P = (CPUState *)(st->mipsyPtr);                           P->numInstructions++;                           if (P->numInstructions > P->nextInstrSample) {                              INST_SAMPLE_EVENT(MipsyReadTime(P->myNum), P->myNum, P->PC);                              P->nextInstrSample += MS_SAMPLE_INSTR_INTERVAL;                           }#endif			}                        RunPCAnnotations(st->iwin_pc[inum], 0);#endif /* MIPSY_MXS */		/* Have to dequeue before updating the register name	*/		/* table, so that old name of register can be released	*/			ms_grad_dequeue (st, inum);		/* The thread state at the graduation point needs to	*/		/* correctly track the register name table.  This code	*/		/* duplicates the actions that the fetch unit took when	*/		/* this instruction was fetched.			*/			ip = &st->iwin[inum];			if ((lreg = st->iwin_lr2[inum]) > 0)				th->half_def[lreg >> 1] = 0;			if ((lreg = st->iwin_lr3[inum]) > 0)				th->half_def[lreg >> 1] = 0;			if ((lreg = st->iwin_lr1 [inum]) > 0)			  {			  halfreg = lreg >> 1;			  if ((lreg < FPREG) || (lreg >= MAX_FP))			    th->regnames [lreg] = ip->r1;			  else			  if ((lreg < FPCTL) || (lreg >= TOT_REG))			    {			    if ((ip->op == OPCVTDW) || (ip->op == OPCVTDS) ||				((ip->op >= OPFADDD) && (ip->op <= OPFFLOORD)))				{				th->regnames[lreg]   = ip->r1;				th->regnames[lreg+1] = ip->r1 + 1;				th->half_def[halfreg] = 0;				}			    else				{				if (th->half_def[halfreg] == (lreg^0x01))				    th->half_def[halfreg] = 0;				else				    {				    int dest_reg, evenreg;				    dest_reg = ip->r1 & (~0x01);				    evenreg = halfreg << 1;				    th->half_def[halfreg] = lreg;				    th->regnames[evenreg]   = dest_reg;				    th->regnames[evenreg+1] = dest_reg+1;				    }				}			    }			  }                        /* CPUPrint("PC %#llx\n", st->iwin_pc[inum]);  */                        /*                        AnnExec(AnnFMLookup(st->iwin_pc[inum], ANNFM_PC_TYPE)); */			}		    else			{		/* If it's completed, delete it regardless of which	*/		/* branch node it is on.				*/			if (st->iwin_flags[inum] & IWIN_LDST)				{#ifdef DEBUG_CHECKS				if (st->iwin_flags[inum] & IWIN_LDSTBUF)					{					fprintf (stderr, 					  "Squashed entry still in ldst buf\n");					ms_break (st, NULL, "ERR");					}#endif				IncStat(ST_GRAD_SQUASHED_LDST);				}			IncStat(ST_GRAD_SQUASHED);                        flush_inst = 0;			ms_grad_dequeue (st, inum);                        record_pipeline_stall(st, th->pc,1);			}		    continue;	/* Keep on graduating instructions,	*/		    }		/* since this one graduated.		*/                if (inum < 0) {                    /* Pipeline is totally empty */                   if (st->active_thread && st->active_thread->stall_icache) {                      /* Nothing done this cycle - record this as memory stall */                      record_icache_stall(st, th->pc,GRAD_WIDTH-i);                      AddToStat(ST_GRAD_ICACHESTALL, GRAD_WIDTH-i);                   } else if (flush_inst) {                       record_pipeline_stall(st, th->pc,GRAD_WIDTH-i);                      AddToStat(ST_GRAD_FLUSHSTALL, GRAD_WIDTH-i);                   } else {                      record_pipeline_stall(st, th->pc,GRAD_WIDTH-i);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -