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

📄 ms_ldst.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
retire_exit:   st->iwin_flags[inum] &= ~IWIN_LDSTBUF;   ldst_buffer_free (st, entry);   return (0);}/* * ldst_record_stall - Record the stall generated by an entry  */voidrecord_ldst_stall(struct s_cpu_state *st, int inum, int stall){   struct s_ldst_buffer *entry = st->inum2ldst[inum];   if (entry->ls->inum != inum) {	fprintf(stderr, "retire failure in ldst_record_stall\r\n");	ms_break (st, NULL, "ERR");   }   MS_STALL_EVENT(CPUNUM(st), entry->ls->addr, st->iwin_pc[inum],                   stall, entry->cacheStallReason);}voidrecord_icache_stall(struct s_cpu_state *st, int pc, int stall){   MS_STALL_EVENT(CPUNUM(st), pc, pc, stall,                   st->active_thread->icache_stall_reason);}voidrecord_pipeline_stall(struct s_cpu_state *st, int pc, int stall){   MS_STALL_EVENT(CPUNUM(st), pc, pc, stall, E_PIPELINE);}	/*	 *  ldst_buffer_squash	 */void ldst_buffer_squash(struct s_cpu_state *st, int inum){   struct s_ldst_buffer *entry = st->inum2ldst[inum];   if (entry->ls->inum != inum) {	fprintf(stderr, "retire failure in ldst_buffer_squash\r\n");	ms_break (st, NULL, "ERR");   }   IncStat(ST_LDST_BUF_SQUASH);   if (entry->dataPtr == NULL)	IncStat(ST_LDST_BUF_SQUASH_ACT);   st->iwin_flags[inum] &= ~IWIN_LDSTBUF;   ldst_buffer_free (st, entry);   return;}/* * MxsApproveImiss - Return TRUE if it is safe to process an instruction *		   cache miss to this address. This routine will disallow *		   any instruction cache miss that might invalidate an active *		   entry in the ldst buffer. */intMxsApproveImiss(struct s_cpu_state *st,int paddr){   int sind;   struct s_ldst_buffer *entry;   sind = SCACHE_INDEXOF(paddr);   for (entry = st->ldst_head; (entry); entry = entry->next)	{	if (SCACHE_INDEXOF(entry->paddr) != sind)	 continue;  /* Skip if not an active entry at same Scache index */	return 0;   }   return 1;}	/*	 *  DoMxsIntervention  -  When a cache line is thrown out, notify	 *			  the load/store buffer by calling this	 *			  routine.	 */voidDoMxsIntervention(struct s_cpu_state *st, int paddr, int size, int writebackonly){    struct s_ldst_buffer *entry;    int paddr_end = paddr + size;    for (entry = st->ldst_head; (entry); entry = entry->next)	{	if (entry->dataPtr == NULL) continue; /* Only a problem if we have						 returned data */	if ((entry->paddr >= paddr) && (entry->paddr < paddr_end)) {	    if (!writebackonly || IsStore(entry->ls->lstype)) {		entry->invalidated = 1;	    }	}    }}	/*	 *  CheckIntervention  -  Check if recycling the cache line might cause	 *			  an intervention, and if so return TRUE.	 *	 *	When mtag is specified, stop the check when the entry	 *	containing that miss tag is reached.	 */int CheckIntervention (struct s_cpu_state *st, void *mtag, int paddr, int size)	{	struct s_ldst_buffer *entry;	int paddr_end = paddr + size;	int	ignore_null = 0;	for (entry = st->ldst_head; (entry); entry = entry->next)		{			/* After the first failed entry is encountered,	*/			/* just need to worry about entries with non-	*/			/* null data pointers.				*/		if (entry->ls->status & LS_ST_FAILED) ignore_null = 1;		if (ignore_null && (entry->dataPtr == NULL)) continue;		if (mtag && (entry->missTag == mtag)) return (0);		if ((entry->paddr >= paddr) && (entry->paddr < paddr_end))			return (1);		}	return (0);	}	/*	 *  GetMxsAction  -  Pass the saved action to caller	 */int GetMxsAction (struct s_cpu_state *st)	{	return (st->ms_action);	}	/*	 *  DoMxsAction  -  Perform the requested action in response to	 *		    a memory system request.	 */void DoMxsAction (struct s_cpu_state *st, void *missTag, int ms_action)	{	struct	s_ldst_buffer *entry, *next_entry = 0;	switch (ms_action)		{		case ACT_UNSTALL_ICACHE:			recurse_unstall (st, 0);			return;		case ACT_DCACHE_MISS:			{			for (entry = st->ldst_head; (entry); entry = next_entry)			    {			    next_entry = entry->next;			    if (entry->missTag == missTag)				{    /* Found the corresponding entry	*/				     /* in the load/store buffer	*/				struct s_lsq *ls = entry->ls;				entry->missTag = (void *) -1;				ls->status &= ~LS_ST_STALL;				if (ls->status & LS_ST_DONE)				    {	/* In this case, the operation	*/					/* has been performed in the	*/					/* load/store buffer already.	*/				    Result ret;				    char *dataPtr;				     /* Update Mipsy PC so memstat knows                                       * where miss came from. */				     ((CPUState *) (st->mipsyPtr))->PC =                                         st->iwin_pc[ls->inum];				    if (IsLoad(ls->lstype))					ret = DCacheFetchShared(CPUNUM(st),					     ls->addr, ls->paddr,0, &dataPtr);				    else					ret = DCacheFetchExclusive(CPUNUM(st),					     ls->addr, ls->paddr,0, &dataPtr);				    if (ret != SUCCESS)					{					fprintf(stderr,					  "Cache callback messup\r\n");					ms_break (st, NULL, "ERR");					}				    entry->dataPtr = dataPtr;				    }				else				    ls->status &= ~LS_ST_CACHED;				}			    }			recurse_unstall (st, 0);  /* Just in case the icache						   * miss merged with a dcache			return;			   * miss */			}		default:			return;		}	}static int ms_lsop_uncached (struct s_cpu_state *st, struct s_lsq *ls)	{	uint	data_address;	int	i;        int err;#undef WRITEBACKREG#if UC_LATENCY > 1#define WRITEBACKREG() \	if (ls->reg == 0) \    Add_to_worklist (st, UC_LATENCY, reg0_writeback,(void *)(ls->inum)); \	else \    Add_to_worklist (st, UC_LATENCY, reg_writeback,(void *)ls->reg);#else#define WRITEBACKREG() \	if (ls->reg == 0) reg0_writeback(st,(void *)(ls->inum)); \	else reg_writeback(st, (void *) ls->reg)#endif        err = 0;	switch (ls->lstype)		{		case LD_UNSIGNED_B: {                        unsigned char c;                        err = DoUncachedRead(st,ls->addr, ls->paddr, 1, &c);                        if (err == 0) {                            Ureg(ls->reg) = c;                           WRITEBACKREG();                        } 			break;                }		case LD_UNSIGNED_H: {                        unsigned short h;                        err = DoUncachedRead(st,ls->addr,ls->paddr, 2, &h);                        if (err == 0) {                            Ureg(ls->reg) = h;                           WRITEBACKREG();                        } 			break;                }		case LD_UNSIGNED_L:			{			int shft = ((int)ls->paddr & 0x03) * 8;			data_address = ((uint)ls->paddr&0xfffffffc);                        err = DoUncachedRead(st,ls->addr,data_address, 4, &i);                        if (err == 0) {                            Ureg(ls->reg) = Ureg(ls->reg2) &						(~(0xffffffff << shft));                           Ureg(ls->reg) |= i << shft;                           WRITEBACKREG();                        }			break;			}		case LD_UNSIGNED_R:			{			int shft = (3 - ((int)ls->paddr & 0x03)) * 8;			int mask = 0xffffff00 << (24 - shft);			data_address = ((uint)ls->paddr&0xfffffffc);                        err = DoUncachedRead(st,ls->addr,data_address, 4, &i);                        if (err == 0) {                            Ureg(ls->reg) = Ureg(ls->reg2) & mask;                           Ureg(ls->reg) |= (i >> shft) & (~mask);                           WRITEBACKREG();                        }			break;			}		case LD_INTEGER_B: {                        signed char b;                        err = DoUncachedRead(st,ls->addr,ls->paddr, 1, &b);                        if (err == 0) {                            Ireg(ls->reg) = b;                           WRITEBACKREG();                        } 			break;                }		case LD_INTEGER_H: {                        short h;                        err = DoUncachedRead(st,ls->addr,ls->paddr, 2, &h);                        if (err == 0) {                            Ireg(ls->reg) = h;                           WRITEBACKREG();                        } 			break;                }		case LD_INTEGER_W:			if (ls->addr & 1) {			    int retval;			    int addr = ls->addr & ~1;			    /* Turn the lw t0, 1(a0) instruction into a conditional			     * store */			    if ((*(int *)addr) & 1) {				retval = 0;			    }  else {				(*(int *)addr) = (int) 1;				retval = 1;			    }			    Ireg(ls->reg) = retval;			    WRITEBACKREG();                            err = 0;			    break;			}                        err = DoUncachedRead(st,ls->addr,ls->paddr, 4, &i);                        if (err == 0) {                            Ireg(ls->reg) = i;                           WRITEBACKREG();                        } 			break;		case LD_FLOAT: {                        float f;                        err = DoUncachedRead(st,ls->addr,ls->paddr, 4, &f);                        if (err == 0) {                            Freg(ls->reg) = f;                           WRITEBACKREG();                        } 			break;                }		case LD_DOUBLE: {                        double d;                        err = DoUncachedRead(st,ls->addr,ls->paddr, 8, &d);                        if (err == 0) {                            Dreg(ls->reg) = d;                           WRITEBACKREG();                        } 			break;                }		case ST_INTEGER_B: {                        char b = (char) Ireg(ls->reg);                        err = DoUncachedWrite(st,ls->addr,ls->paddr, 1, 0, &b);			break;                }                case ST_INTEGER_H: {                        short h = (short) Ireg(ls->reg);                        err = DoUncachedWrite(st,ls->addr,ls->paddr, 2, 0, &h);			break;                }		case ST_INTEGER_W:                        err = DoUncachedWrite(st,ls->addr,ls->paddr, 4, 0, &Ireg(ls->reg));			break;		case ST_FLOAT:                        err = DoUncachedWrite(st,ls->addr,ls->paddr, 4, 0, &Freg(ls->reg));			break;		case ST_DOUBLE:                        err = DoUncachedWrite(st,ls->addr,ls->paddr, 8, 0, &Dreg(ls->reg));			break;		case ST_INTEGER_L:		case ST_INTEGER_R:                   /* Can't handle these yet */		default:			fprintf(stderr,				"Bad lstype passed to ms_lsop_uncached\r\n");			ms_break (st, NULL, "ERR");			break;		}        if (err != 0) {           return err;        }	if (IsStore(ls->lstype)) {	    IncStat(ST_LSOP_UNCACHED_STORE);#ifdef PRECISE#ifdef DEBUG_CHECKS	    if (st->iwin_flags[ls->inum] & IWIN_FREED)		{		fprintf(stderr, "Freed store instruction being executed!\r\n");		ms_break (st, NULL, "ERR");		}#endif /* DEBUG_CHECKS */#endif	    free_inst(st, ls->inum);	} else	    IncStat(ST_LSOP_UNCACHED_LOAD);        return err;	}	/*	 *  recurse_unstall  -  Unstall the fetch unit after a cache miss	 *			has been satisfied.	 *	 *	Return TRUE if a thread was unstalled.	 */static int recurse_unstall (struct s_cpu_state *st, int br_node)	{	BrTREE	*br;	THREAD	*th;	int ret = 0;	if (br_node < 0) return (0);	br = &st->branch_tree[br_node];	th = &st->threads[br->thread];	if (th->stall_icache)		{		th->stall_icache = 0;		UpdateStallFetch (th);		ret = 1;		}	return (ret + recurse_unstall (st, br->lchild) +			recurse_unstall (st, br->rchild));	}#ifndef MIPSY_MXS	/*	 *  is_misaligned  -  Return TRUE if the load/store instruction	 *			will cause an alignment error.	 */static int is_misaligned (int lstype, int addr)	{	switch (lstype)		{		case LD_UNSIGNED_B:			return (0);		case LD_UNSIGNED_H:			return (addr & 0x01);		case LD_UNSIGNED_L:			return (0);		case LD_UNSIGNED_R:			return (0);		case LD_INTEGER_B:			return (0);		case LD_INTEGER_H:			return (addr & 0x01);		case LD_INTEGER_W:			return (addr & 0x03 ? 1 : 0);		case LD_FLOAT:			return (addr & 0x03 ? 1 : 0);		case LD_DOUBLE:			return (addr & 0x07 ? 1 : 0);		case ST_INTEGER_B:			return (0);		case ST_INTEGER_H:			return (addr & 0x01);		case ST_INTEGER_W:			return (addr & 0x03 ? 1 : 0);		case ST_INTEGER_L:			return (0);		case ST_INTEGER_R:			return (0);		case ST_FLOAT:			return (addr & 0x03 ? 1 : 0);		case ST_DOUBLE:			return (addr & 0x07 ? 1 : 0);                default:                        break;		}	return (1);	}#endif /* !MIPSY_MXS */

⌨️ 快捷键说明

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