isa.cc revision 11770
1/* 2 * Copyright (c) 2009 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#include "arch/mips/isa.hh" 32#include "arch/mips/mt.hh" 33#include "arch/mips/mt_constants.hh" 34#include "arch/mips/pra_constants.hh" 35#include "base/bitfield.hh" 36#include "cpu/base.hh" 37#include "cpu/thread_context.hh" 38#include "debug/MipsPRA.hh" 39#include "params/MipsISA.hh" 40 41namespace MipsISA 42{ 43 44std::string 45ISA::miscRegNames[NumMiscRegs] = 46{ 47 "Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "", 48 "Random", "VPEControl", "VPEConf0", "VPEConf1", 49 "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", 50 "EntryLo0", "TCStatus", "TCBind", "TCRestart", 51 "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", 52 "EntryLo1", "", "", "", "", "", "", "", 53 "Context", "ContextConfig", "", "", "", "", "", "", 54 "PageMask", "PageGrain", "", "", "", "", "", "", 55 "Wired", "SRSConf0", "SRCConf1", "SRSConf2", 56 "SRSConf3", "SRSConf4", "", "", 57 "HWREna", "", "", "", "", "", "", "", 58 "BadVAddr", "", "", "", "", "", "", "", 59 "Count", "", "", "", "", "", "", "", 60 "EntryHi", "", "", "", "", "", "", "", 61 "Compare", "", "", "", "", "", "", "", 62 "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "", 63 "Cause", "", "", "", "", "", "", "", 64 "EPC", "", "", "", "", "", "", "", 65 "PRId", "EBase", "", "", "", "", "", "", 66 "Config", "Config1", "Config2", "Config3", "", "", "", "", 67 "LLAddr", "", "", "", "", "", "", "", 68 "WatchLo0", "WatchLo1", "WatchLo2", "WatchLo3", 69 "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7", 70 "WatchHi0", "WatchHi1", "WatchHi2", "WatchHi3", 71 "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7", 72 "XCContext64", "", "", "", "", "", "", "", 73 "", "", "", "", "", "", "", "", 74 "", "", "", "", "", "", "", "", 75 "Debug", "TraceControl1", "TraceControl2", "UserTraceData", 76 "TraceBPC", "", "", "", 77 "DEPC", "", "", "", "", "", "", "", 78 "PerfCnt0", "PerfCnt1", "PerfCnt2", "PerfCnt3", 79 "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7", 80 "ErrCtl", "", "", "", "", "", "", "", 81 "CacheErr0", "CacheErr1", "CacheErr2", "CacheErr3", "", "", "", "", 82 "TagLo0", "DataLo1", "TagLo2", "DataLo3", 83 "TagLo4", "DataLo5", "TagLo6", "DataLo7", 84 "TagHi0", "DataHi1", "TagHi2", "DataHi3", 85 "TagHi4", "DataHi5", "TagHi6", "DataHi7", 86 "ErrorEPC", "", "", "", "", "", "", "", 87 "DESAVE", "", "", "", "", "", "", "", 88 "LLFlag" 89}; 90 91ISA::ISA(Params *p) 92 : SimObject(p), numThreads(p->num_threads), numVpes(p->num_vpes) 93{ 94 miscRegFile.resize(NumMiscRegs); 95 bankType.resize(NumMiscRegs); 96 97 for (int i=0; i < NumMiscRegs; i++) { 98 miscRegFile[i].resize(1); 99 bankType[i] = perProcessor; 100 } 101 102 miscRegFile_WriteMask.resize(NumMiscRegs); 103 104 for (int i = 0; i < NumMiscRegs; i++) { 105 miscRegFile_WriteMask[i].push_back(0); 106 } 107 108 // Initialize all Per-VPE regs 109 uint32_t per_vpe_regs[] = { MISCREG_VPE_CONTROL, 110 MISCREG_VPE_CONF0, MISCREG_VPE_CONF1, 111 MISCREG_YQMASK, 112 MISCREG_VPE_SCHEDULE, MISCREG_VPE_SCHEFBACK, 113 MISCREG_VPE_OPT, MISCREG_SRS_CONF0, 114 MISCREG_SRS_CONF1, MISCREG_SRS_CONF2, 115 MISCREG_SRS_CONF3, MISCREG_SRS_CONF4, 116 MISCREG_EBASE 117 }; 118 uint32_t num_vpe_regs = sizeof(per_vpe_regs) / 4; 119 for (int i = 0; i < num_vpe_regs; i++) { 120 if (numVpes > 1) { 121 miscRegFile[per_vpe_regs[i]].resize(numVpes); 122 } 123 bankType[per_vpe_regs[i]] = perVirtProcessor; 124 } 125 126 // Initialize all Per-TC regs 127 uint32_t per_tc_regs[] = { MISCREG_STATUS, 128 MISCREG_TC_STATUS, MISCREG_TC_BIND, 129 MISCREG_TC_RESTART, MISCREG_TC_HALT, 130 MISCREG_TC_CONTEXT, MISCREG_TC_SCHEDULE, 131 MISCREG_TC_SCHEFBACK, 132 MISCREG_DEBUG, MISCREG_LLADDR 133 }; 134 uint32_t num_tc_regs = sizeof(per_tc_regs) / 4; 135 136 for (int i = 0; i < num_tc_regs; i++) { 137 miscRegFile[per_tc_regs[i]].resize(numThreads); 138 bankType[per_tc_regs[i]] = perThreadContext; 139 } 140 141 clear(); 142} 143 144const MipsISAParams * 145ISA::params() const 146{ 147 return dynamic_cast<const Params *>(_params); 148} 149 150void 151ISA::clear() 152{ 153 for (int i = 0; i < NumMiscRegs; i++) { 154 for (int j = 0; j < miscRegFile[i].size(); j++) 155 miscRegFile[i][j] = 0; 156 157 for (int k = 0; k < miscRegFile_WriteMask[i].size(); k++) 158 miscRegFile_WriteMask[i][k] = (long unsigned int)(-1); 159 } 160} 161 162 163void 164ISA::configCP() 165{ 166 DPRINTF(MipsPRA, "Resetting CP0 State with %i TCs and %i VPEs\n", 167 numThreads, numVpes); 168 169 CoreSpecific cp; 170 panic("CP state must be set before the following code is used"); 171 172 // Do Default CP0 initialization HERE 173 174 // Do Initialization for MT cores here (eventually use 175 // core_name parameter to toggle this initialization) 176 // =================================================== 177 DPRINTF(MipsPRA, "Initializing CP0 State.... "); 178 179 PRIdReg procId = readMiscRegNoEffect(MISCREG_PRID); 180 procId.coOp = cp.CP0_PRId_CompanyOptions; 181 procId.coId = cp.CP0_PRId_CompanyID; 182 procId.procId = cp.CP0_PRId_ProcessorID; 183 procId.rev = cp.CP0_PRId_Revision; 184 setMiscRegNoEffect(MISCREG_PRID, procId); 185 186 // Now, create Write Mask for ProcID register 187 MiscReg procIDMask = 0; // Read-Only register 188 replaceBits(procIDMask, 0, 32, 0); 189 setRegMask(MISCREG_PRID, procIDMask); 190 191 // Config 192 ConfigReg cfg = readMiscRegNoEffect(MISCREG_CONFIG); 193 cfg.be = cp.CP0_Config_BE; 194 cfg.at = cp.CP0_Config_AT; 195 cfg.ar = cp.CP0_Config_AR; 196 cfg.mt = cp.CP0_Config_MT; 197 cfg.vi = cp.CP0_Config_VI; 198 cfg.m = 1; 199 setMiscRegNoEffect(MISCREG_CONFIG, cfg); 200 // Now, create Write Mask for Config register 201 MiscReg cfg_Mask = 0x7FFF0007; 202 replaceBits(cfg_Mask, 0, 32, 0); 203 setRegMask(MISCREG_CONFIG, cfg_Mask); 204 205 // Config1 206 Config1Reg cfg1 = readMiscRegNoEffect(MISCREG_CONFIG1); 207 cfg1.mmuSize = cp.CP0_Config1_MMU; 208 cfg1.is = cp.CP0_Config1_IS; 209 cfg1.il = cp.CP0_Config1_IL; 210 cfg1.ia = cp.CP0_Config1_IA; 211 cfg1.ds = cp.CP0_Config1_DS; 212 cfg1.dl = cp.CP0_Config1_DL; 213 cfg1.da = cp.CP0_Config1_DA; 214 cfg1.fp = cp.CP0_Config1_FP; 215 cfg1.ep = cp.CP0_Config1_EP; 216 cfg1.wr = cp.CP0_Config1_WR; 217 cfg1.md = cp.CP0_Config1_MD; 218 cfg1.c2 = cp.CP0_Config1_C2; 219 cfg1.pc = cp.CP0_Config1_PC; 220 cfg1.m = cp.CP0_Config1_M; 221 setMiscRegNoEffect(MISCREG_CONFIG1, cfg1); 222 // Now, create Write Mask for Config register 223 MiscReg cfg1_Mask = 0; // Read Only Register 224 replaceBits(cfg1_Mask, 0, 32, 0); 225 setRegMask(MISCREG_CONFIG1, cfg1_Mask); 226 227 // Config2 228 Config2Reg cfg2 = readMiscRegNoEffect(MISCREG_CONFIG2); 229 cfg2.tu = cp.CP0_Config2_TU; 230 cfg2.ts = cp.CP0_Config2_TS; 231 cfg2.tl = cp.CP0_Config2_TL; 232 cfg2.ta = cp.CP0_Config2_TA; 233 cfg2.su = cp.CP0_Config2_SU; 234 cfg2.ss = cp.CP0_Config2_SS; 235 cfg2.sl = cp.CP0_Config2_SL; 236 cfg2.sa = cp.CP0_Config2_SA; 237 cfg2.m = cp.CP0_Config2_M; 238 setMiscRegNoEffect(MISCREG_CONFIG2, cfg2); 239 // Now, create Write Mask for Config register 240 MiscReg cfg2_Mask = 0x7000F000; // Read Only Register 241 replaceBits(cfg2_Mask, 0, 32, 0); 242 setRegMask(MISCREG_CONFIG2, cfg2_Mask); 243 244 // Config3 245 Config3Reg cfg3 = readMiscRegNoEffect(MISCREG_CONFIG3); 246 cfg3.dspp = cp.CP0_Config3_DSPP; 247 cfg3.lpa = cp.CP0_Config3_LPA; 248 cfg3.veic = cp.CP0_Config3_VEIC; 249 cfg3.vint = cp.CP0_Config3_VInt; 250 cfg3.sp = cp.CP0_Config3_SP; 251 cfg3.mt = cp.CP0_Config3_MT; 252 cfg3.sm = cp.CP0_Config3_SM; 253 cfg3.tl = cp.CP0_Config3_TL; 254 setMiscRegNoEffect(MISCREG_CONFIG3, cfg3); 255 // Now, create Write Mask for Config register 256 MiscReg cfg3_Mask = 0; // Read Only Register 257 replaceBits(cfg3_Mask, 0, 32, 0); 258 setRegMask(MISCREG_CONFIG3, cfg3_Mask); 259 260 // EBase - CPUNum 261 EBaseReg eBase = readMiscRegNoEffect(MISCREG_EBASE); 262 eBase.cpuNum = cp.CP0_EBase_CPUNum; 263 replaceBits(eBase, 31, 31, 1); 264 setMiscRegNoEffect(MISCREG_EBASE, eBase); 265 // Now, create Write Mask for Config register 266 MiscReg EB_Mask = 0x3FFFF000;// Except Exception Base, the 267 // entire register is read only 268 replaceBits(EB_Mask, 0, 32, 0); 269 setRegMask(MISCREG_EBASE, EB_Mask); 270 271 // SRS Control - HSS (Highest Shadow Set) 272 SRSCtlReg scsCtl = readMiscRegNoEffect(MISCREG_SRSCTL); 273 scsCtl.hss = cp.CP0_SrsCtl_HSS; 274 setMiscRegNoEffect(MISCREG_SRSCTL, scsCtl); 275 // Now, create Write Mask for the SRS Ctl register 276 MiscReg SC_Mask = 0x0000F3C0; 277 replaceBits(SC_Mask, 0, 32, 0); 278 setRegMask(MISCREG_SRSCTL, SC_Mask); 279 280 // IntCtl - IPTI, IPPCI 281 IntCtlReg intCtl = readMiscRegNoEffect(MISCREG_INTCTL); 282 intCtl.ipti = cp.CP0_IntCtl_IPTI; 283 intCtl.ippci = cp.CP0_IntCtl_IPPCI; 284 setMiscRegNoEffect(MISCREG_INTCTL, intCtl); 285 // Now, create Write Mask for the IntCtl register 286 MiscReg IC_Mask = 0x000003E0; 287 replaceBits(IC_Mask, 0, 32, 0); 288 setRegMask(MISCREG_INTCTL, IC_Mask); 289 290 // Watch Hi - M - FIXME (More than 1 Watch register) 291 WatchHiReg watchHi = readMiscRegNoEffect(MISCREG_WATCHHI0); 292 watchHi.m = cp.CP0_WatchHi_M; 293 setMiscRegNoEffect(MISCREG_WATCHHI0, watchHi); 294 // Now, create Write Mask for the IntCtl register 295 MiscReg wh_Mask = 0x7FFF0FFF; 296 replaceBits(wh_Mask, 0, 32, 0); 297 setRegMask(MISCREG_WATCHHI0, wh_Mask); 298 299 // Perf Ctr - M - FIXME (More than 1 PerfCnt Pair) 300 PerfCntCtlReg perfCntCtl = readMiscRegNoEffect(MISCREG_PERFCNT0); 301 perfCntCtl.m = cp.CP0_PerfCtr_M; 302 perfCntCtl.w = cp.CP0_PerfCtr_W; 303 setMiscRegNoEffect(MISCREG_PERFCNT0, perfCntCtl); 304 // Now, create Write Mask for the IntCtl register 305 MiscReg pc_Mask = 0x00007FF; 306 replaceBits(pc_Mask, 0, 32, 0); 307 setRegMask(MISCREG_PERFCNT0, pc_Mask); 308 309 // Random 310 setMiscRegNoEffect(MISCREG_CP0_RANDOM, 63); 311 // Now, create Write Mask for the IntCtl register 312 MiscReg random_Mask = 0; 313 replaceBits(random_Mask, 0, 32, 0); 314 setRegMask(MISCREG_CP0_RANDOM, random_Mask); 315 316 // PageGrain 317 PageGrainReg pageGrain = readMiscRegNoEffect(MISCREG_PAGEGRAIN); 318 pageGrain.esp = cp.CP0_Config3_SP; 319 setMiscRegNoEffect(MISCREG_PAGEGRAIN, pageGrain); 320 // Now, create Write Mask for the IntCtl register 321 MiscReg pg_Mask = 0x10000000; 322 replaceBits(pg_Mask, 0, 32, 0); 323 setRegMask(MISCREG_PAGEGRAIN, pg_Mask); 324 325 // Status 326 StatusReg status = readMiscRegNoEffect(MISCREG_STATUS); 327 // Only CU0 and IE are modified on a reset - everything else needs 328 // to be controlled on a per CPU model basis 329 330 // Enable CP0 on reset 331 // status.cu0 = 1; 332 333 // Enable ERL bit on a reset 334 status.erl = 1; 335 // Enable BEV bit on a reset 336 status.bev = 1; 337 338 setMiscRegNoEffect(MISCREG_STATUS, status); 339 // Now, create Write Mask for the Status register 340 MiscReg stat_Mask = 0xFF78FF17; 341 replaceBits(stat_Mask, 0, 32, 0); 342 setRegMask(MISCREG_STATUS, stat_Mask); 343 344 345 // MVPConf0 346 MVPConf0Reg mvpConf0 = readMiscRegNoEffect(MISCREG_MVP_CONF0); 347 mvpConf0.tca = 1; 348 mvpConf0.pvpe = numVpes - 1; 349 mvpConf0.ptc = numThreads - 1; 350 setMiscRegNoEffect(MISCREG_MVP_CONF0, mvpConf0); 351 352 // VPEConf0 353 VPEConf0Reg vpeConf0 = readMiscRegNoEffect(MISCREG_VPE_CONF0); 354 vpeConf0.mvp = 1; 355 setMiscRegNoEffect(MISCREG_VPE_CONF0, vpeConf0); 356 357 // TCBind 358 for (ThreadID tid = 0; tid < numThreads; tid++) { 359 TCBindReg tcBind = readMiscRegNoEffect(MISCREG_TC_BIND, tid); 360 tcBind.curTC = tid; 361 setMiscRegNoEffect(MISCREG_TC_BIND, tcBind, tid); 362 } 363 // TCHalt 364 TCHaltReg tcHalt = readMiscRegNoEffect(MISCREG_TC_HALT); 365 tcHalt.h = 0; 366 setMiscRegNoEffect(MISCREG_TC_HALT, tcHalt); 367 368 // TCStatus 369 // Set TCStatus Activated to 1 for the initial thread that is running 370 TCStatusReg tcStatus = readMiscRegNoEffect(MISCREG_TC_STATUS); 371 tcStatus.a = 1; 372 setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 373 374 // Set Dynamically Allocatable bit to 1 for all other threads 375 for (ThreadID tid = 1; tid < numThreads; tid++) { 376 tcStatus = readMiscRegNoEffect(MISCREG_TC_STATUS, tid); 377 tcStatus.da = 1; 378 setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus, tid); 379 } 380 381 382 MiscReg mask = 0x7FFFFFFF; 383 384 // Now, create Write Mask for the Index register 385 replaceBits(mask, 0, 32, 0); 386 setRegMask(MISCREG_INDEX, mask); 387 388 mask = 0x3FFFFFFF; 389 replaceBits(mask, 0, 32, 0); 390 setRegMask(MISCREG_ENTRYLO0, mask); 391 setRegMask(MISCREG_ENTRYLO1, mask); 392 393 mask = 0xFF800000; 394 replaceBits(mask, 0, 32, 0); 395 setRegMask(MISCREG_CONTEXT, mask); 396 397 mask = 0x1FFFF800; 398 replaceBits(mask, 0, 32, 0); 399 setRegMask(MISCREG_PAGEMASK, mask); 400 401 mask = 0x0; 402 replaceBits(mask, 0, 32, 0); 403 setRegMask(MISCREG_BADVADDR, mask); 404 setRegMask(MISCREG_LLADDR, mask); 405 406 mask = 0x08C00300; 407 replaceBits(mask, 0, 32, 0); 408 setRegMask(MISCREG_CAUSE, mask); 409 410} 411 412inline unsigned 413ISA::getVPENum(ThreadID tid) const 414{ 415 TCBindReg tcBind = miscRegFile[MISCREG_TC_BIND][tid]; 416 return tcBind.curVPE; 417} 418 419MiscReg 420ISA::readMiscRegNoEffect(int misc_reg, ThreadID tid) const 421{ 422 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 423 ? tid : getVPENum(tid); 424 DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) (%lx).\n", 425 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 426 miscRegFile[misc_reg][reg_sel]); 427 return miscRegFile[misc_reg][reg_sel]; 428} 429 430//@TODO: MIPS MT's register view automatically connects 431// Status to TCStatus depending on current thread 432//template <class TC> 433MiscReg 434ISA::readMiscReg(int misc_reg, ThreadContext *tc, ThreadID tid) 435{ 436 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 437 ? tid : getVPENum(tid); 438 DPRINTF(MipsPRA, 439 "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", 440 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 441 miscRegFile[misc_reg][reg_sel]); 442 443 return miscRegFile[misc_reg][reg_sel]; 444} 445 446void 447ISA::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid) 448{ 449 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 450 ? tid : getVPENum(tid); 451 DPRINTF(MipsPRA, 452 "[tid:%i]: Setting (direct set) CP0 Register:%u " 453 "Select:%u (%s) to %#x.\n", 454 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 455 456 miscRegFile[misc_reg][reg_sel] = val; 457} 458 459void 460ISA::setRegMask(int misc_reg, const MiscReg &val, ThreadID tid) 461{ 462 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 463 ? tid : getVPENum(tid); 464 DPRINTF(MipsPRA, 465 "[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n", 466 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 467 miscRegFile_WriteMask[misc_reg][reg_sel] = val; 468} 469 470// PROGRAMMER'S NOTES: 471// (1) Some CP0 Registers have fields that cannot 472// be overwritten. Make sure to handle those particular registers 473// with care! 474void 475ISA::setMiscReg(int misc_reg, const MiscReg &val, 476 ThreadContext *tc, ThreadID tid) 477{ 478 int reg_sel = (bankType[misc_reg] == perThreadContext) 479 ? tid : getVPENum(tid); 480 481 DPRINTF(MipsPRA, 482 "[tid:%i]: Setting CP0 Register:%u " 483 "Select:%u (%s) to %#x, with effect.\n", 484 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 485 486 MiscReg cp0_val = filterCP0Write(misc_reg, reg_sel, val); 487 488 miscRegFile[misc_reg][reg_sel] = cp0_val; 489 490 scheduleCP0Update(tc->getCpuPtr(), Cycles(1)); 491} 492 493/** 494 * This method doesn't need to adjust the Control Register Offset 495 * since it has already been done in the calling method 496 * (setRegWithEffect) 497*/ 498MiscReg 499ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) 500{ 501 MiscReg retVal = val; 502 503 // Mask off read-only regions 504 retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; 505 MiscReg curVal = miscRegFile[misc_reg][reg_sel]; 506 // Mask off current alue with inverse mask (clear writeable bits) 507 curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); 508 retVal |= curVal; // Combine the two 509 DPRINTF(MipsPRA, 510 "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, " 511 "current val: %lx, written val: %x\n", 512 miscRegFile_WriteMask[misc_reg][reg_sel], 513 ~miscRegFile_WriteMask[misc_reg][reg_sel], 514 val, miscRegFile[misc_reg][reg_sel], retVal); 515 return retVal; 516} 517 518void 519ISA::scheduleCP0Update(BaseCPU *cpu, Cycles delay) 520{ 521 if (!cp0Updated) { 522 cp0Updated = true; 523 524 //schedule UPDATE 525 CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0); 526 cpu->schedule(cp0_event, cpu->clockEdge(delay)); 527 } 528} 529 530void 531ISA::updateCPU(BaseCPU *cpu) 532{ 533 /////////////////////////////////////////////////////////////////// 534 // 535 // EVALUATE CP0 STATE FOR MIPS MT 536 // 537 /////////////////////////////////////////////////////////////////// 538 MVPConf0Reg mvpConf0 = readMiscRegNoEffect(MISCREG_MVP_CONF0); 539 ThreadID num_threads = mvpConf0.ptc + 1; 540 541 for (ThreadID tid = 0; tid < num_threads; tid++) { 542 TCStatusReg tcStatus = readMiscRegNoEffect(MISCREG_TC_STATUS, tid); 543 TCHaltReg tcHalt = readMiscRegNoEffect(MISCREG_TC_HALT, tid); 544 545 //@todo: add vpe/mt check here thru mvpcontrol & vpecontrol regs 546 if (tcHalt.h == 1 || tcStatus.a == 0) { 547 haltThread(cpu->getContext(tid)); 548 } else if (tcHalt.h == 0 && tcStatus.a == 1) { 549 restoreThread(cpu->getContext(tid)); 550 } 551 } 552 553 num_threads = mvpConf0.ptc + 1; 554 555 // Toggle update flag after we finished updating 556 cp0Updated = false; 557} 558 559ISA::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) 560 : Event(CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) 561{ } 562 563void 564ISA::CP0Event::process() 565{ 566 switch (cp0EventType) 567 { 568 case UpdateCP0: 569 cp0->updateCPU(cpu); 570 break; 571 } 572} 573 574const char * 575ISA::CP0Event::description() const 576{ 577 return "Coprocessor-0 event"; 578} 579 580void 581ISA::CP0Event::scheduleEvent(Cycles delay) 582{ 583 cpu->reschedule(this, cpu->clockEdge(delay), true); 584} 585 586void 587ISA::CP0Event::unscheduleEvent() 588{ 589 if (scheduled()) 590 squash(); 591} 592 593} 594 595MipsISA::ISA * 596MipsISAParams::create() 597{ 598 return new MipsISA::ISA(this); 599} 600