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