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

📄 ms_ldst.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
		return (0);		}#ifdef MIPSY_MXS	if ((ls->lstype == ST_INTEGER_SC) &&	    !(((CPUState *) (st->mipsyPtr))->LLbit)) {	    goto  scfail;	}	/* Update Mipsy PC so memstat knows where miss came from. */	((CPUState *) (st->mipsyPtr))->PC = st->iwin_pc[ls->inum];#endif    if (ls->lstype == PREFETCH) {      int mcmd;      if (ls->paddr != -1) {         switch (-ls->reg) {         case 1: case 5: case 7:            mcmd = MEMSYS_GETX;            break;         case 0: case 4: case 6:         default:            mcmd = MEMSYS_GET;            break;         }         SCachePrefetch(CPUNUM(st), ls->addr, ls->paddr, mcmd);      }#ifdef PREF_DEBUG        CPUPrint("\t\tCPU %d EX Prefetch addr = %08x cycle = %d ret = %d\n",                  CPUNUM(st), entry->ls->paddr, st->work_cycle, ret);#endif      free_inst(st, ls->inum);      ls->status |= LS_ST_DONE;      return 0;    }	if (ls->status & LS_ST_STALL)		{		ret = STALL;		dataPtr = (char *)entry->missTag;		}	else		{				/* Set flag for CheckIntervention	*/		ls->status |= LS_ST_FAILED;		st->ms_action = ACT_DCACHE_MISS;		if (IsLoad(ls->lstype)) {		    IncStat(ST_CACHE_LOAD);		    flavor = (ls->lstype == LD_INTEGER_LL) ? LL_FLAVOR : 0;		    ret = DCacheFetchShared(CPUNUM(st), ls->addr, ls->paddr,						flavor, &dataPtr);		} else {		    IncStat(ST_CACHE_STORE);		    flavor = (ls->lstype == ST_INTEGER_SC) ? SC_FLAVOR : 0;		    ret = DCacheFetchExclusive(CPUNUM(st), ls->addr, ls->paddr,						flavor, &dataPtr);		}		ls->status &= ~LS_ST_FAILED;		}	switch (ret) {	case SUCCESS: {		/* Hit in the cache, do the operation (unless the data	*/		/* is still pending).					*/	    ls->status |= LS_ST_CACHED;	    if (ls->status & LS_ST_PEND) return (0);		/* When the operation is done, clear the invalidated	*/		/* flag.  If the flag gets set between here and when	*/		/* this operation is retired, then we have to retry it.	*/	    entry->dataPtr = dataPtr;	    entry->invalidated = 0;	    ms_lsop (st, ls, entry, 1);#ifdef PREF_DEBUG        CPUPrint("\t\tCPU %d EX %s addr = %08x cycle = %d\n", CPUNUM(st),                 IsLoad(ls->lstype) ? "Load" : "Store", ls->paddr, st->work_cycle);#endif	    ls->status |= LS_ST_DONE;	    IncStat(ST_CACHE_HIT);	    return 0;	}	case FAILURE: {	    /* Cache couldn't accept the request. Return failure to caller	     * so it will be retried.	     */	    IncStat(ST_CACHE_FAILURE);	    if (IsLoad(ls->lstype))		set_new_excuse (st, ls->reg, ST_CACHE_LBSY);	    ls->status |= LS_ST_FAILED;	    return -1;	}	case STALL: {	    /* Memsystem has it now. Wait for callback */	    ls->status |= LS_ST_STALL + LS_ST_CACHED;	    entry->missTag = (void *) dataPtr;            entry->cacheStallReason = MxsClassifyMiss(CPUNUM(st),                                      entry->ls->addr, entry->ls->paddr, FALSE);	    if (ls->status & LS_ST_PEND) return (0);	    IncStat(ST_CACHE_MISS);	    if ((entry->loadhit) ||		(IsStore(ls->lstype) && (ls->lstype != ST_INTEGER_SC))) {		/* Actually, stores and loads that hit in the write buffer		 * can be processed. Special case SC instructions. */		ms_lsop (st, ls, entry, 1);		ls->status |= LS_ST_DONE;		if (entry->loadhit) IncStat(ST_CACHE_LOADHIT);	    }	    if (IsLoad(ls->lstype))		set_new_excuse (st, ls->reg, ST_CACHE_BUS);	    return 0;	}	case SCFAILURE: {	  scfail:	    Ireg(ls->reg2) = 0;  /* FAIL the SC */	    if (ls->reg2 == 0)		reg0_writeback(st, (void *) (ls->inum));	    else		reg_writeback(st, (void *) ls->reg2);	    entry->size = 0;	    IncStat(ST_CACHE_SCFAILURE);	    ls->status |= LS_ST_DONE;	    return 0;	    }	default:	    if (IsLoad(ls->lstype))		set_new_excuse (st, ls->reg, ST_CACHE_LBSY);	    ls->status |= LS_ST_CACHED;	    return (0);	}	}	/*	 *  set_new_excuse  -  Update the reason why the register is not	 *			yet available	 */static void set_new_excuse (struct s_cpu_state *st, int reg, int excuse)	{	int reg_ix = reg >> 1;	if (st->new_excuse[reg_ix] == ST_NO_EXCUSE)		st->reg_excuse[reg_ix] = excuse;	else		st->new_excuse[reg_ix] = excuse;	}/************************************************************************//*									*//* Common routine to perform load operations, regardless of whether	*//* there is a cache or not.						*//*									*//************************************************************************/	/*	 *  ms_lsop  -  Perform load/store operation	 *	 *	Converts virtual address to address in simulator's memory	 *	and performs the indicated operation.  Always returns 0	 *	to indicate success.	 */static int ms_lsop (struct s_cpu_state *st, struct s_lsq *ls,				struct s_ldst_buffer *entry, int update_inst)	{	int  reg, i, update;	char *dataPtr;	uint paddr = ls->paddr;	static double nulldoubleword = 0;	WorkDecls;#ifndef MXS_CACHE		/* If no cache, Must check for errors here:	*/		/* Screen out errors due to speculative loads	*/	if (WouldFault(st, lstype, ls->addr))		{		if (IsLoad (ls->lstype))			st->reg_rstat[ls->reg >> 1].reg_status |= REG_ERROR;		st->iwin_flags[ls->inum] |= IWIN_FAULT;		CheckSquash (st, &st->iwin[ls->inum]);		return (0);		}#endif	reg = ls->reg;	dataPtr = entry->dataPtr;	if (dataPtr == NULL) {	    /* This should only happen when we have a read that	     * hits in the write buffer but is not in the class. Give	     * a fake memory location to start with load which will	     * be filled from the write buffer.	     */	    dataPtr = (char *) &nulldoubleword;	}#if PC_LATENCY > 1#define WRITEBACKREG() \	if (reg == 0) \    Add_to_worklist (st, PC_LATENCY, reg0_writeback,(void *)(ls->inum)); \	else \    Add_to_worklist (st, PC_LATENCY, reg_writeback,(void *)reg);#else#define WRITEBACKREG() \	if (reg == 0) reg0_writeback(st,(void *)(ls->inum)); \	else reg_writeback(st, (void *) reg)#endif	switch (ls->lstype)		{		case LD_UNSIGNED_B: {			unsigned char uc;			uc = * (unsigned char *)dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&uc,1);			Ureg(reg) = uc;			WRITEBACKREG();			break;		     }		case LD_UNSIGNED_H: {			ushort  us;			us = *(ushort *)dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&us,2);			Ureg(reg) = us;			WRITEBACKREG();			break;		     }		case LD_UNSIGNED_L:			{			int reg2 = ls->reg2;			int shft = ((int)dataPtr & 0x03) * 8;			dataPtr = (char *)((int)dataPtr&0xfffffffc);			i = *(unsigned int*) dataPtr;			update = ldst_buffer_updateRead (st, entry,						paddr &~0x3, (char *)&i, 4);			Ureg(reg) = Ureg(reg2) & (~(0xffffffff << shft));			Ureg(reg) |= i << shft;			WRITEBACKREG();			break;			}		case LD_UNSIGNED_R:			{			int reg2 = ls->reg2;			int shft = (3 - ((int)dataPtr & 0x03)) * 8;			int mask = 0xffffff00 << (24 - shft);			dataPtr = (char *)((int)dataPtr&0xfffffffc);			i = *(unsigned int*) dataPtr;			update = ldst_buffer_updateRead (st, entry,						paddr &~0x3, (char *)&i, 4);			Ureg(reg) = Ureg(reg2) & mask;			Ureg(reg) |= (i >> shft) & (~mask);			WRITEBACKREG();			break;			}		case LD_INTEGER_B: {			signed char c;			c = *(signed char *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&c,1);			Ireg(reg) = c;			WRITEBACKREG();			break;		     }		case LD_INTEGER_H: {			short s;			s = *(short *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&s,2);			Ireg(reg) = s;			WRITEBACKREG();			break;		     }		case LD_INTEGER_W: {			int w;			w = *(int *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&w,4);			Ireg(reg) = w;			WRITEBACKREG();			break;		     }		case LD_INTEGER_LL: {			int w;			w = *(int *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&w,4);			Ireg(reg) = w;			WRITEBACKREG();#ifdef MIPSY_MXS			((CPUState *) (st->mipsyPtr))->LLbit = 1;#endif			break;		     }		case LD_FLOAT:{			float f;			f = *(float *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&f,4);			Freg(reg) = f;			WRITEBACKREG();			break;		     }		case LD_DOUBLE: {			double d;			d = *(double *) dataPtr;			update =			ldst_buffer_updateRead(st,entry,paddr,(char *)&d,8);			Dreg(reg) = d;			WRITEBACKREG();			break;		     }		case ST_INTEGER_B: {			char b = Ireg(ls->reg);			ldst_buffer_write(st,entry,paddr,(char *)&b,1);			break;		     }		case ST_INTEGER_H: {			short s = Ireg(ls->reg);			ldst_buffer_write(st,entry,paddr,(char *)&s,2);			break;		     }		case ST_INTEGER_W: {			int i = Ireg(ls->reg);			ldst_buffer_write(st,entry,paddr,(char *)&i,4);			break;		     }		case ST_INTEGER_L: {			uint i;			int byte = (((int)paddr) & 0x3);			i = Ureg(ls->reg);			ldst_buffer_write(st,entry,paddr,(char *)&i,4-byte);			break;		     }		case ST_INTEGER_R: {			 uint i;			int byte = (((int)paddr) & 0x3);			i = Ureg(ls->reg) << (24 - byte*8);			ldst_buffer_write(st,entry,paddr&~0x3,(char *)&i,1 + byte);			break;		     }		case ST_FLOAT: {			float f = Freg(ls->reg);			ldst_buffer_write(st,entry,paddr,(char *)&f,4);			break;		     }		case ST_DOUBLE: {			double d = Dreg(ls->reg);			ldst_buffer_write(st,entry,paddr, (char *)&d,8);			break;		     }		case ST_INTEGER_SC: {			int i = Ireg(ls->reg);			reg = ls->reg2;			ldst_buffer_write(st,entry,paddr,(char *)&i,4);			Ireg(reg) = 1;			WRITEBACKREG();			break;		     }        case PREFETCH: {          fprintf(stderr, "ms_lsop called on prefetch instruction\r\n");          ms_break (st, NULL, "ERR");        }		}	if (update_inst)		{#ifdef DEBUG_CHECKS		if (st->iwin_flags[ls->inum] & IWIN_SQUASH)			{			fprintf (stderr, "Executing squashed load/store\r\n");			ms_break (st, NULL, "ERR");			}#endif /* DEBUG_CHECKS */#ifdef PRECISE		if (st->iwin[ls->inum].r1 < 0)			free_inst(st, ls->inum);#else /* PRECISE */		if (IsLoad (ls->lstype))			{			int	ret;			if (update) entry->dataPtr =						(char *) &nulldoubleword;			ret = ldst_buffer_retire (st, ls->inum);#ifdef DEBUG_CHECKS			if (ret != 0)				{				fprintf (stderr, "Retire failure on read\r\n");				ms_break (st, NULL, "ERR");				}#endif /* DEBUG_CHECKS */			}#endif /* PRECISE */		}	return (0);	}int LdSizeOf(int lstype){    switch (lstype)		{		case LD_UNSIGNED_B:		case LD_INTEGER_B:			return 1;		case LD_UNSIGNED_H:		case LD_INTEGER_H:			return 2;		case LD_UNSIGNED_L:			return 4;		case LD_UNSIGNED_R:			return 4;		case LD_INTEGER_W:		case LD_INTEGER_LL:		    return 4;		case LD_FLOAT:		    return 4;		case LD_DOUBLE:		    return 8;		}   return 0;}	/*	 *  ldst_buffer_alloc  -  Allocate an entry in ldst_buffer	 *	 *	Also check if this is a load that is satisfied by	 *	an earlier store, and set a pointer to it if so	 *	 *	Returns a NULL pointer if allocation fails	 */static struct s_ldst_buffer *ldst_buffer_alloc(struct s_cpu_state *st, int paddr, int lstype)	{	struct s_ldst_buffer *entry, *prev_entry, *store1, *store2;	char *vs;        prev_entry = 0; /* Slience bogus compiler error message */		/* Grab the next entry from the reserved list.		*/		/* It's an error if this entry hasn't been reserved	*/	entry = st->ldst_nextReserved;	if (entry == NULL) return (NULL);		/* Move entry from reserved list to active load/store	*/		/* list.  Add at end of list to preserve order.		*/	st->ldst_nextReserved = entry->next;	if (st->ldst_tail)		{		st->ldst_tail->next = entry;		entry->prev = st->ldst_tail;		entry->next = NULL;		st->ldst_tail = entry;		}	else		{		st->ldst_head = entry;		st->ldst_tail = entry;		entry->next = NULL;		entry->prev = NULL;		}		/* Then fill in this entry				*/	entry->dataPtr = NULL;	entry->missTag = (void *) -1;        entry->cacheStallReason = 0;	entry->paddr = paddr;	entry->size = 0;

⌨️ 快捷键说明

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