isa.cc revision 6334
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 MiscReg ProcID = readMiscRegNoEffect(PRId); 185 replaceBits(ProcID,PRIdCoOp_HI,PRIdCoOp_LO,cp.CP0_PRId_CompanyOptions); 186 replaceBits(ProcID,PRIdCoID_HI,PRIdCoID_LO,cp.CP0_PRId_CompanyID); 187 replaceBits(ProcID,PRIdProc_ID_HI,PRIdProc_ID_LO,cp.CP0_PRId_ProcessorID); 188 replaceBits(ProcID,PRIdRev_HI,PRIdRev_LO,cp.CP0_PRId_Revision); 189 setMiscRegNoEffect(PRId,ProcID); 190 // Now, create Write Mask for ProcID register 191 MiscReg ProcID_Mask = 0; // Read-Only register 192 replaceBits(ProcID_Mask,0,32,0); 193 setRegMask(PRId,ProcID_Mask); 194 195 // Config 196 MiscReg cfg = readMiscRegNoEffect(Config); 197 replaceBits(cfg, Config_BE_HI, Config_BE_LO, cp.CP0_Config_BE); 198 replaceBits(cfg, Config_AT_HI, Config_AT_LO, cp.CP0_Config_AT); 199 replaceBits(cfg, Config_AR_HI, Config_AR_LO, cp.CP0_Config_AR); 200 replaceBits(cfg, Config_MT_HI, Config_MT_LO, cp.CP0_Config_MT); 201 replaceBits(cfg, Config_VI_HI, Config_VI_LO, cp.CP0_Config_VI); 202 replaceBits(cfg, Config_M, 1); 203 setMiscRegNoEffect(Config, cfg); 204 // Now, create Write Mask for Config register 205 MiscReg cfg_Mask = 0x7FFF0007; 206 replaceBits(cfg_Mask,0,32,0); 207 setRegMask(Config,cfg_Mask); 208 209 // Config1 210 MiscReg cfg1 = readMiscRegNoEffect(Config1); 211 replaceBits(cfg1, Config1_MMUSize_HI, Config1_MMUSize_LO, 212 cp.CP0_Config1_MMU); 213 replaceBits(cfg1, Config1_IS_HI, Config1_IS_LO, cp.CP0_Config1_IS); 214 replaceBits(cfg1, Config1_IL_HI, Config1_IL_LO, cp.CP0_Config1_IL); 215 replaceBits(cfg1, Config1_IA_HI, Config1_IA_LO, cp.CP0_Config1_IA); 216 replaceBits(cfg1, Config1_DS_HI, Config1_DS_LO, cp.CP0_Config1_DS); 217 replaceBits(cfg1, Config1_DL_HI, Config1_DL_LO, cp.CP0_Config1_DL); 218 replaceBits(cfg1, Config1_DA_HI, Config1_DA_LO, cp.CP0_Config1_DA); 219 replaceBits(cfg1, Config1_FP_HI, Config1_FP_LO, cp.CP0_Config1_FP); 220 replaceBits(cfg1, Config1_EP_HI, Config1_EP_LO, cp.CP0_Config1_EP); 221 replaceBits(cfg1, Config1_WR_HI, Config1_WR_LO, cp.CP0_Config1_WR); 222 replaceBits(cfg1, Config1_MD_HI, Config1_MD_LO, cp.CP0_Config1_MD); 223 replaceBits(cfg1, Config1_C2_HI, Config1_C2_LO, cp.CP0_Config1_C2); 224 replaceBits(cfg1, Config1_PC_HI, Config1_PC_LO, cp.CP0_Config1_PC); 225 replaceBits(cfg1, Config1_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 MiscReg cfg2 = readMiscRegNoEffect(Config2); 234 replaceBits(cfg2, Config2_TU_HI, Config2_TU_LO, cp.CP0_Config2_TU); 235 replaceBits(cfg2, Config2_TS_HI, Config2_TS_LO, cp.CP0_Config2_TS); 236 replaceBits(cfg2, Config2_TL_HI, Config2_TL_LO, cp.CP0_Config2_TL); 237 replaceBits(cfg2, Config2_TA_HI, Config2_TA_LO, cp.CP0_Config2_TA); 238 replaceBits(cfg2, Config2_SU_HI, Config2_SU_LO, cp.CP0_Config2_SU); 239 replaceBits(cfg2, Config2_SS_HI, Config2_SS_LO, cp.CP0_Config2_SS); 240 replaceBits(cfg2, Config2_SL_HI, Config2_SL_LO, cp.CP0_Config2_SL); 241 replaceBits(cfg2, Config2_SA_HI, Config2_SA_LO, cp.CP0_Config2_SA); 242 replaceBits(cfg2, Config2_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 MiscReg cfg3 = readMiscRegNoEffect(Config3); 251 replaceBits(cfg3, Config3_DSPP_HI, Config3_DSPP_LO, cp.CP0_Config3_DSPP); 252 replaceBits(cfg3, Config3_LPA_HI, Config3_LPA_LO, cp.CP0_Config3_LPA); 253 replaceBits(cfg3, Config3_VEIC_HI, Config3_VEIC_LO, cp.CP0_Config3_VEIC); 254 replaceBits(cfg3, Config3_VINT_HI, Config3_VINT_LO, cp.CP0_Config3_VInt); 255 replaceBits(cfg3, Config3_SP_HI, Config3_SP_LO, cp.CP0_Config3_SP); 256 replaceBits(cfg3, Config3_MT_HI, Config3_MT_LO, cp.CP0_Config3_MT); 257 replaceBits(cfg3, Config3_SM_HI, Config3_SM_LO, cp.CP0_Config3_SM); 258 replaceBits(cfg3, Config3_TL_HI, Config3_TL_LO, 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 MiscReg EB = readMiscRegNoEffect(EBase); 267 replaceBits(EB, EBase_CPUNum_HI, EBase_CPUNum_LO, cp.CP0_EBase_CPUNum); 268 replaceBits(EB, 31, 31, 1); 269 setMiscRegNoEffect(EBase, EB); 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 MiscReg SC = readMiscRegNoEffect(SRSCtl); 278 replaceBits(SC, SRSCtl_HSS_HI,SRSCtl_HSS_LO,cp.CP0_SrsCtl_HSS); 279 setMiscRegNoEffect(SRSCtl, SC); 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 MiscReg IC = readMiscRegNoEffect(IntCtl); 287 replaceBits(IC, IntCtl_IPTI_HI,IntCtl_IPTI_LO,cp.CP0_IntCtl_IPTI); 288 replaceBits(IC, IntCtl_IPPCI_HI,IntCtl_IPPCI_LO,cp.CP0_IntCtl_IPPCI); 289 setMiscRegNoEffect(IntCtl, IC); 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 MiscReg WHi = readMiscRegNoEffect(WatchHi0); 297 replaceBits(WHi, WatchHi_M, cp.CP0_WatchHi_M); 298 setMiscRegNoEffect(WatchHi0, WHi); 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 MiscReg PCtr = readMiscRegNoEffect(PerfCnt0); 306 replaceBits(PCtr, PerfCntCtl_M, cp.CP0_PerfCtr_M); 307 replaceBits(PCtr, PerfCntCtl_W, cp.CP0_PerfCtr_W); 308 setMiscRegNoEffect(PerfCnt0, PCtr); 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 MiscReg random = readMiscRegNoEffect(CP0_Random); 316 random = 63; 317 setMiscRegNoEffect(CP0_Random, random); 318 // Now, create Write Mask for the IntCtl register 319 MiscReg random_Mask = 0; 320 replaceBits(random_Mask,0,32,0); 321 setRegMask(CP0_Random,random_Mask); 322 323 // PageGrain 324 MiscReg pagegrain = readMiscRegNoEffect(PageGrain); 325 replaceBits(pagegrain,PageGrain_ESP,cp.CP0_Config3_SP); 326 setMiscRegNoEffect(PageGrain, pagegrain); 327 // Now, create Write Mask for the IntCtl register 328 MiscReg pg_Mask = 0x10000000; 329 replaceBits(pg_Mask,0,32,0); 330 setRegMask(PageGrain,pg_Mask); 331 332 // Status 333 MiscReg stat = readMiscRegNoEffect(Status); 334 // Only CU0 and IE are modified on a reset - everything else needs 335 // to be controlled on a per CPU model basis 336 337 // Enable CP0 on reset 338 // replaceBits(stat, Status_CU0_HI,Status_CU0_LO, 1); 339 340 // Enable ERL bit on a reset 341 replaceBits(stat, Status_ERL_HI, Status_ERL_LO, 1); 342 343 // Enable BEV bit on a reset 344 replaceBits(stat, Status_BEV_HI, Status_BEV_LO, 1); 345 346 setMiscRegNoEffect(Status, stat); 347 // Now, create Write Mask for the Status register 348 MiscReg stat_Mask = 0xFF78FF17; 349 replaceBits(stat_Mask,0,32,0); 350 setRegMask(Status,stat_Mask); 351 352 353 // MVPConf0 354 MiscReg mvp_conf0 = readMiscRegNoEffect(MVPConf0); 355 replaceBits(mvp_conf0, MVPC0_TCA, 1); 356 replaceBits(mvp_conf0, MVPC0_PVPE_HI, MVPC0_PVPE_LO, num_vpes - 1); 357 replaceBits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO, num_threads - 1); 358 setMiscRegNoEffect(MVPConf0, mvp_conf0); 359 360 // VPEConf0 361 MiscReg vpe_conf0 = readMiscRegNoEffect(VPEConf0); 362 replaceBits(vpe_conf0, VPEC0_MVP, 1); 363 setMiscRegNoEffect(VPEConf0, vpe_conf0); 364 365 // TCBind 366 for (ThreadID tid = 0; tid < num_threads; tid++) { 367 MiscReg tc_bind = readMiscRegNoEffect(TCBind, tid); 368 replaceBits(tc_bind, TCB_CUR_TC_HI, TCB_CUR_TC_LO, tid); 369 setMiscRegNoEffect(TCBind, tc_bind, tid); 370 } 371 // TCHalt 372 MiscReg tc_halt = readMiscRegNoEffect(TCHalt); 373 replaceBits(tc_halt, TCH_H, 0); 374 setMiscRegNoEffect(TCHalt, tc_halt); 375 /*for (ThreadID tid = 1; tid < num_threads; tid++) { 376 // Set TCHalt Halt bit to 1 for all other threads 377 tc_halt = readMiscRegNoEffect(TCHalt, tid); 378 replaceBits(tc_halt, TCH_H, 1); 379 setReg(TCHalt, tc_halt, tid); 380 }*/ 381 382 // TCStatus 383 // Set TCStatus Activated to 1 for the initial thread that is running 384 MiscReg tc_status = readMiscRegNoEffect(TCStatus); 385 replaceBits(tc_status, TCS_A, 1); 386 setMiscRegNoEffect(TCStatus, tc_status); 387 388 // Set Dynamically Allocatable bit to 1 for all other threads 389 for (ThreadID tid = 1; tid < num_threads; tid++) { 390 tc_status = readMiscRegNoEffect(TCStatus, tid); 391 replaceBits(tc_status, TCSTATUS_DA, 1); 392 setMiscRegNoEffect(TCStatus, tc_status, tid); 393 } 394 395 396 MiscReg Mask = 0x7FFFFFFF; 397 398 // Now, create Write Mask for the Index register 399 replaceBits(Mask,0,32,0); 400 setRegMask(Index,Mask); 401 402 Mask = 0x3FFFFFFF; 403 replaceBits(Mask,0,32,0); 404 setRegMask(EntryLo0,Mask); 405 setRegMask(EntryLo1,Mask); 406 407 Mask = 0xFF800000; 408 replaceBits(Mask,0,32,0); 409 setRegMask(Context,Mask); 410 411 Mask = 0x1FFFF800; 412 replaceBits(Mask,0,32,0); 413 setRegMask(PageMask,Mask); 414 415 Mask = 0x0; 416 replaceBits(Mask,0,32,0); 417 setRegMask(BadVAddr,Mask); 418 setRegMask(LLAddr,Mask); 419 420 Mask = 0x08C00300; 421 replaceBits(Mask,0,32,0); 422 setRegMask(Cause,Mask); 423 424} 425 426inline unsigned 427ISA::getVPENum(ThreadID tid) 428{ 429 unsigned tc_bind = miscRegFile[TCBind - Ctrl_Base_DepTag][tid]; 430 return bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 431} 432 433MiscReg 434ISA::readMiscRegNoEffect(int reg_idx, ThreadID tid) 435{ 436 int misc_reg = reg_idx - Ctrl_Base_DepTag; 437 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 438 ? tid : getVPENum(tid); 439 DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) (%lx).\n", 440 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 441 miscRegFile[misc_reg][reg_sel]); 442 return miscRegFile[misc_reg][reg_sel]; 443} 444 445//@TODO: MIPS MT's register view automatically connects 446// Status to TCStatus depending on current thread 447//template <class TC> 448MiscReg 449ISA::readMiscReg(int reg_idx, ThreadContext *tc, ThreadID tid) 450{ 451 int misc_reg = reg_idx - Ctrl_Base_DepTag; 452 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 453 ? tid : getVPENum(tid); 454 DPRINTF(MipsPRA, 455 "Reading CP0 Register:%u Select:%u (%s) with effect (%lx).\n", 456 misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], 457 miscRegFile[misc_reg][reg_sel]); 458 459 460 switch (misc_reg) 461 { 462 default: 463 return miscRegFile[misc_reg][reg_sel]; 464 } 465} 466 467void 468ISA::setMiscRegNoEffect(int reg_idx, const MiscReg &val, ThreadID tid) 469{ 470 int misc_reg = reg_idx - Ctrl_Base_DepTag; 471 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 472 ? tid : getVPENum(tid); 473 DPRINTF(MipsPRA, 474 "[tid:%i]: Setting (direct set) CP0 Register:%u " 475 "Select:%u (%s) to %#x.\n", 476 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 477 478 miscRegFile[misc_reg][reg_sel] = val; 479} 480 481void 482ISA::setRegMask(int reg_idx, const MiscReg &val, ThreadID tid) 483{ 484 // return; 485 int misc_reg = reg_idx - Ctrl_Base_DepTag; 486 unsigned reg_sel = (bankType[misc_reg] == perThreadContext) 487 ? tid : getVPENum(tid); 488 DPRINTF(MipsPRA, 489 "[tid:%i]: Setting CP0 Register: %u Select: %u (%s) to %#x\n", 490 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 491 miscRegFile_WriteMask[misc_reg][reg_sel] = val; 492} 493 494// PROGRAMMER'S NOTES: 495// (1) Some CP0 Registers have fields that cannot 496// be overwritten. Make sure to handle those particular registers 497// with care! 498//template <class TC> 499void 500ISA::setMiscReg(int reg_idx, const MiscReg &val, 501 ThreadContext *tc, ThreadID tid) 502{ 503 int misc_reg = reg_idx - Ctrl_Base_DepTag; 504 int reg_sel = (bankType[misc_reg] == perThreadContext) 505 ? tid : getVPENum(tid); 506 507 DPRINTF(MipsPRA, 508 "[tid:%i]: Setting CP0 Register:%u " 509 "Select:%u (%s) to %#x, with effect.\n", 510 tid, misc_reg / 8, misc_reg % 8, miscRegNames[misc_reg], val); 511 512 MiscReg cp0_val = filterCP0Write(misc_reg, reg_sel, val); 513 514 miscRegFile[misc_reg][reg_sel] = cp0_val; 515 516 scheduleCP0Update(1); 517} 518 519/** 520 * This method doesn't need to adjust the Control Register Offset 521 * since it has already been done in the calling method 522 * (setRegWithEffect) 523*/ 524MiscReg 525ISA::filterCP0Write(int misc_reg, int reg_sel, const MiscReg &val) 526{ 527 MiscReg retVal = val; 528 529 // Mask off read-only regions 530 retVal &= miscRegFile_WriteMask[misc_reg][reg_sel]; 531 MiscReg curVal = miscRegFile[misc_reg][reg_sel]; 532 // Mask off current alue with inverse mask (clear writeable bits) 533 curVal &= (~miscRegFile_WriteMask[misc_reg][reg_sel]); 534 retVal |= curVal; // Combine the two 535 DPRINTF(MipsPRA, 536 "filterCP0Write: Mask: %lx, Inverse Mask: %lx, write Val: %x, " 537 "current val: %lx, written val: %x\n", 538 miscRegFile_WriteMask[misc_reg][reg_sel], 539 ~miscRegFile_WriteMask[misc_reg][reg_sel], 540 val, miscRegFile[misc_reg][reg_sel], retVal); 541 return retVal; 542} 543 544void 545ISA::scheduleCP0Update(int delay) 546{ 547 if (!cp0Updated) { 548 cp0Updated = true; 549 550 //schedule UPDATE 551 CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0); 552 cpu->schedule(cp0_event, curTick + cpu->ticks(delay)); 553 } 554} 555 556void 557ISA::updateCPU() 558{ 559 /////////////////////////////////////////////////////////////////// 560 // 561 // EVALUATE CP0 STATE FOR MIPS MT 562 // 563 /////////////////////////////////////////////////////////////////// 564 unsigned mvp_conf0 = readMiscRegNoEffect(MVPConf0); 565 ThreadID num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 566 567 for (ThreadID tid = 0; tid < num_threads; tid++) { 568 MiscReg tc_status = readMiscRegNoEffect(TCStatus, tid); 569 MiscReg tc_halt = readMiscRegNoEffect(TCHalt, tid); 570 571 //@todo: add vpe/mt check here thru mvpcontrol & vpecontrol regs 572 if (bits(tc_halt, TCH_H) == 1 || bits(tc_status, TCS_A) == 0) { 573 haltThread(cpu->getContext(tid)); 574 } else if (bits(tc_halt, TCH_H) == 0 && bits(tc_status, TCS_A) == 1) { 575 restoreThread(cpu->getContext(tid)); 576 } 577 } 578 579 num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 580 581 // Toggle update flag after we finished updating 582 cp0Updated = false; 583} 584 585ISA::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type) 586 : Event(CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type) 587{ } 588 589void 590ISA::CP0Event::process() 591{ 592 switch (cp0EventType) 593 { 594 case UpdateCP0: 595 cp0->updateCPU(); 596 break; 597 } 598 599 //cp0EventRemoveList.push(this); 600} 601 602const char * 603ISA::CP0Event::description() const 604{ 605 return "Coprocessor-0 event"; 606} 607 608void 609ISA::CP0Event::scheduleEvent(int delay) 610{ 611 cpu->reschedule(this, curTick + cpu->ticks(delay), true); 612} 613 614void 615ISA::CP0Event::unscheduleEvent() 616{ 617 if (scheduled()) 618 squash(); 619} 620 621} 622