isa.cc revision 6378
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 94ISA::ISA(BaseCPU *_cpu) 95{ 96 cpu = _cpu; 97 init(); 98} 99 100void 101ISA::init() 102{ 103 miscRegFile.resize(NumMiscRegs); 104 bankType.resize(NumMiscRegs); 105 106 for (int i=0; i < NumMiscRegs; i++) { 107 miscRegFile[i].resize(1); 108 bankType[i] = perProcessor; 109 } 110 111 miscRegFile_WriteMask.resize(NumMiscRegs); 112 113 for (int i = 0; i < NumMiscRegs; i++) { 114 miscRegFile_WriteMask[i].push_back(0); 115 } 116 clear(0); 117} 118 119void 120ISA::clear(unsigned tid_or_vpn) 121{ 122 for(int i = 0; i < NumMiscRegs; i++) { 123 miscRegFile[i][tid_or_vpn] = 0; 124 miscRegFile_WriteMask[i][tid_or_vpn] = (long unsigned int)(-1); 125 } 126} 127 128void 129ISA::expandForMultithreading(ThreadID num_threads, unsigned num_vpes) 130{ 131 // Initialize all Per-VPE regs 132 uint32_t per_vpe_regs[] = { VPEControl, VPEConf0, VPEConf1, YQMask, 133 VPESchedule, VPEScheFBack, VPEOpt, SRSConf0, 134 SRSConf1, SRSConf2, SRSConf3, SRSConf4, 135 EBase 136 }; 137 uint32_t num_vpe_regs = sizeof(per_vpe_regs) / 4; 138 for (int i = 0; i < num_vpe_regs; i++) { 139 if (num_vpes > 1) { 140 miscRegFile[per_vpe_regs[i]].resize(num_vpes); 141 } 142 bankType[per_vpe_regs[i]] = perVirtProcessor; 143 } 144 145 // Initialize all Per-TC regs 146 uint32_t per_tc_regs[] = { Status, TCStatus, TCBind, TCRestart, TCHalt, 147 TCContext, TCSchedule, TCScheFBack, Debug, 148 LLAddr 149 }; 150 uint32_t num_tc_regs = sizeof(per_tc_regs) / 4; 151 152 for (int i = 0; i < num_tc_regs; i++) { 153 miscRegFile[per_tc_regs[i]].resize(num_threads); 154 bankType[per_tc_regs[i]] = perThreadContext; 155 } 156 157 158 if (num_vpes > 1) { 159 for (int i=1; i < num_vpes; i++) { 160 clear(i); 161 } 162 } 163 164} 165 166//@TODO: Use MIPS STYLE CONSTANTS (e.g. TCHALT_H instead of TCH_H) 167void 168ISA::reset(std::string core_name, ThreadID num_threads, 169 unsigned num_vpes, BaseCPU *_cpu) 170{ 171 DPRINTF(MipsPRA, "Resetting CP0 State with %i TCs and %i VPEs\n", 172 num_threads, num_vpes); 173 cpu = _cpu; 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(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(PRId, procId); 190 191 // Now, create Write Mask for ProcID register 192 MiscReg ProcID_Mask = 0; // Read-Only register 193 replaceBits(ProcID_Mask, 0, 32, 0); 194 setRegMask(PRId, ProcID_Mask); 195 196 // Config 197 ConfigReg cfg = readMiscRegNoEffect(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(Config, cfg); 205 // Now, create Write Mask for Config register 206 MiscReg cfg_Mask = 0x7FFF0007; 207 replaceBits(cfg_Mask, 0, 32, 0); 208 setRegMask(Config, cfg_Mask); 209 210 // Config1 211 Config1Reg cfg1 = readMiscRegNoEffect(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(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(Config1, cfg1_Mask); 231 232 // Config2 233 Config2Reg cfg2 = readMiscRegNoEffect(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(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(Config2, cfg2_Mask); 248 249 // Config3 250 Config3Reg cfg3 = readMiscRegNoEffect(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(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(Config3, cfg3_Mask); 264 265 // EBase - CPUNum 266 EBaseReg eBase = readMiscRegNoEffect(EBase); 267 eBase.cpuNum = cp.CP0_EBase_CPUNum; 268 replaceBits(eBase, 31, 31, 1); 269 setMiscRegNoEffect(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(EBase, EB_Mask); 275 276 // SRS Control - HSS (Highest Shadow Set) 277 SRSCtlReg scsCtl = readMiscRegNoEffect(SRSCtl); 278 scsCtl.hss = cp.CP0_SrsCtl_HSS; 279 setMiscRegNoEffect(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(SRSCtl, SC_Mask); 284 285 // IntCtl - IPTI, IPPCI 286 IntCtlReg intCtl = readMiscRegNoEffect(IntCtl); 287 intCtl.ipti = cp.CP0_IntCtl_IPTI; 288 intCtl.ippci = cp.CP0_IntCtl_IPPCI; 289 setMiscRegNoEffect(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(IntCtl, IC_Mask); 294 295 // Watch Hi - M - FIXME (More than 1 Watch register) 296 WatchHiReg watchHi = readMiscRegNoEffect(WatchHi0); 297 watchHi.m = cp.CP0_WatchHi_M; 298 setMiscRegNoEffect(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(WatchHi0, wh_Mask); 303 304 // Perf Ctr - M - FIXME (More than 1 PerfCnt Pair) 305 PerfCntCtlReg perfCntCtl = readMiscRegNoEffect(PerfCnt0); 306 perfCntCtl.m = cp.CP0_PerfCtr_M; 307 perfCntCtl.w = cp.CP0_PerfCtr_W; 308 setMiscRegNoEffect(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(PerfCnt0, pc_Mask); 313 314 // Random 315 setMiscRegNoEffect(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(CP0_Random, random_Mask); 320 321 // PageGrain 322 PageGrainReg pageGrain = readMiscRegNoEffect(PageGrain); 323 pageGrain.esp = cp.CP0_Config3_SP; 324 setMiscRegNoEffect(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(PageGrain, pg_Mask); 329 330 // Status 331 StatusReg status = readMiscRegNoEffect(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(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(Status, stat_Mask); 348 349 350 // MVPConf0 351 MVPConf0Reg mvpConf0 = readMiscRegNoEffect(MVPConf0); 352 mvpConf0.tca = 1; 353 mvpConf0.pvpe = num_vpes - 1; 354 mvpConf0.ptc = num_threads - 1; 355 setMiscRegNoEffect(MVPConf0, mvpConf0); 356 357 // VPEConf0 358 VPEConf0Reg vpeConf0 = readMiscRegNoEffect(VPEConf0); 359 vpeConf0.mvp = 1; 360 setMiscRegNoEffect(VPEConf0, vpeConf0); 361 362 // TCBind 363 for (ThreadID tid = 0; tid < num_threads; tid++) { 364 TCBindReg tcBind = readMiscRegNoEffect(TCBind, tid); 365 tcBind.curTC = tid; 366 setMiscRegNoEffect(TCBind, tcBind, tid); 367 } 368 // TCHalt 369 TCHaltReg tcHalt = readMiscRegNoEffect(TCHalt); 370 tcHalt.h = 0; 371 setMiscRegNoEffect(TCHalt, tcHalt); 372 373 // TCStatus 374 // Set TCStatus Activated to 1 for the initial thread that is running 375 TCStatusReg tcStatus = readMiscRegNoEffect(TCStatus); 376 tcStatus.a = 1; 377 setMiscRegNoEffect(TCStatus, 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(TCStatus, tid); 382 tcStatus.da = 1; 383 setMiscRegNoEffect(TCStatus, 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(Index, Mask); 392 393 Mask = 0x3FFFFFFF; 394 replaceBits(Mask, 0, 32, 0); 395 setRegMask(EntryLo0, Mask); 396 setRegMask(EntryLo1, Mask); 397 398 Mask = 0xFF800000; 399 replaceBits(Mask, 0, 32, 0); 400 setRegMask(Context, Mask); 401 402 Mask = 0x1FFFF800; 403 replaceBits(Mask, 0, 32, 0); 404 setRegMask(PageMask, Mask); 405 406 Mask = 0x0; 407 replaceBits(Mask, 0, 32, 0); 408 setRegMask(BadVAddr, Mask); 409 setRegMask(LLAddr, Mask); 410 411 Mask = 0x08C00300; 412 replaceBits(Mask, 0, 32, 0); 413 setRegMask(Cause, Mask); 414 415} 416 417inline unsigned 418ISA::getVPENum(ThreadID tid) 419{ 420 TCBindReg tcBind = miscRegFile[TCBind - Ctrl_Base_DepTag][tid]; 421 return tcBind.curVPE; 422} 423 424MiscReg 425ISA::readMiscRegNoEffect(int reg_idx, ThreadID tid) 426{ 427 int misc_reg = reg_idx - Ctrl_Base_DepTag; 428 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 429 ? tid : getVPENum(tid); 430 DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) (%lx).\n", 431 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 432 miscRegFile[misc_reg][reg_sel]); 433 return miscRegFile[misc_reg][reg_sel]; 434} 435 436//@TODO: MIPS MT's register view automatically connects 437// Status to TCStatus depending on current thread 438//template <class TC> 439MiscReg 440ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid) 441{ 442 int misc_reg = reg_idx - Ctrl_Base_DepTag; 443 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 444 ? tid : getVPENum(tid); 445 DPRINTF(MipsPRA, 446 "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", 447 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 448 miscRegFile[misc_reg][reg_sel]); 449 450 return miscRegFile[misc_reg][reg_sel]; 451} 452 453void 454ISA::setMiscRegNoEffect(int reg_idx, const MiscReg &val, ThreadID tid) 455{ 456 int misc_reg = reg_idx - Ctrl_Base_DepTag; 457 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 458 ? tid : getVPENum(tid); 459 DPRINTF(MipsPRA, 460 "[tid:%i]: Setting (direct set) CP0 Register:%u " 461 "Select:%u (%s) to %#x.\n", 462 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 463 464 miscRegFile[misc_reg][reg_sel] = val; 465} 466 467void 468ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid) 469{ 470 // return; 471 int misc_reg = reg_idx - Ctrl_Base_DepTag; 472 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 473 ? tid : getVPENum(tid); 474 DPRINTF(MipsPRA, 475 "[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n", 476 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 477 miscRegFile_WriteMask[misc_reg][reg_sel] = val; 478} 479 480// PROGRAMMER'S NOTES: 481// (1) Some CP0 Registers have fields that cannot 482// be overwritten. Make sure to handle those particular registers 483// with care! 484void 485ISA::setMiscReg(int reg_idx, const MiscReg &val, 486 ThreadContext *tc, ThreadID tid) 487{ 488 int misc_reg = reg_idx - Ctrl_Base_DepTag; 489 int reg_sel = (bankType[misc_reg] == perThreadContext) 490 ? tid : getVPENum(tid); 491 492 DPRINTF(MipsPRA, 493 "[tid:%i]: Setting CP0 Register:%u " 494 "Select:%u (%s) to %#x, with effect.\n", 495 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 496 497 MiscReg cp0_val = filterCP0Write(misc_reg, reg_sel, val); 498 499 miscRegFile[misc_reg][reg_sel] = cp0_val; 500 501 scheduleCP0Update(1); 502} 503 504/** 505 * This method doesn't need to adjust the Control Register Offset 506 * since it has already been done in the calling method 507 * (setRegWithEffect) 508*/ 509MiscReg 510ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) 511{ 512 MiscReg retVal = val; 513 514 // Mask off read-only regions 515 retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; 516 MiscReg curVal = miscRegFile[misc_reg][reg_sel]; 517 // Mask off current alue with inverse mask (clear writeable bits) 518 curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); 519 retVal |= curVal; // Combine the two 520 DPRINTF(MipsPRA, 521 "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, " 522 "current val: %lx, written val: %x\n", 523 miscRegFile_WriteMask[misc_reg][reg_sel], 524 ~miscRegFile_WriteMask[misc_reg][reg_sel], 525 val, miscRegFile[misc_reg][reg_sel], retVal); 526 return retVal; 527} 528 529void 530ISA::scheduleCP0Update(int delay) 531{ 532 if (!cp0Updated) { 533 cp0Updated = true; 534 535 //schedule UPDATE 536 CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0); 537 cpu->schedule(cp0_event, curTick + cpu->ticks(delay)); 538 } 539} 540 541void 542ISA::updateCPU() 543{ 544 /////////////////////////////////////////////////////////////////// 545 // 546 // EVALUATE CP0 STATE FOR MIPS MT 547 // 548 /////////////////////////////////////////////////////////////////// 549 MVPConf0Reg mvpConf0 = readMiscRegNoEffect(MVPConf0); 550 ThreadID num_threads = mvpConf0.ptc + 1; 551 552 for (ThreadID tid = 0; tid < num_threads; tid++) { 553 TCStatusReg tcStatus = readMiscRegNoEffect(TCStatus, tid); 554 TCHaltReg tcHalt = readMiscRegNoEffect(TCHalt, tid); 555 556 //@todo: add vpe/mt check here thru mvpcontrol & vpecontrol regs 557 if (tcHalt.h == 1 || tcStatus.a == 0) { 558 haltThread(cpu->getContext(tid)); 559 } else if (tcHalt.h == 0 && tcStatus.a == 1) { 560 restoreThread(cpu->getContext(tid)); 561 } 562 } 563 564 num_threads = mvpConf0.ptc + 1; 565 566 // Toggle update flag after we finished updating 567 cp0Updated = false; 568} 569 570ISA::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) 571 : Event(CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) 572{ } 573 574void 575ISA::CP0Event::process() 576{ 577 switch (cp0EventType) 578 { 579 case UpdateCP0: 580 cp0->updateCPU(); 581 break; 582 } 583} 584 585const char * 586ISA::CP0Event::description() const 587{ 588 return "Coprocessor-0 event"; 589} 590 591void 592ISA::CP0Event::scheduleEvent(int delay) 593{ 594 cpu->reschedule(this, curTick + cpu->ticks(delay), true); 595} 596 597void 598ISA::CP0Event::unscheduleEvent() 599{ 600 if (scheduled()) 601 squash(); 602} 603 604} 605