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

📄 ms_fetch.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_fetch.c  -  Handle instruction fetching for the MXS simulator	 *	 *	Jim Bennett	 *	1994, 1995	 */#ifdef MIPSY_MXS#include <sys/types.h>#endif#include <stdlib.h>#include "ms.h"#ifdef MIPSY_MXS#include "cpu_state.h"#include "mipsy.h"#include "annotations.h"#include "cp0.h"#include "pcache.h"#endif/* Global variable set if there is an annotation on this instruction. */extern int mxs_annotation;static int ms_rename (struct s_cpu_state *st, INST *ip, THREAD *th,				int this_inst, int store_inst);	/*	 *  ms_fetch  -  Fetch instructions from the text segment and add	 *		 them to the instruction window	 */void ms_fetch (struct s_cpu_state *st)	{	INST	*ip;	THREAD	*th;	BrTREE	*br;	int	this_inst, fetches, store_inst;	int	nfetch;			/* Number of successful fetches	*/#ifdef MIPSY_MXS	uint	inst;#endif	AddToStat (ST_FETCHES_TRIED, FETCH_WIDTH);	if (st->exception_pending)	    {	/* Pending exception stalls all threads	*/		AddToStat (ST_FETCH_EXPEND, FETCH_WIDTH)		return;	    }	nfetch = 0;#if MAX_ACT_THREADS == 1	for (fetches=0;fetches<FETCH_WIDTH;fetches++)#else	for (th = st->active_thread, fetches=0;				fetches<FETCH_WIDTH;				fetches++, th = th->active_thread)#endif 		{			/* If instruction window is full,	*/			/* then proceed to next unit.		*/		if (st->iwin_ninst >= IWIN_SIZE)			{			AddToStat (ST_FETCH_IW_FULL, FETCH_WIDTH-fetches)			break;			}		this_inst = st->iwin_nextfree;		if (this_inst < 0)			{			AddToStat (ST_FETCH_RB_FULL, FETCH_WIDTH-fetches)			break;			}			/* If there are no active unstalled threads,	*/			/* then proceed to next unit.			*/#if MAX_ACT_THREADS == 1		th = st->active_thread;		if (!th) {		    AddToStat (ST_FETCH_STALL_OTH,FETCH_WIDTH-fetches)		    AddToStat (ST_FETCH_STALL,FETCH_WIDTH-fetches)		    break;		}		if (th->stall_fetch) {		    if (th->stall_branch) {			if (th->stall_thread) {			  AddToStat (ST_FETCH_STALLTHREAD,FETCH_WIDTH-fetches);			} else {			  AddToStat (ST_FETCH_STALLBRANCH,FETCH_WIDTH-fetches);			}		    } else if (th->stall_fpc) {			AddToStat (ST_FETCH_STALLFPC,FETCH_WIDTH-fetches);		    } else if (th->stall_icache) {			AddToStat (ST_FETCH_STALLICACHE,FETCH_WIDTH-fetches);		    } else if (th->stall_itlbmiss) {			AddToStat (ST_FETCH_STALLITLB,FETCH_WIDTH-fetches);		    } else  if (th->stall_except) {			AddToStat (ST_FETCH_STALLEXCEPT,FETCH_WIDTH-fetches);		    } else  if (th->stall_sys) {			AddToStat (ST_FETCH_STALLSYS,FETCH_WIDTH-fetches);		    } else  if (th->stall_cp0) {			AddToStat (ST_FETCH_STALLCP0,FETCH_WIDTH-fetches);		    } else  if (th->stall_sc) {			AddToStat (ST_FETCH_STALLSC,FETCH_WIDTH-fetches);                    } else {			AddToStat (ST_FETCH_STALL_OTH,FETCH_WIDTH-fetches);                    }		    AddToStat (ST_FETCH_STALL,FETCH_WIDTH-fetches)#ifndef MIPSY_MXS#ifdef DEBUG_CHECKS			if (((th->thread_st & TH_SPEC) == 0) &&			    (th->stall_icache || th->stall_except) )				{				fprintf (stderr,					"Fetch unit permanently stalled\r\n");				fprintf (stderr,					"Cycle #% 9d%0.5d\r\n",					st->work_ticks, st->work_cycle);				ms_break (st, NULL, "ERR");				}#endif#endif		    break;		}#else		while ((th) && th->stall_fetch)			th = th->active_thread;		if (th == NULL)			{			th = st->active_thread;			while ((th) && th->stall_fetch)				th = th->active_thread;			if (th == NULL)				{		    		AddToStat (ST_FETCH_STALL_OTH,						FETCH_WIDTH-fetches)				AddToStat (ST_FETCH_STALL,						FETCH_WIDTH-fetches);				break;				}			}#endif		ip = &st->iwin [this_inst];#ifdef MIPSY_MXS			/* Fetch the instruction to this thread	*/		{		PA	paddr;		int	ret, dum1, dum2, bdoor;		uint    tlbFlavor = TLB_IFETCH|TLB_READING;		CPUState *P = (CPUState *) (st->mipsyPtr);		if ((th->pc & 3) == 0) {                       void *bdoorAddr = 0;		    ret = TranslateVirtual(P, th->pc, &paddr, &tlbFlavor, &bdoorAddr);		} else {		    RECORD_EXCEPTION(P, EXC_RADE, E_VEC,th->pc,                              P->CP0[C0_TLBHI], P->CP0[C0_CTXT],                             P->CP0[C0_XCTXT]);  		    ret = FAILURE;		}		if (ret != SUCCESS)			{			th->except = GetLastException(st);			th->stall_itlbmiss = 1;			UpdateStallFetch (th);			IncStat (ST_FETCH_STALLITLB);			IncStat (ST_FETCH_STALL);			continue;			}                bdoor = (tlbFlavor & TLB_BDOOR);		if (!bdoor) {		    st->ms_action = ACT_UNSTALL_ICACHE;		    P->PC = th->pc;		    ret = ReadICache(P->myNum, th->pc, paddr, &inst);		    if (ret != SUCCESS)			{			    if (ret == FAILURE) {				/* Cache wouldn't accept req - stall for a cycle. */                                IncStat (ST_FETCH_CACHEFAILURE);				IncStat (ST_FETCH_STALLICACHE);				IncStat (ST_FETCH_STALL);				continue;			    }			    th->stall_icache = 1;                            th->icache_stall_reason = MxsClassifyMiss(P->myNum,                                                 th->pc, paddr, TRUE);			    UpdateStallFetch (th);			    IncStat (ST_FETCH_STALLICACHE);			    IncStat (ST_FETCH_STALL);			    continue;			}		}		if (!bdoor)  {                   compile_inst (inst, th->pc, ip, &dum1, &dum2);		} else {		   ip->op = OPBDOOR;		   ip->r1 = ip->r2 = ip->r3 = -1;		   ip->imm = paddr;		}	     }#else			/* If the PC of this thread is invalid, then	*/			/* stall the thread.				*/		if (th->pc == OUTSIDE_ADDR)			{			th->stall_icache = 1;			UpdateStallFetch (th);			IncStat (ST_FETCH_STALL_INV);			IncStat (ST_FETCH_STALL);			continue;			}			/* Fetch the instruction to this thread	*/		*ip = pmap.ctbuf[th->pc];#endif#ifdef PRINT_INST	{	int t, flagp;	if (enable_iprint && ((st->work_cycle % iprint_frequency) == 0))		{		printf ("% 7d%0.5d @0x%8.8x: ",			st->work_ticks, st->work_cycle, th->debugpc);		print_inst (stdout, ip);		flagp = 0;		if (ip->r2 > 0)			{			t = th->regnames [ip->r2];			printf (" [");			print_reg_contents (stdout, ip->r2, &st->regs[t]);			flagp = 1;			}		if (ip->r3 > 0)			{			t = th->regnames [ip->r3];			if (flagp)				printf (", ");			else				printf (" [");			print_reg_contents (stdout, ip->r3, &st->regs[t]);			flagp = 1;			}		if (flagp)			printf ("]\r\n");		else			printf ("\r\n");#ifdef PRINT_IREG		for (i=0; i<32; i+=8)			printf ( "%8x %8x %8x %8x %8x %8x %8x %8x\r\n",				Ireg(i), Ireg(i+1), Ireg(i+2), Ireg(i+3),				Ireg(i+4), Ireg(i+5), Ireg(i+6), Ireg(i+7));		printf ("\r\n");#endif		}	}#endif		st->iwin_br_node [this_inst] = th->branch_node;#ifdef BREAKPOINT		if (th->debugpc == brkpt) ms_break (st, ip, "PC BRK");		if (ip->op == opcbrk) ms_break (st, ip, "OP BRK");#endif			/* If it is a branch likely inst, we need to	*/			/* ensure we can process it now.		*/			/* NOTE:  This means that branch likely	inst's	*/			/* won't work in a non-speculative model.	*/			/* I.e. THREAD_WIDTH must be at least two.	*/		if (is_likely (ip->op) && (st->nthreads >= THREAD_WIDTH))			{			IncStat (ST_FETCH_THREAD);			continue;			}			/* Convert illegal instruction sequence to	*/			/* illegal instruction, for exception handling	*/		if (th->branch_dly && (is_branch (ip->op) || is_call (ip->op))) 			{			ip->op = OPILL;			ip->r1 = ip->r2 = ip->r3 = -1;			}			/* Rename logical registers to use real		*/			/* (physical) registers.			*/		store_inst = is_store (ip->op);		if (ms_rename (st, ip, th, this_inst, store_inst) < 0)			{			IncStat (ST_FETCH_NAME);			continue;			}			/* Rename succeeded, so it is OK to update the	*/			/* machine state now.				*/		ms_grad_enqueue (st, this_inst);		st->iwin_pc [this_inst] = th->pc;		st->iwin_flags [this_inst] |= IWIN_BUSY;		if (mxs_annotation)			st->iwin_flags [this_inst] |= IWIN_ANNOTATED;		if (th->thread_st & TH_SPEC)			st->iwin_flags [this_inst] |= IWIN_SPEC;		st->iwin_nextfree = st->iwin_freelist [this_inst];		th->pc = th->pc + PC_INC;		th->debugpc += 4;			/* Add instruction to list for this thread	*/		br = &st->branch_tree [th->branch_node];		if (br->iwin_tail_th >= 0)			{			st->iwin_thread [br->iwin_tail_th] = this_inst;			st->iwin_bthread [this_inst] = br->iwin_tail_th;			st->iwin_thread [this_inst] = -1;			br->iwin_tail_th = this_inst;			}		else			{			br->iwin_head_th = this_inst;			br->iwin_tail_th = this_inst;			st->iwin_bthread [this_inst] = -1;			st->iwin_thread [this_inst] = -1;			}			/* Add load/store instructions to load/store chain */		if (is_ldst (ip->op))		    {		    if (store_inst) st->iwin_flags [this_inst] |= IWIN_STORE;		    ms_ldst_enqueue (st, this_inst);#ifdef ONE_PHASE_LS			/* Loads and stores must wait if there is a	*/			/* preceeding store.				*/		    if (st->iwin_nstores > 0)			st->iwin_flags [this_inst] |= IWIN_LDST_DEP;			/* A store must wait if there are any		*/			/* preceeding loads or stores.			*/		    if (store_inst)			{			if (this_inst != st->iwin_head_ldst)				st->iwin_flags [this_inst] |= IWIN_LDST_DEP;			st->iwin_nstores++;			}#endif		    }			/* Add this instruction to the tail	*/			/* of the priority chain in the window	*/		nfetch++;		ms_pri_enqueue (st, this_inst);			/* If we've just fetched some kind of branch,	*/			/* then stop fetching until the branch is	*/			/* resolved.					*/		if (is_branch (ip->op) || is_call (ip->op))			{			if (th->branch_dly)				{				fprintf (stderr,				  "No branches allowed in branch shadow!!\r\n");				ms_break (st, NULL, "ERR");				}				/* IWIN_BRDLY is used to hold off issue	*/				/* of this inst until branch delay	*/				/* slots have been fetched.		*/			st->iwin_flags [this_inst] |= IWIN_BRDLY + IWIN_BRANCH;			th->branch_inum = this_inst;			th->branch_dly = BRANCH_SLOTS + 1;			th->returnpc = th->pc + (BRANCH_SLOTS*PC_INC);				/* Handle branch likely instructions	*/			if (is_likely (ip->op))				{				th->stall_branch = 1;				UpdateStallFetch (th);				ms_branch (st, th, 1);				}			}		else			/* If it is a system call or a write to the FP	*/			/* control register, stall fetching until all	*/			/* prior instructions are executed.		*/		if (is_sys (ip->op) || is_fp_ctl (ip->op) || is_sc(ip->op))			{                        if (is_sc (ip->op))                             th->stall_sc = 1;			else if (is_sys(ip->op)) {                            if (ip->op == OPCP0) 				th->stall_cp0 = 1;                            else 				th->stall_sys = 1;                        }  else 			    th->stall_fpc = 1;                        			UpdateStallFetch (th);			if (!is_sc(ip->op))

⌨️ 快捷键说明

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