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