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