2 * Copyright (c) 2009 The Regents of The University of Michigan
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.
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.
31 #include "arch/sparc/isa.hh"
33 #include "arch/sparc/asi.hh"
34 #include "arch/sparc/decoder.hh"
35 #include "base/bitfield.hh"
36 #include "base/trace.hh"
37 #include "cpu/base.hh"
38 #include "cpu/thread_context.hh"
39 #include "debug/MiscRegs.hh"
40 #include "debug/Timer.hh"
41 #include "params/SparcISA.hh"
61 static const PSTATE PstateMask
= buildPstateMask();
73 const SparcISAParams
*
76 return dynamic_cast<const Params
*>(_params
);
82 installGlobals(gl
, CurrentGlobalsOffset
);
83 installWindow(cwp
, CurrentWindowOffset
);
84 // Microcode registers.
85 for (int i
= 0; i
< NumMicroIntRegs
; i
++)
86 intRegMap
[MicroIntOffset
+ i
] = i
+ TotalGlobals
+ NWindows
* 16;
87 installGlobals(gl
, NextGlobalsOffset
);
88 installWindow(cwp
- 1, NextWindowOffset
);
89 installGlobals(gl
, PreviousGlobalsOffset
);
90 installWindow(cwp
+ 1, PreviousWindowOffset
);
94 ISA::installWindow(int cwp
, int offset
)
96 assert(offset
>= 0 && offset
+ NumWindowedRegs
<= NumIntRegs
);
97 RegIndex
*mapChunk
= intRegMap
+ offset
;
98 for (int i
= 0; i
< NumWindowedRegs
; i
++)
99 mapChunk
[i
] = TotalGlobals
+
100 ((i
- cwp
* RegsPerWindow
+ TotalWindowed
) % (TotalWindowed
));
104 ISA::installGlobals(int gl
, int offset
)
106 assert(offset
>= 0 && offset
+ NumGlobalRegs
<= NumIntRegs
);
107 RegIndex
*mapChunk
= intRegMap
+ offset
;
109 for (int i
= 1; i
< NumGlobalRegs
; i
++)
110 mapChunk
[i
] = i
+ gl
* NumGlobalRegs
;
130 memset(tpc
, 0, sizeof(tpc
));
131 memset(tnpc
, 0, sizeof(tnpc
));
132 memset(tstate
, 0, sizeof(tstate
));
133 memset(tt
, 0, sizeof(tt
));
143 // In a T1, bit 11 is apparently always 1
146 memset(htstate
, 0, sizeof(htstate
));
150 // This is set this way in Legion for some reason
151 strandStatusReg
= 0x50000;
159 memset(scratchPad
, 0, sizeof(scratchPad
));
170 // If one of these events is active, it's not obvious to me how to get
171 // rid of it cleanly. For now we'll just assert that they're not.
172 if (tickCompare
!= NULL
&& sTickCompare
!= NULL
&& hSTickCompare
!= NULL
)
173 panic("Tick comparison event active when clearing the ISA object.\n");
177 ISA::readMiscRegNoEffect(int miscReg
) const
180 // The three miscRegs are moved up from the switch statement
181 // due to more frequent calls.
183 if (miscReg
== MISCREG_GL
)
185 if (miscReg
== MISCREG_CWP
)
187 if (miscReg
== MISCREG_TLB_DATA
) {
188 /* Package up all the data for the tlb:
189 * 6666555555555544444444443333333333222222222211111111110000000000
190 * 3210987654321098765432109876543210987654321098765432109876543210
191 * secContext | priContext | |tl|partid| |||||^hpriv
198 return (uint64_t)hpstate
.hpriv
|
199 (uint64_t)hpstate
.red
<< 1 |
200 (uint64_t)pstate
.priv
<< 2 |
201 (uint64_t)pstate
.am
<< 3 |
202 bits((uint64_t)lsuCtrlReg
,3,2) << 4 |
203 bits((uint64_t)partId
,7,0) << 8 |
204 bits((uint64_t)tl
,2,0) << 16 |
205 (uint64_t)priContext
<< 32 |
206 (uint64_t)secContext
<< 48;
210 // case MISCREG_TLB_DATA:
211 // [original contents see above]
223 panic("PCR not implemented\n");
225 panic("PIC not implemented\n");
228 case MISCREG_SOFTINT
:
230 case MISCREG_TICK_CMPR
:
234 case MISCREG_STICK_CMPR
:
237 /** Privilged Registers */
246 case MISCREG_PRIVTICK
:
247 panic("Priviliged access to tick registers not implemented\n");
251 return (RegVal
)pstate
;
259 // case MISCREG_CANSAVE:
261 // case MISCREG_CANRESTORE:
262 // return canrestore;
263 // case MISCREG_CLEANWIN:
265 // case MISCREG_OTHERWIN:
267 // case MISCREG_WSTATE:
272 /** Hyper privileged registers */
273 case MISCREG_HPSTATE
:
274 return (RegVal
)hpstate
;
275 case MISCREG_HTSTATE
:
276 return htstate
[tl
-1];
281 case MISCREG_STRAND_STS_REG
:
282 return strandStatusReg
;
283 case MISCREG_HSTICK_CMPR
:
286 /** Floating Point Status Register */
288 DPRINTF(MiscRegs
, "FSR read as: %#x\n", fsr
);
291 case MISCREG_MMU_P_CONTEXT
:
293 case MISCREG_MMU_S_CONTEXT
:
295 case MISCREG_MMU_PART_ID
:
297 case MISCREG_MMU_LSU_CTRL
:
300 case MISCREG_SCRATCHPAD_R0
:
301 return scratchPad
[0];
302 case MISCREG_SCRATCHPAD_R1
:
303 return scratchPad
[1];
304 case MISCREG_SCRATCHPAD_R2
:
305 return scratchPad
[2];
306 case MISCREG_SCRATCHPAD_R3
:
307 return scratchPad
[3];
308 case MISCREG_SCRATCHPAD_R4
:
309 return scratchPad
[4];
310 case MISCREG_SCRATCHPAD_R5
:
311 return scratchPad
[5];
312 case MISCREG_SCRATCHPAD_R6
:
313 return scratchPad
[6];
314 case MISCREG_SCRATCHPAD_R7
:
315 return scratchPad
[7];
316 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
317 return cpu_mondo_head
;
318 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
319 return cpu_mondo_tail
;
320 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
321 return dev_mondo_head
;
322 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
323 return dev_mondo_tail
;
324 case MISCREG_QUEUE_RES_ERROR_HEAD
:
325 return res_error_head
;
326 case MISCREG_QUEUE_RES_ERROR_TAIL
:
327 return res_error_tail
;
328 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
329 return nres_error_head
;
330 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
331 return nres_error_tail
;
333 panic("Miscellaneous register %d not implemented\n", miscReg
);
338 ISA::readMiscReg(int miscReg
, ThreadContext
* tc
)
341 // tick and stick are aliased to each other in niagra
342 // well store the tick data in stick and the interrupt bit in tick
345 case MISCREG_PRIVTICK
:
346 // I'm not sure why legion ignores the lowest two bits, but we'll go
348 // change from curCycle() to instCount() until we're done with legion
349 DPRINTF(Timer
, "Instruction Count when TICK read: %#X stick=%#X\n",
350 tc
->getCpuPtr()->instCount(), stick
);
351 return mbits(tc
->getCpuPtr()->instCount() + (int64_t)stick
,62,2) |
354 // in legion if fp is enabled du and dl are set
358 panic("Performance Instrumentation not impl\n");
359 case MISCREG_SOFTINT_CLR
:
360 case MISCREG_SOFTINT_SET
:
361 panic("Can read from softint clr/set\n");
362 case MISCREG_SOFTINT
:
363 case MISCREG_TICK_CMPR
:
364 case MISCREG_STICK_CMPR
:
366 case MISCREG_HTSTATE
:
369 case MISCREG_STRAND_STS_REG
:
370 case MISCREG_HSTICK_CMPR
:
371 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
372 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
373 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
374 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
375 case MISCREG_QUEUE_RES_ERROR_HEAD
:
376 case MISCREG_QUEUE_RES_ERROR_TAIL
:
377 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
378 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
379 case MISCREG_HPSTATE
:
380 return readFSReg(miscReg
, tc
);
382 return readMiscRegNoEffect(miscReg
);
386 ISA::setMiscRegNoEffect(int miscReg
, RegVal val
)
405 panic("PCR not implemented\n");
407 panic("PIC not implemented\n");
411 case MISCREG_SOFTINT
:
414 case MISCREG_TICK_CMPR
:
420 case MISCREG_STICK_CMPR
:
424 /** Privilged Registers */
437 case MISCREG_PRIVTICK
:
438 panic("Priviliged access to tick regesiters not implemented\n");
440 // clear lower 7 bits on writes.
441 tba
= val
& ULL(~0x7FFF);
444 pstate
= (val
& PstateMask
);
455 // case MISCREG_CANSAVE:
458 // case MISCREG_CANRESTORE:
461 // case MISCREG_CLEANWIN:
464 // case MISCREG_OTHERWIN:
467 // case MISCREG_WSTATE:
474 /** Hyper privileged registers */
475 case MISCREG_HPSTATE
:
478 case MISCREG_HTSTATE
:
487 case MISCREG_STRAND_STS_REG
:
488 strandStatusReg
= val
;
490 case MISCREG_HSTICK_CMPR
:
494 /** Floating Point Status Register */
497 DPRINTF(MiscRegs
, "FSR written with: %#x\n", fsr
);
500 case MISCREG_MMU_P_CONTEXT
:
503 case MISCREG_MMU_S_CONTEXT
:
506 case MISCREG_MMU_PART_ID
:
509 case MISCREG_MMU_LSU_CTRL
:
513 case MISCREG_SCRATCHPAD_R0
:
516 case MISCREG_SCRATCHPAD_R1
:
519 case MISCREG_SCRATCHPAD_R2
:
522 case MISCREG_SCRATCHPAD_R3
:
525 case MISCREG_SCRATCHPAD_R4
:
528 case MISCREG_SCRATCHPAD_R5
:
531 case MISCREG_SCRATCHPAD_R6
:
534 case MISCREG_SCRATCHPAD_R7
:
537 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
538 cpu_mondo_head
= val
;
540 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
541 cpu_mondo_tail
= val
;
543 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
544 dev_mondo_head
= val
;
546 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
547 dev_mondo_tail
= val
;
549 case MISCREG_QUEUE_RES_ERROR_HEAD
:
550 res_error_head
= val
;
552 case MISCREG_QUEUE_RES_ERROR_TAIL
:
553 res_error_tail
= val
;
555 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
556 nres_error_head
= val
;
558 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
559 nres_error_tail
= val
;
562 panic("Miscellaneous register %d not implemented\n", miscReg
);
567 ISA::setMiscReg(int miscReg
, RegVal val
, ThreadContext
* tc
)
569 RegVal new_val
= val
;
573 tc
->getDecoderPtr()->setContext(val
);
577 // stick and tick are same thing on niagra
578 // use stick for offset and tick for holding intrrupt bit
579 stick
= mbits(val
,62,0) - tc
->getCpuPtr()->instCount();
580 tick
= mbits(val
,63,63);
581 DPRINTF(Timer
, "Writing TICK=%#X\n", val
);
584 // Configure the fpu based on the fprs
587 // Set up performance counting based on pcr value
590 pstate
= val
& PstateMask
;
595 if (hpstate
.tlz
&& tl
== 0 && !hpstate
.hpriv
)
596 tc
->getCpuPtr()->postInterrupt(0, IT_TRAP_LEVEL_ZERO
, 0);
598 tc
->getCpuPtr()->clearInterrupt(0, IT_TRAP_LEVEL_ZERO
, 0);
602 new_val
= val
>= NWindows
? NWindows
- 1 : val
;
604 new_val
= NWindows
- 1;
606 installWindow(new_val
, CurrentWindowOffset
);
607 installWindow(new_val
- 1, NextWindowOffset
);
608 installWindow(new_val
+ 1, PreviousWindowOffset
);
611 installGlobals(val
, CurrentGlobalsOffset
);
612 installGlobals(val
, NextGlobalsOffset
);
613 installGlobals(val
, PreviousGlobalsOffset
);
616 case MISCREG_SOFTINT
:
617 case MISCREG_SOFTINT_SET
:
618 case MISCREG_SOFTINT_CLR
:
619 case MISCREG_TICK_CMPR
:
620 case MISCREG_STICK_CMPR
:
622 case MISCREG_HTSTATE
:
625 case MISCREG_STRAND_STS_REG
:
626 case MISCREG_HSTICK_CMPR
:
627 case MISCREG_QUEUE_CPU_MONDO_HEAD
:
628 case MISCREG_QUEUE_CPU_MONDO_TAIL
:
629 case MISCREG_QUEUE_DEV_MONDO_HEAD
:
630 case MISCREG_QUEUE_DEV_MONDO_TAIL
:
631 case MISCREG_QUEUE_RES_ERROR_HEAD
:
632 case MISCREG_QUEUE_RES_ERROR_TAIL
:
633 case MISCREG_QUEUE_NRES_ERROR_HEAD
:
634 case MISCREG_QUEUE_NRES_ERROR_TAIL
:
635 case MISCREG_HPSTATE
:
636 setFSReg(miscReg
, val
, tc
);
639 setMiscRegNoEffect(miscReg
, new_val
);
643 ISA::serialize(CheckpointOut
&cp
) const
645 SERIALIZE_SCALAR(asi
);
646 SERIALIZE_SCALAR(tick
);
647 SERIALIZE_SCALAR(fprs
);
648 SERIALIZE_SCALAR(gsr
);
649 SERIALIZE_SCALAR(softint
);
650 SERIALIZE_SCALAR(tick_cmpr
);
651 SERIALIZE_SCALAR(stick
);
652 SERIALIZE_SCALAR(stick_cmpr
);
653 SERIALIZE_ARRAY(tpc
,MaxTL
);
654 SERIALIZE_ARRAY(tnpc
,MaxTL
);
655 SERIALIZE_ARRAY(tstate
,MaxTL
);
656 SERIALIZE_ARRAY(tt
,MaxTL
);
657 SERIALIZE_SCALAR(tba
);
658 SERIALIZE_SCALAR(pstate
);
659 SERIALIZE_SCALAR(tl
);
660 SERIALIZE_SCALAR(pil
);
661 SERIALIZE_SCALAR(cwp
);
662 SERIALIZE_SCALAR(gl
);
663 SERIALIZE_SCALAR(hpstate
);
664 SERIALIZE_ARRAY(htstate
,MaxTL
);
665 SERIALIZE_SCALAR(hintp
);
666 SERIALIZE_SCALAR(htba
);
667 SERIALIZE_SCALAR(hstick_cmpr
);
668 SERIALIZE_SCALAR(strandStatusReg
);
669 SERIALIZE_SCALAR(fsr
);
670 SERIALIZE_SCALAR(priContext
);
671 SERIALIZE_SCALAR(secContext
);
672 SERIALIZE_SCALAR(partId
);
673 SERIALIZE_SCALAR(lsuCtrlReg
);
674 SERIALIZE_ARRAY(scratchPad
,8);
675 SERIALIZE_SCALAR(cpu_mondo_head
);
676 SERIALIZE_SCALAR(cpu_mondo_tail
);
677 SERIALIZE_SCALAR(dev_mondo_head
);
678 SERIALIZE_SCALAR(dev_mondo_tail
);
679 SERIALIZE_SCALAR(res_error_head
);
680 SERIALIZE_SCALAR(res_error_tail
);
681 SERIALIZE_SCALAR(nres_error_head
);
682 SERIALIZE_SCALAR(nres_error_tail
);
683 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
684 ThreadContext
*tc
= NULL
;
687 bool tick_intr_sched
= true;
690 tc
= tickCompare
->getTC();
691 else if (sTickCompare
)
692 tc
= sTickCompare
->getTC();
693 else if (hSTickCompare
)
694 tc
= hSTickCompare
->getTC();
696 tick_intr_sched
= false;
698 SERIALIZE_SCALAR(tick_intr_sched
);
701 cpu
= tc
->getCpuPtr();
702 tc_num
= cpu
->findContext(tc
);
703 if (tickCompare
&& tickCompare
->scheduled())
704 tick_cmp
= tickCompare
->when();
705 if (sTickCompare
&& sTickCompare
->scheduled())
706 stick_cmp
= sTickCompare
->when();
707 if (hSTickCompare
&& hSTickCompare
->scheduled())
708 hstick_cmp
= hSTickCompare
->when();
710 SERIALIZE_OBJPTR(cpu
);
711 SERIALIZE_SCALAR(tc_num
);
712 SERIALIZE_SCALAR(tick_cmp
);
713 SERIALIZE_SCALAR(stick_cmp
);
714 SERIALIZE_SCALAR(hstick_cmp
);
719 ISA::unserialize(CheckpointIn
&cp
)
721 UNSERIALIZE_SCALAR(asi
);
722 UNSERIALIZE_SCALAR(tick
);
723 UNSERIALIZE_SCALAR(fprs
);
724 UNSERIALIZE_SCALAR(gsr
);
725 UNSERIALIZE_SCALAR(softint
);
726 UNSERIALIZE_SCALAR(tick_cmpr
);
727 UNSERIALIZE_SCALAR(stick
);
728 UNSERIALIZE_SCALAR(stick_cmpr
);
729 UNSERIALIZE_ARRAY(tpc
,MaxTL
);
730 UNSERIALIZE_ARRAY(tnpc
,MaxTL
);
731 UNSERIALIZE_ARRAY(tstate
,MaxTL
);
732 UNSERIALIZE_ARRAY(tt
,MaxTL
);
733 UNSERIALIZE_SCALAR(tba
);
736 UNSERIALIZE_SCALAR(pstate
);
737 this->pstate
= pstate
;
739 UNSERIALIZE_SCALAR(tl
);
740 UNSERIALIZE_SCALAR(pil
);
741 UNSERIALIZE_SCALAR(cwp
);
742 UNSERIALIZE_SCALAR(gl
);
746 UNSERIALIZE_SCALAR(hpstate
);
747 this->hpstate
= hpstate
;
749 UNSERIALIZE_ARRAY(htstate
,MaxTL
);
750 UNSERIALIZE_SCALAR(hintp
);
751 UNSERIALIZE_SCALAR(htba
);
752 UNSERIALIZE_SCALAR(hstick_cmpr
);
753 UNSERIALIZE_SCALAR(strandStatusReg
);
754 UNSERIALIZE_SCALAR(fsr
);
755 UNSERIALIZE_SCALAR(priContext
);
756 UNSERIALIZE_SCALAR(secContext
);
757 UNSERIALIZE_SCALAR(partId
);
758 UNSERIALIZE_SCALAR(lsuCtrlReg
);
759 UNSERIALIZE_ARRAY(scratchPad
,8);
760 UNSERIALIZE_SCALAR(cpu_mondo_head
);
761 UNSERIALIZE_SCALAR(cpu_mondo_tail
);
762 UNSERIALIZE_SCALAR(dev_mondo_head
);
763 UNSERIALIZE_SCALAR(dev_mondo_tail
);
764 UNSERIALIZE_SCALAR(res_error_head
);
765 UNSERIALIZE_SCALAR(res_error_tail
);
766 UNSERIALIZE_SCALAR(nres_error_head
);
767 UNSERIALIZE_SCALAR(nres_error_tail
);
769 Tick tick_cmp
= 0, stick_cmp
= 0, hstick_cmp
= 0;
770 ThreadContext
*tc
= NULL
;
773 bool tick_intr_sched
;
774 UNSERIALIZE_SCALAR(tick_intr_sched
);
775 if (tick_intr_sched
) {
776 UNSERIALIZE_OBJPTR(cpu
);
778 UNSERIALIZE_SCALAR(tc_num
);
779 UNSERIALIZE_SCALAR(tick_cmp
);
780 UNSERIALIZE_SCALAR(stick_cmp
);
781 UNSERIALIZE_SCALAR(hstick_cmp
);
782 tc
= cpu
->getContext(tc_num
);
785 tickCompare
= new TickCompareEvent(this, tc
);
786 schedule(tickCompare
, tick_cmp
);
789 sTickCompare
= new STickCompareEvent(this, tc
);
790 schedule(sTickCompare
, stick_cmp
);
793 hSTickCompare
= new HSTickCompareEvent(this, tc
);
794 schedule(hSTickCompare
, hstick_cmp
);
804 SparcISAParams::create()
806 return new SparcISA::ISA(this);