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