isa.cc revision 8147
12086SN/A/* 22086SN/A * Copyright (c) 2009 The Regents of The University of Michigan 32086SN/A * All rights reserved. 42086SN/A * 52086SN/A * Redistribution and use in source and binary forms, with or without 62086SN/A * modification, are permitted provided that the following conditions are 72086SN/A * met: redistributions of source code must retain the above copyright 82086SN/A * notice, this list of conditions and the following disclaimer; 92086SN/A * redistributions in binary form must reproduce the above copyright 102086SN/A * notice, this list of conditions and the following disclaimer in the 112086SN/A * documentation and/or other materials provided with the distribution; 122086SN/A * neither the name of the copyright holders nor the names of its 132086SN/A * contributors may be used to endorse or promote products derived from 142086SN/A * this software without specific prior written permission. 152086SN/A * 162086SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172086SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182086SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192086SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202086SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212086SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222086SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232086SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242086SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252086SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262086SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272086SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Gabe Black 292665Ssaidi@eecs.umich.edu */ 302665Ssaidi@eecs.umich.edu 312086SN/A#include "arch/mips/isa.hh" 324202Sbinkertn@umich.edu#include "arch/mips/mt_constants.hh" 332086SN/A#include "arch/mips/mt.hh" 344202Sbinkertn@umich.edu#include "arch/mips/pra_constants.hh" 354202Sbinkertn@umich.edu#include "base/bitfield.hh" 369022Sgblack@eecs.umich.edu#include "cpu/base.hh" 374202Sbinkertn@umich.edu#include "cpu/thread_context.hh" 388745Sgblack@eecs.umich.edu 396313Sgblack@eecs.umich.edunamespace MipsISA 408778Sgblack@eecs.umich.edu{ 418778Sgblack@eecs.umich.edu 428778Sgblack@eecs.umich.edustd::string 436365Sgblack@eecs.umich.eduISA::miscRegNames[NumMiscRegs] = 444997Sgblack@eecs.umich.edu{ 458778Sgblack@eecs.umich.edu "Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "", 464202Sbinkertn@umich.edu "Random", "VPEControl", "VPEConf0", "VPEConf1", 478778Sgblack@eecs.umich.edu "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", 488778Sgblack@eecs.umich.edu "EntryLo0", "TCStatus", "TCBind", "TCRestart", 498778Sgblack@eecs.umich.edu "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", 504997Sgblack@eecs.umich.edu "EntryLo1", "", "", "", "", "", "", "", 518747Sgblack@eecs.umich.edu "Context", "ContextConfig", "", "", "", "", "", "", 524826Ssaidi@eecs.umich.edu "PageMask", "PageGrain", "", "", "", "", "", "", 538760Sgblack@eecs.umich.edu "Wired", "SRSConf0", "SRCConf1", "SRSConf2", 542086SN/A "SRSConf3", "SRSConf4", "", "", 558745Sgblack@eecs.umich.edu "HWREna", "", "", "", "", "", "", "", 569384SAndreas.Sandberg@arm.com "BadVAddr", "", "", "", "", "", "", "", 576365Sgblack@eecs.umich.edu "Count", "", "", "", "", "", "", "", 588778Sgblack@eecs.umich.edu "EntryHi", "", "", "", "", "", "", "", 598745Sgblack@eecs.umich.edu "Compare", "", "", "", "", "", "", "", 606365Sgblack@eecs.umich.edu "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "", 618335Snate@binkert.org "Cause", "", "", "", "", "", "", "", 628335Snate@binkert.org "EPC", "", "", "", "", "", "", "", 634997Sgblack@eecs.umich.edu "PRId", "EBase", "", "", "", "", "", "", 6410196SCurtis.Dunham@arm.com "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