Fix up instructions to read and write control registers, and got rid of the control...
[gem5.git] / src / arch / sparc / miscregfile.cc
1 /*
2 * Copyright (c) 2003-2005 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 * Ali Saidi
30 */
31
32 #include "arch/sparc/miscregfile.hh"
33 #include "base/bitfield.hh"
34 #include "base/trace.hh"
35 #include "config/full_system.hh"
36 #include "cpu/base.hh"
37 #include "cpu/thread_context.hh"
38
39 #if FULL_SYSTEM
40 #include "arch/sparc/system.hh"
41 #endif
42
43 using namespace SparcISA;
44 using namespace std;
45
46 class Checkpoint;
47
48 //These functions map register indices to names
49 string SparcISA::getMiscRegName(RegIndex index)
50 {
51 static::string miscRegName[NumMiscRegs] =
52 {"y", "ccr", "asi", "tick", "pc", "fprs", "pcr", "pic",
53 "gsr", "softint_set", "softint_clr", "softint", "tick_cmpr",
54 "stick", "stick_cmpr",
55 "tpc", "tnpc", "tstate", "tt", "privtick", "tba", "pstate", "tl",
56 "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
57 "wstate", "gl",
58 "hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
59 "hstick_cmpr",
60 "fsr"};
61 return miscRegName[index];
62 }
63
64 void MiscRegFile::reset()
65 {
66 }
67
68 MiscReg MiscRegFile::readReg(int miscReg)
69 {
70 switch (miscReg) {
71 case MISCREG_Y:
72 return y;
73 case MISCREG_CCR:
74 return ccr;
75 case MISCREG_ASI:
76 return asi;
77 case MISCREG_FPRS:
78 return fprs;
79 case MISCREG_TICK:
80 return tick;
81 case MISCREG_PCR:
82 panic("PCR not implemented\n");
83 case MISCREG_PIC:
84 panic("PIC not implemented\n");
85 case MISCREG_GSR:
86 return gsr;
87 case MISCREG_SOFTINT:
88 return softint;
89 case MISCREG_TICK_CMPR:
90 return tick_cmpr;
91 case MISCREG_STICK:
92 return stick;
93 case MISCREG_STICK_CMPR:
94 return stick_cmpr;
95
96 /** Privilged Registers */
97 case MISCREG_TPC:
98 return tpc[tl-1];
99 case MISCREG_TNPC:
100 return tnpc[tl-1];
101 case MISCREG_TSTATE:
102 return tstate[tl-1];
103 case MISCREG_TT:
104 return tt[tl-1];
105 case MISCREG_PRIVTICK:
106 panic("Priviliged access to tick registers not implemented\n");
107 case MISCREG_TBA:
108 return tba;
109 case MISCREG_PSTATE:
110 return pstate;
111 case MISCREG_TL:
112 return tl;
113 case MISCREG_PIL:
114 return pil;
115 case MISCREG_CWP:
116 return cwp;
117 case MISCREG_CANSAVE:
118 return cansave;
119 case MISCREG_CANRESTORE:
120 return canrestore;
121 case MISCREG_CLEANWIN:
122 return cleanwin;
123 case MISCREG_OTHERWIN:
124 return otherwin;
125 case MISCREG_WSTATE:
126 return wstate;
127 case MISCREG_GL:
128 return gl;
129
130 /** Hyper privileged registers */
131 case MISCREG_HPSTATE:
132 return hpstate;
133 case MISCREG_HTSTATE:
134 return htstate[tl-1];
135 case MISCREG_HINTP:
136 panic("HINTP not implemented\n");
137 case MISCREG_HTBA:
138 return htba;
139 case MISCREG_HVER:
140 return NWindows | MaxTL << 8 | MaxGL << 16;
141 case MISCREG_STRAND_STS_REG:
142 return strandStatusReg;
143 case MISCREG_HSTICK_CMPR:
144 return hstick_cmpr;
145
146 /** Floating Point Status Register */
147 case MISCREG_FSR:
148 return fsr;
149 default:
150 panic("Miscellaneous register %d not implemented\n", miscReg);
151 }
152 }
153
154 MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc)
155 {
156 switch (miscReg) {
157 case MISCREG_TICK:
158 case MISCREG_PRIVTICK:
159 return tc->getCpuPtr()->curCycle() - (tick & mask(63)) |
160 (tick & ~(mask(63))) << 63;
161 case MISCREG_FPRS:
162 panic("FPU not implemented\n");
163 case MISCREG_PCR:
164 case MISCREG_PIC:
165 panic("Performance Instrumentation not impl\n");
166 /** Floating Point Status Register */
167 case MISCREG_FSR:
168 panic("Floating Point not implemented\n");
169 //We'll include this only in FS so we don't need the SparcSystem type around
170 //in SE.
171 #if FULL_SYSTEM
172 case MISCREG_STICK:
173 SparcSystem *sys;
174 sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
175 assert(sys != NULL);
176 return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
177 #endif
178 case MISCREG_HVER:
179 return NWindows | MaxTL << 8 | MaxGL << 16;
180 }
181 return readReg(miscReg);
182 }
183
184 void MiscRegFile::setReg(int miscReg, const MiscReg &val)
185 {
186 switch (miscReg) {
187 case MISCREG_Y:
188 y = val;
189 break;
190 case MISCREG_CCR:
191 ccr = val;
192 break;
193 case MISCREG_ASI:
194 asi = val;
195 break;
196 case MISCREG_FPRS:
197 fprs = val;
198 break;
199 case MISCREG_TICK:
200 tick = val;
201 break;
202 case MISCREG_PCR:
203 panic("PCR not implemented\n");
204 case MISCREG_PIC:
205 panic("PIC not implemented\n");
206 case MISCREG_GSR:
207 gsr = val;
208 break;
209 case MISCREG_SOFTINT:
210 softint = val;
211 break;
212 case MISCREG_TICK_CMPR:
213 tick_cmpr = val;
214 break;
215 case MISCREG_STICK:
216 stick = val;
217 break;
218 case MISCREG_STICK_CMPR:
219 stick_cmpr = val;
220 break;
221
222 /** Privilged Registers */
223 case MISCREG_TPC:
224 tpc[tl-1] = val;
225 break;
226 case MISCREG_TNPC:
227 tnpc[tl-1] = val;
228 break;
229 case MISCREG_TSTATE:
230 tstate[tl-1] = val;
231 break;
232 case MISCREG_TT:
233 tt[tl-1] = val;
234 break;
235 case MISCREG_PRIVTICK:
236 panic("Priviliged access to tick regesiters not implemented\n");
237 case MISCREG_TBA:
238 // clear lower 7 bits on writes.
239 tba = val & ULL(~0x7FFF);
240 break;
241 case MISCREG_PSTATE:
242 pstate = val;
243 break;
244 case MISCREG_TL:
245 tl = val;
246 break;
247 case MISCREG_PIL:
248 pil = val;
249 break;
250 case MISCREG_CWP:
251 cwp = val;
252 break;
253 case MISCREG_CANSAVE:
254 cansave = val;
255 break;
256 case MISCREG_CANRESTORE:
257 canrestore = val;
258 break;
259 case MISCREG_CLEANWIN:
260 cleanwin = val;
261 break;
262 case MISCREG_OTHERWIN:
263 otherwin = val;
264 break;
265 case MISCREG_WSTATE:
266 wstate = val;
267 break;
268 case MISCREG_GL:
269 gl = val;
270 break;
271
272 /** Hyper privileged registers */
273 case MISCREG_HPSTATE:
274 hpstate = val;
275 break;
276 case MISCREG_HTSTATE:
277 htstate[tl-1] = val;
278 break;
279 case MISCREG_HINTP:
280 panic("HINTP not implemented\n");
281 case MISCREG_HTBA:
282 htba = val;
283 break;
284 case MISCREG_STRAND_STS_REG:
285 strandStatusReg = val;
286 break;
287 case MISCREG_HSTICK_CMPR:
288 hstick_cmpr = val;
289 break;
290
291 /** Floating Point Status Register */
292 case MISCREG_FSR:
293 fsr = val;
294 break;
295 default:
296 panic("Miscellaneous register %d not implemented\n", miscReg);
297 }
298 }
299
300 inline void MiscRegFile::setImplicitAsis()
301 {
302 //The spec seems to use trap level to indicate the privilege level of the
303 //processor. It's unclear whether the implicit ASIs should directly depend
304 //on the trap level, or if they should really be based on the privelege
305 //bits
306 if(tl == 0)
307 {
308 implicitInstAsi = implicitDataAsi =
309 (pstate & (1 << 9)) ? ASI_PRIMARY_LITTLE : ASI_PRIMARY;
310 }
311 else if(tl <= MaxPTL)
312 {
313 implicitInstAsi = ASI_NUCLEUS;
314 implicitDataAsi = (pstate & (1 << 9)) ? ASI_NUCLEUS_LITTLE : ASI_NUCLEUS;
315 }
316 else
317 {
318 //This is supposed to force physical addresses to match the spec.
319 //It might not because of context values and partition values.
320 implicitInstAsi = implicitDataAsi = ASI_REAL;
321 }
322 }
323
324 void MiscRegFile::setRegWithEffect(int miscReg,
325 const MiscReg &val, ThreadContext * tc)
326 {
327 const uint64_t Bit64 = (1ULL << 63);
328 #if FULL_SYSTEM
329 uint64_t time;
330 SparcSystem *sys;
331 #endif
332 switch (miscReg) {
333 case MISCREG_TICK:
334 tick = tc->getCpuPtr()->curCycle() - val & ~Bit64;
335 tick |= val & Bit64;
336 break;
337 case MISCREG_FPRS:
338 //Configure the fpu based on the fprs
339 break;
340 case MISCREG_PCR:
341 //Set up performance counting based on pcr value
342 break;
343 case MISCREG_PSTATE:
344 pstate = val;
345 setImplicitAsis();
346 return;
347 case MISCREG_TL:
348 tl = val;
349 setImplicitAsis();
350 return;
351 case MISCREG_CWP:
352 tc->changeRegFileContext(CONTEXT_CWP, val);
353 break;
354 case MISCREG_GL:
355 tc->changeRegFileContext(CONTEXT_GLOBALS, val);
356 break;
357 case MISCREG_SOFTINT:
358 //We need to inject interrupts, and or notify the interrupt
359 //object that it needs to use a different interrupt level.
360 //Any newly appropriate interrupts will happen when the cpu gets
361 //around to checking for them. This might not be quite what we
362 //want.
363 break;
364 case MISCREG_SOFTINT_CLR:
365 //Do whatever this is supposed to do...
366 break;
367 case MISCREG_SOFTINT_SET:
368 //Do whatever this is supposed to do...
369 break;
370 #if FULL_SYSTEM
371 case MISCREG_TICK_CMPR:
372 if (tickCompare == NULL)
373 tickCompare = new TickCompareEvent(this, tc);
374 setReg(miscReg, val);
375 if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
376 tickCompare->deschedule();
377 time = (tick_cmpr & mask(63)) - (tick & mask(63));
378 if (!(tick_cmpr & ~mask(63)) && time > 0)
379 tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
380 break;
381 #endif
382 case MISCREG_PIL:
383 //We need to inject interrupts, and or notify the interrupt
384 //object that it needs to use a different interrupt level.
385 //Any newly appropriate interrupts will happen when the cpu gets
386 //around to checking for them. This might not be quite what we
387 //want.
388 break;
389 //We'll include this only in FS so we don't need the SparcSystem type around
390 //in SE.
391 #if FULL_SYSTEM
392 case MISCREG_STICK:
393 sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
394 assert(sys != NULL);
395 sys->sysTick = curTick/Clock::Int::ns - val & ~Bit64;
396 stick |= val & Bit64;
397 break;
398 case MISCREG_STICK_CMPR:
399 if (sTickCompare == NULL)
400 sTickCompare = new STickCompareEvent(this, tc);
401 sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
402 assert(sys != NULL);
403 if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
404 sTickCompare->deschedule();
405 time = (stick_cmpr & mask(63)) - sys->sysTick;
406 if (!(stick_cmpr & ~mask(63)) && time > 0)
407 sTickCompare->schedule(time * Clock::Int::ns);
408 break;
409 case MISCREG_HSTICK_CMPR:
410 if (hSTickCompare == NULL)
411 hSTickCompare = new HSTickCompareEvent(this, tc);
412 sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
413 assert(sys != NULL);
414 if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
415 hSTickCompare->deschedule();
416 int64_t time = (hstick_cmpr & mask(63)) - sys->sysTick;
417 if (!(hstick_cmpr & ~mask(63)) && time > 0)
418 hSTickCompare->schedule(time * Clock::Int::ns);
419 break;
420 #endif
421 }
422 setReg(miscReg, val);
423 }
424
425 void MiscRegFile::serialize(std::ostream & os)
426 {
427 SERIALIZE_SCALAR(pstate);
428 SERIALIZE_SCALAR(tba);
429 SERIALIZE_SCALAR(y);
430 SERIALIZE_SCALAR(pil);
431 SERIALIZE_SCALAR(gl);
432 SERIALIZE_SCALAR(cwp);
433 SERIALIZE_ARRAY(tt, MaxTL);
434 SERIALIZE_SCALAR(ccr);
435 SERIALIZE_SCALAR(asi);
436 SERIALIZE_SCALAR(tl);
437 SERIALIZE_ARRAY(tpc, MaxTL);
438 SERIALIZE_ARRAY(tnpc, MaxTL);
439 SERIALIZE_ARRAY(tstate, MaxTL);
440 SERIALIZE_SCALAR(tick);
441 SERIALIZE_SCALAR(cansave);
442 SERIALIZE_SCALAR(canrestore);
443 SERIALIZE_SCALAR(otherwin);
444 SERIALIZE_SCALAR(cleanwin);
445 SERIALIZE_SCALAR(wstate);
446 SERIALIZE_SCALAR(fsr);
447 SERIALIZE_SCALAR(fprs);
448 SERIALIZE_SCALAR(hpstate);
449 SERIALIZE_ARRAY(htstate, MaxTL);
450 SERIALIZE_SCALAR(htba);
451 SERIALIZE_SCALAR(hstick_cmpr);
452 SERIALIZE_SCALAR((int)implicitInstAsi);
453 SERIALIZE_SCALAR((int)implicitDataAsi);
454 }
455
456 void MiscRegFile::unserialize(Checkpoint * cp, const std::string & section)
457 {
458 UNSERIALIZE_SCALAR(pstate);
459 UNSERIALIZE_SCALAR(tba);
460 UNSERIALIZE_SCALAR(y);
461 UNSERIALIZE_SCALAR(pil);
462 UNSERIALIZE_SCALAR(gl);
463 UNSERIALIZE_SCALAR(cwp);
464 UNSERIALIZE_ARRAY(tt, MaxTL);
465 UNSERIALIZE_SCALAR(ccr);
466 UNSERIALIZE_SCALAR(asi);
467 UNSERIALIZE_SCALAR(tl);
468 UNSERIALIZE_ARRAY(tpc, MaxTL);
469 UNSERIALIZE_ARRAY(tnpc, MaxTL);
470 UNSERIALIZE_ARRAY(tstate, MaxTL);
471 UNSERIALIZE_SCALAR(tick);
472 UNSERIALIZE_SCALAR(cansave);
473 UNSERIALIZE_SCALAR(canrestore);
474 UNSERIALIZE_SCALAR(otherwin);
475 UNSERIALIZE_SCALAR(cleanwin);
476 UNSERIALIZE_SCALAR(wstate);
477 UNSERIALIZE_SCALAR(fsr);
478 UNSERIALIZE_SCALAR(fprs);
479 UNSERIALIZE_SCALAR(hpstate);
480 UNSERIALIZE_ARRAY(htstate, MaxTL);
481 UNSERIALIZE_SCALAR(htba);
482 UNSERIALIZE_SCALAR(hstick_cmpr);
483 int temp;
484 UNSERIALIZE_SCALAR(temp);
485 implicitInstAsi = (ASI)temp;
486 UNSERIALIZE_SCALAR(temp);
487 implicitDataAsi = (ASI)temp;
488 }
489
490 #if FULL_SYSTEM
491 void
492 MiscRegFile::processTickCompare(ThreadContext *tc)
493 {
494 panic("tick compare not implemented\n");
495 }
496
497 void
498 MiscRegFile::processSTickCompare(ThreadContext *tc)
499 {
500 panic("tick compare not implemented\n");
501 }
502
503 void
504 MiscRegFile::processHSTickCompare(ThreadContext *tc)
505 {
506 panic("tick compare not implemented\n");
507 }
508 #endif