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