📄 ms_ldst.c
字号:
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 + -