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