registers.hh revision 2665
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#ifndef __ARCH_SPARC_REGFILE_HH__
33#define __ARCH_SPARC_REGFILE_HH__
34
35#include "arch/sparc/exceptions.hh"
36#include "arch/sparc/faults.hh"
37#include "base/trace.hh"
38#include "sim/byteswap.hh"
39#include "cpu/cpuevent.hh"
40#include "sim/host.hh"
41
42class Checkpoint;
43
44namespace SparcISA
45{
46
47    typedef uint8_t  RegIndex;
48
49    // MAXTL - maximum trap level
50    const int MaxPTL = 2;
51    const int MaxTL  = 6;
52    const int MaxGL  = 3;
53    const int MaxPGL = 2;
54
55    // NWINDOWS - number of register windows, can be 3 to 32
56    const int NWindows = 32;
57
58
59    const int AsrStart = 0;
60    const int PrStart = 32;
61    const int HprStart = 64;
62    const int MiscStart = 96;
63
64
65    const uint64_t Bit64 = 0x8000000000000000;
66
67    class IntRegFile
68    {
69      protected:
70        static const int FrameOffsetBits = 3;
71        static const int FrameNumBits = 2;
72
73        static const int RegsPerFrame = 1 << FrameOffsetBits;
74        static const int FrameNumMask =
75                (FrameNumBits == sizeof(int)) ?
76                (unsigned int)(-1) :
77                (1 << FrameNumBits) - 1;
78        static const int FrameOffsetMask =
79                (FrameOffsetBits == sizeof(int)) ?
80                (unsigned int)(-1) :
81                (1 << FrameOffsetBits) - 1;
82
83        IntReg regGlobals[MaxGL][RegsPerFrame];
84        IntReg regSegments[2 * NWindows][RegsPerFrame];
85
86        enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames};
87
88        IntReg * regView[NumFrames];
89
90        static const int RegGlobalOffset = 0;
91        static const int FrameOffset = MaxGL * RegsPerFrame;
92        int offset[NumFrames];
93
94      public:
95
96        int flattenIndex(int reg)
97        {
98            int flatIndex = offset[reg >> FrameOffsetBits]
99                | (reg & FrameOffsetMask);
100            DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex);
101            return flatIndex;
102        }
103
104        void clear()
105        {
106            int x;
107            for (x = 0; x < MaxGL; x++)
108                memset(regGlobals[x], 0, sizeof(regGlobals[x]));
109            for(int x = 0; x < 2 * NWindows; x++)
110                bzero(regSegments[x], sizeof(regSegments[x]));
111        }
112
113        IntRegFile()
114        {
115            offset[Globals] = 0;
116            regView[Globals] = regGlobals[0];
117            setCWP(0);
118            clear();
119        }
120
121        IntReg readReg(int intReg)
122        {
123            IntReg val =
124                regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask];
125            DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val);
126            return val;
127        }
128
129        Fault setReg(int intReg, const IntReg &val)
130        {
131            if(intReg)
132                DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val);
133            regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val;
134            return NoFault;
135        }
136
137        //This doesn't effect the actual CWP register.
138        //It's purpose is to adjust the view of the register file
139        //to what it would be if CWP = cwp.
140        void setCWP(int cwp)
141        {
142            int index = ((NWindows - cwp) % NWindows) * 2;
143            offset[Outputs] = FrameOffset + (index * RegsPerFrame);
144            offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame);
145            offset[Inputs] = FrameOffset +
146                (((index+2) % (NWindows * 2)) * RegsPerFrame);
147            regView[Outputs] = regSegments[index];
148            regView[Locals] = regSegments[index+1];
149            regView[Inputs] = regSegments[(index+2) % (NWindows * 2)];
150
151            DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp);
152        }
153
154        void setGlobals(int gl)
155        {
156
157            DPRINTF(Sparc, "Now using %d globals", gl);
158
159            regView[Globals] = regGlobals[gl];
160            offset[Globals] = RegGlobalOffset + gl * RegsPerFrame;
161        }
162
163        void serialize(std::ostream &os);
164
165        void unserialize(Checkpoint *cp, const std::string &section);
166    };
167
168    typedef float float32_t;
169    typedef double float64_t;
170    //FIXME long double refers to a 10 byte float, rather than a
171    //16 byte float as required. This data type may have to be emulated.
172    typedef double float128_t;
173
174    class FloatRegFile
175    {
176      public:
177        static const int SingleWidth = 32;
178        static const int DoubleWidth = 64;
179        static const int QuadWidth = 128;
180
181      protected:
182
183        //Since the floating point registers overlap each other,
184        //A generic storage space is used. The float to be returned is
185        //pulled from the appropriate section of this region.
186        char regSpace[SingleWidth / 8 * NumFloatRegs];
187
188      public:
189
190        void clear()
191        {
192            bzero(regSpace, sizeof(regSpace));
193        }
194
195        FloatReg readReg(int floatReg, int width)
196        {
197            //In each of these cases, we have to copy the value into a temporary
198            //variable. This is because we may otherwise try to access an
199            //unaligned portion of memory.
200            switch(width)
201            {
202              case SingleWidth:
203                float32_t result32;
204                memcpy(&result32, regSpace + 4 * floatReg, width);
205                return htog(result32);
206              case DoubleWidth:
207                float64_t result64;
208                memcpy(&result64, regSpace + 4 * floatReg, width);
209                return htog(result64);
210              case QuadWidth:
211                float128_t result128;
212                memcpy(&result128, regSpace + 4 * floatReg, width);
213                return htog(result128);
214              default:
215                panic("Attempted to read a %d bit floating point register!", width);
216            }
217        }
218
219        FloatRegBits readRegBits(int floatReg, int width)
220        {
221            //In each of these cases, we have to copy the value into a temporary
222            //variable. This is because we may otherwise try to access an
223            //unaligned portion of memory.
224            switch(width)
225            {
226              case SingleWidth:
227                uint32_t result32;
228                memcpy(&result32, regSpace + 4 * floatReg, width);
229                return htog(result32);
230              case DoubleWidth:
231                uint64_t result64;
232                memcpy(&result64, regSpace + 4 * floatReg, width);
233                return htog(result64);
234              case QuadWidth:
235                uint64_t result128;
236                memcpy(&result128, regSpace + 4 * floatReg, width);
237                return htog(result128);
238              default:
239                panic("Attempted to read a %d bit floating point register!", width);
240            }
241        }
242
243        Fault setReg(int floatReg, const FloatReg &val, int width)
244        {
245            //In each of these cases, we have to copy the value into a temporary
246            //variable. This is because we may otherwise try to access an
247            //unaligned portion of memory.
248            switch(width)
249            {
250              case SingleWidth:
251                uint32_t result32 = gtoh((uint32_t)val);
252                memcpy(regSpace + 4 * floatReg, &result32, width);
253              case DoubleWidth:
254                uint64_t result64 = gtoh((uint64_t)val);
255                memcpy(regSpace + 4 * floatReg, &result64, width);
256              case QuadWidth:
257                uint64_t result128 = gtoh((uint64_t)val);
258                memcpy(regSpace + 4 * floatReg, &result128, width);
259              default:
260                panic("Attempted to read a %d bit floating point register!", width);
261            }
262            return NoFault;
263        }
264
265        Fault setRegBits(int floatReg, const FloatRegBits &val, int width)
266        {
267            //In each of these cases, we have to copy the value into a temporary
268            //variable. This is because we may otherwise try to access an
269            //unaligned portion of memory.
270            switch(width)
271            {
272              case SingleWidth:
273                uint32_t result32 = gtoh((uint32_t)val);
274                memcpy(regSpace + 4 * floatReg, &result32, width);
275              case DoubleWidth:
276                uint64_t result64 = gtoh((uint64_t)val);
277                memcpy(regSpace + 4 * floatReg, &result64, width);
278              case QuadWidth:
279                uint64_t result128 = gtoh((uint64_t)val);
280                memcpy(regSpace + 4 * floatReg, &result128, width);
281              default:
282                panic("Attempted to read a %d bit floating point register!", width);
283            }
284            return NoFault;
285        }
286
287        void serialize(std::ostream &os);
288
289        void unserialize(Checkpoint *cp, const std::string &section);
290    };
291
292    enum MiscRegIndex
293    {
294        /** Ancillary State Registers */
295        MISCREG_Y  = AsrStart + 0,
296        MISCREG_CCR = AsrStart + 2,
297        MISCREG_ASI = AsrStart + 3,
298        MISCREG_TICK = AsrStart + 4,
299        MISCREG_PC = AsrStart + 5,
300        MISCREG_FPRS = AsrStart + 6,
301        MISCREG_PCR = AsrStart + 16,
302        MISCREG_PIC = AsrStart + 17,
303        MISCREG_GSR = AsrStart + 19,
304        MISCREG_SOFTINT_SET = AsrStart + 20,
305        MISCREG_SOFTINT_CLR = AsrStart + 21,
306        MISCREG_SOFTINT = AsrStart + 22,
307        MISCREG_TICK_CMPR = AsrStart + 23,
308        MISCREG_STICK = AsrStart + 24,
309        MISCREG_STICK_CMPR = AsrStart + 25,
310
311        /** Privilged Registers */
312        MISCREG_TPC = PrStart + 0,
313        MISCREG_TNPC = PrStart + 1,
314        MISCREG_TSTATE = PrStart + 2,
315        MISCREG_TT = PrStart + 3,
316        MISCREG_PRIVTICK = PrStart + 4,
317        MISCREG_TBA = PrStart + 5,
318        MISCREG_PSTATE = PrStart + 6,
319        MISCREG_TL = PrStart + 7,
320        MISCREG_PIL = PrStart + 8,
321        MISCREG_CWP = PrStart + 9,
322        MISCREG_CANSAVE = PrStart + 10,
323        MISCREG_CANRESTORE = PrStart + 11,
324        MISCREG_CLEANWIN = PrStart + 12,
325        MISCREG_OTHERWIN = PrStart + 13,
326        MISCREG_WSTATE = PrStart + 14,
327        MISCREG_GL = PrStart + 16,
328
329        /** Hyper privileged registers */
330        MISCREG_HPSTATE = HprStart + 0,
331        MISCREG_HTSTATE = HprStart + 1,
332        MISCREG_HINTP = HprStart + 3,
333        MISCREG_HTBA = HprStart + 5,
334        MISCREG_HVER = HprStart + 6,
335        MISCREG_STRAND_STS_REG = HprStart + 16,
336        MISCREG_HSTICK_CMPR = HprStart + 31,
337
338        /** Floating Point Status Register */
339        MISCREG_FSR = MiscStart + 0
340
341    };
342
343    // The control registers, broken out into fields
344    class MiscRegFile
345    {
346      private:
347
348        /* ASR Registers */
349        union {
350            uint64_t y;		// Y (used in obsolete multiplication)
351            struct {
352                uint64_t value:32;	// The actual value stored in y
353                uint64_t :32;	// reserved bits
354            } yFields;
355        };
356        union {
357            uint8_t	ccr;		// Condition Code Register
358            struct {
359                union {
360                    uint8_t icc:4;	// 32-bit condition codes
361                    struct {
362                        uint8_t c:1;	// Carry
363                        uint8_t v:1;	// Overflow
364                        uint8_t z:1;	// Zero
365                        uint8_t n:1;	// Negative
366                    } iccFields;
367                };
368                union {
369                    uint8_t xcc:4;	// 64-bit condition codes
370                    struct {
371                        uint8_t c:1;	// Carry
372                        uint8_t v:1;	// Overflow
373                        uint8_t z:1;	// Zero
374                        uint8_t n:1;	// Negative
375                    } xccFields;
376                };
377            } ccrFields;
378        };
379        uint8_t asi;		// Address Space Identifier
380        union {
381            uint64_t tick;		// Hardware clock-tick counter
382            struct {
383                int64_t counter:63;	// Clock-tick count
384                uint64_t npt:1;		// Non-priveleged trap
385            } tickFields;
386        };
387        union {
388            uint8_t		fprs;	// Floating-Point Register State
389            struct {
390                uint8_t dl:1;		// Dirty lower
391                uint8_t du:1;		// Dirty upper
392                uint8_t fef:1;		// FPRS enable floating-Point
393            } fprsFields;
394        };
395        union {
396            uint64_t softint;
397            struct {
398                uint64_t tm:1;
399                uint64_t int_level:14;
400                uint64_t sm:1;
401            } softintFields;
402        };
403        union {
404            uint64_t tick_cmpr;		// Hardware tick compare registers
405            struct {
406                uint64_t tick_cmpr:63;	// Clock-tick count
407                uint64_t int_dis:1;		// Non-priveleged trap
408            } tick_cmprFields;
409        };
410        union {
411            uint64_t stick;		// Hardware clock-tick counter
412            struct {
413                int64_t :63;	// Not used, storage in SparcSystem
414                uint64_t npt:1;		// Non-priveleged trap
415            } stickFields;
416        };
417        union {
418            uint64_t stick_cmpr;		// Hardware tick compare registers
419            struct {
420                uint64_t tick_cmpr:63;	// Clock-tick count
421                uint64_t int_dis:1;		// Non-priveleged trap
422            } stick_cmprFields;
423        };
424
425
426        /* Privileged Registers */
427        uint64_t tpc[MaxTL];	// Trap Program Counter (value from
428                                // previous trap level)
429        uint64_t tnpc[MaxTL];	// Trap Next Program Counter (value from
430                                // previous trap level)
431        union {
432            uint64_t tstate[MaxTL];	// Trap State
433            struct {
434                //Values are from previous trap level
435                uint64_t cwp:5;		// Current Window Pointer
436                uint64_t :3;	// Reserved bits
437                uint64_t pstate:13;	// Process State
438                uint64_t :3;	// Reserved bits
439                uint64_t asi:8;		// Address Space Identifier
440                uint64_t ccr:8;		// Condition Code Register
441                uint64_t gl:8;		// Global level
442            } tstateFields[MaxTL];
443        };
444        uint16_t tt[MaxTL];	// Trap Type (Type of trap which occured
445                                // on the previous level)
446        uint64_t tba;		// Trap Base Address
447
448        union {
449            uint16_t pstate;		// Process State Register
450            struct {
451                uint16_t :1;		// reserved
452                uint16_t ie:1;		// Interrupt enable
453                uint16_t priv:1;	// Privelege mode
454                uint16_t am:1;		// Address mask
455                uint16_t pef:1;		// PSTATE enable floating-point
456                uint16_t :1;		// reserved2
457                uint16_t mm:2;		// Memory Model
458                uint16_t tle:1;		// Trap little-endian
459                uint16_t cle:1;		// Current little-endian
460            } pstateFields;
461        };
462        uint8_t tl;		// Trap Level
463        uint8_t pil;		// Process Interrupt Register
464        uint8_t cwp;		// Current Window Pointer
465        uint8_t cansave;	// Savable windows
466        uint8_t canrestore;	// Restorable windows
467        uint8_t cleanwin;	// Clean windows
468        uint8_t otherwin;	// Other windows
469        union {
470            uint8_t wstate;		// Window State
471            struct {
472                uint8_t normal:3;	// Bits TT<4:2> are set to on a normal
473                                        // register window trap
474                uint8_t other:3;	// Bits TT<4:2> are set to on an "otherwin"
475                                        // register window trap
476            } wstateFields;
477        };
478        uint8_t gl;             // Global level register
479
480
481        /** Hyperprivileged Registers */
482        union {
483            uint64_t hpstate; // Hyperprivileged State Register
484            struct {
485                uint8_t tlz: 1;
486                uint8_t :1;
487                uint8_t hpriv:1;
488                uint8_t :2;
489                uint8_t red:1;
490                uint8_t :4;
491                uint8_t ibe:1;
492                uint8_t id:1;
493            } hpstateFields;
494        };
495
496        uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register
497        uint64_t hintp;
498        uint64_t htba; // Hyperprivileged Trap Base Address register
499        union {
500            uint64_t hstick_cmpr;		// Hardware tick compare registers
501            struct {
502                uint64_t tick_cmpr:63;	// Clock-tick count
503                uint64_t int_dis:1;		// Non-priveleged trap
504            } hstick_cmprFields;
505        };
506
507        uint64_t strandStatusReg; // Per strand status register
508
509
510        /** Floating point misc registers. */
511        union {
512            uint64_t	fsr;	// Floating-Point State Register
513            struct {
514                union {
515                    uint64_t cexc:5;	// Current excpetion
516                    struct {
517                        uint64_t nxc:1;		// Inexact
518                        uint64_t dzc:1;		// Divide by zero
519                        uint64_t ufc:1;		// Underflow
520                        uint64_t ofc:1;		// Overflow
521                        uint64_t nvc:1;		// Invalid operand
522                    } cexcFields;
523                };
524                union {
525                    uint64_t aexc:5;		// Accrued exception
526                    struct {
527                        uint64_t nxc:1;		// Inexact
528                        uint64_t dzc:1;		// Divide by zero
529                        uint64_t ufc:1;		// Underflow
530                        uint64_t ofc:1;		// Overflow
531                        uint64_t nvc:1;		// Invalid operand
532                    } aexcFields;
533                };
534                uint64_t fcc0:2;		// Floating-Point condtion codes
535                uint64_t :1;		// Reserved bits
536                uint64_t qne:1;			// Deferred trap queue not empty
537                                                // with no queue, it should read 0
538                uint64_t ftt:3;			// Floating-Point trap type
539                uint64_t ver:3;			// Version (of the FPU)
540                uint64_t :2;		// Reserved bits
541                uint64_t ns:1;			// Nonstandard floating point
542                union {
543                    uint64_t tem:5;			// Trap Enable Mask
544                    struct {
545                        uint64_t nxm:1;		// Inexact
546                        uint64_t dzm:1;		// Divide by zero
547                        uint64_t ufm:1;		// Underflow
548                        uint64_t ofm:1;		// Overflow
549                        uint64_t nvm:1;		// Invalid operand
550                    } temFields;
551                };
552                uint64_t :2;		// Reserved bits
553                uint64_t rd:2;			// Rounding direction
554                uint64_t fcc1:2;		// Floating-Point condition codes
555                uint64_t fcc2:2;		// Floating-Point condition codes
556                uint64_t fcc3:2;		// Floating-Point condition codes
557                uint64_t :26;		// Reserved bits
558            } fsrFields;
559        };
560
561        // These need to check the int_dis field and if 0 then
562        // set appropriate bit in softint and checkinterrutps on the cpu
563#if FULL_SYSTEM
564        /** Process a tick compare event and generate an interrupt on the cpu if
565         * appropriate. */
566        void processTickCompare(ExecContext *xc);
567        void processSTickCompare(ExecContext *xc);
568        void processHSTickCompare(ExecContext *xc);
569
570        typedef CpuEventWrapper<MiscRegFile,
571                &MiscRegFile::processTickCompare> TickCompareEvent;
572        TickCompareEvent *tickCompare;
573
574        typedef CpuEventWrapper<MiscRegFile,
575                &MiscRegFile::processSTickCompare> STickCompareEvent;
576        STickCompareEvent *sTickCompare;
577
578        typedef CpuEventWrapper<MiscRegFile,
579                &MiscRegFile::processHSTickCompare> HSTickCompareEvent;
580        HSTickCompareEvent *hSTickCompare;
581
582        /** Fullsystem only register version of ReadRegWithEffect() */
583        MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ExecContext *xc);
584        /** Fullsystem only register version of SetRegWithEffect() */
585        Fault setFSRegWithEffect(int miscReg, const MiscReg &val,
586                ExecContext * xc);
587#endif
588      public:
589
590        void reset()
591        {
592            pstateFields.pef = 0; //No FPU
593            //pstateFields.pef = 1; //FPU
594#if FULL_SYSTEM
595            //For SPARC, when a system is first started, there is a power
596            //on reset Trap which sets the processor into the following state.
597            //Bits that aren't set aren't defined on startup.
598            tl = MaxTL;
599            gl = MaxGL;
600
601            tickFields.counter = 0; //The TICK register is unreadable bya
602            tickFields.npt = 1; //The TICK register is unreadable by by !priv
603
604            softint = 0; // Clear all the soft interrupt bits
605            tick_cmprFields.int_dis = 1; // disable timer compare interrupts
606            tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
607            stickFields.npt = 1; //The TICK register is unreadable by by !priv
608            stick_cmprFields.int_dis = 1; // disable timer compare interrupts
609            stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
610
611
612            tt[tl] = power_on_reset;
613            pstate = 0; // fields 0 but pef
614            pstateFields.pef = 1;
615
616            hpstate = 0;
617            hpstateFields.red = 1;
618            hpstateFields.hpriv = 1;
619            hpstateFields.tlz = 0; // this is a guess
620
621            hintp = 0; // no interrupts pending
622            hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
623            hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
624
625#else
626/*	    //This sets up the initial state of the processor for usermode processes
627            pstateFields.priv = 0; //Process runs in user mode
628            pstateFields.ie = 1; //Interrupts are enabled
629            fsrFields.rd = 0; //Round to nearest
630            fsrFields.tem = 0; //Floating point traps not enabled
631            fsrFields.ns = 0; //Non standard mode off
632            fsrFields.qne = 0; //Floating point queue is empty
633            fsrFields.aexc = 0; //No accrued exceptions
634            fsrFields.cexc = 0; //No current exceptions
635
636            //Register window management registers
637            otherwin = 0; //No windows contain info from other programs
638            canrestore = 0; //There are no windows to pop
639            cansave = MaxTL - 2; //All windows are available to save into
640            cleanwin = MaxTL;*/
641#endif
642        }
643
644        MiscRegFile()
645        {
646            reset();
647        }
648
649        /** read a value out of an either an SE or FS IPR. No checking is done
650         * about SE vs. FS as this is mostly used to copy the regfile. Thus more
651         * register are copied that are necessary for FS. However this prevents
652         * a bunch of ifdefs and is rarely called so is not performance
653         * criticial. */
654        MiscReg readReg(int miscReg);
655
656        /** Read a value from an IPR. Only the SE iprs are here and the rest
657         * are are readFSRegWithEffect (which is called by readRegWithEffect()).
658         * Checking is done for permission based on state bits in the miscreg
659         * file. */
660        MiscReg readRegWithEffect(int miscReg, Fault &fault, ExecContext *xc);
661
662        /** write a value into an either an SE or FS IPR. No checking is done
663         * about SE vs. FS as this is mostly used to copy the regfile. Thus more
664         * register are copied that are necessary for FS. However this prevents
665         * a bunch of ifdefs and is rarely called so is not performance
666         * criticial.*/
667        Fault setReg(int miscReg, const MiscReg &val);
668
669        /** Write a value into an IPR. Only the SE iprs are here and the rest
670         * are are setFSRegWithEffect (which is called by setRegWithEffect()).
671         * Checking is done for permission based on state bits in the miscreg
672         * file. */
673        Fault setRegWithEffect(int miscReg,
674                const MiscReg &val, ExecContext * xc);
675
676        void serialize(std::ostream & os);
677
678        void unserialize(Checkpoint * cp, const std::string & section);
679
680        void copyMiscRegs(ExecContext * xc);
681
682        bool isHyperPriv() { return hpstateFields.hpriv; }
683        bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
684        bool isNonPriv() { return !isPriv(); }
685    };
686
687    typedef union
688    {
689        IntReg  intreg;
690        FloatReg   fpreg;
691        MiscReg ctrlreg;
692    } AnyReg;
693
694    class RegFile
695    {
696      protected:
697        Addr pc;		// Program Counter
698        Addr npc;		// Next Program Counter
699        Addr nnpc;
700
701      public:
702        Addr readPC()
703        {
704            return pc;
705        }
706
707        void setPC(Addr val)
708        {
709            pc = val;
710        }
711
712        Addr readNextPC()
713        {
714            return npc;
715        }
716
717        void setNextPC(Addr val)
718        {
719            npc = val;
720        }
721
722        Addr readNextNPC()
723        {
724            return nnpc;
725        }
726
727        void setNextNPC(Addr val)
728        {
729            nnpc = val;
730        }
731
732      protected:
733        IntRegFile intRegFile;		// integer register file
734        FloatRegFile floatRegFile;	// floating point register file
735        MiscRegFile miscRegFile;	// control register file
736
737      public:
738
739        void clear()
740        {
741            intRegFile.clear();
742            floatRegFile.clear();
743        }
744
745        int FlattenIntIndex(int reg)
746        {
747            return intRegFile.flattenIndex(reg);
748        }
749
750        MiscReg readMiscReg(int miscReg)
751        {
752            return miscRegFile.readReg(miscReg);
753        }
754
755        MiscReg readMiscRegWithEffect(int miscReg,
756                Fault &fault, ExecContext *xc)
757        {
758            return miscRegFile.readRegWithEffect(miscReg, fault, xc);
759        }
760
761        Fault setMiscReg(int miscReg, const MiscReg &val)
762        {
763            return miscRegFile.setReg(miscReg, val);
764        }
765
766        Fault setMiscRegWithEffect(int miscReg, const MiscReg &val,
767                ExecContext * xc)
768        {
769            return miscRegFile.setRegWithEffect(miscReg, val, xc);
770        }
771
772        FloatReg readFloatReg(int floatReg, int width)
773        {
774            return floatRegFile.readReg(floatReg, width);
775        }
776
777        FloatReg readFloatReg(int floatReg)
778        {
779            //Use the "natural" width of a single float
780            return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth);
781        }
782
783        FloatRegBits readFloatRegBits(int floatReg, int width)
784        {
785            return floatRegFile.readRegBits(floatReg, width);
786        }
787
788        FloatRegBits readFloatRegBits(int floatReg)
789        {
790            //Use the "natural" width of a single float
791            return floatRegFile.readRegBits(floatReg,
792                    FloatRegFile::SingleWidth);
793        }
794
795        Fault setFloatReg(int floatReg, const FloatReg &val, int width)
796        {
797            return floatRegFile.setReg(floatReg, val, width);
798        }
799
800        Fault setFloatReg(int floatReg, const FloatReg &val)
801        {
802            //Use the "natural" width of a single float
803            return setFloatReg(floatReg, val, FloatRegFile::SingleWidth);
804        }
805
806        Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width)
807        {
808            return floatRegFile.setRegBits(floatReg, val, width);
809        }
810
811        Fault setFloatRegBits(int floatReg, const FloatRegBits &val)
812        {
813            //Use the "natural" width of a single float
814            return floatRegFile.setRegBits(floatReg, val,
815                    FloatRegFile::SingleWidth);
816        }
817
818        IntReg readIntReg(int intReg)
819        {
820            return intRegFile.readReg(intReg);
821        }
822
823        Fault setIntReg(int intReg, const IntReg &val)
824        {
825            return intRegFile.setReg(intReg, val);
826        }
827
828        void serialize(std::ostream &os);
829        void unserialize(Checkpoint *cp, const std::string &section);
830
831      public:
832
833        enum ContextParam
834        {
835            CONTEXT_CWP,
836            CONTEXT_GLOBALS
837        };
838        typedef int ContextVal;
839
840        void changeContext(ContextParam param, ContextVal val)
841        {
842            switch(param)
843            {
844              case CONTEXT_CWP:
845                intRegFile.setCWP(val);
846                break;
847              case CONTEXT_GLOBALS:
848                intRegFile.setGlobals(val);
849                break;
850              default:
851                panic("Tried to set illegal context parameter in the SPARC regfile.\n");
852            }
853        }
854    };
855
856    void copyRegs(ExecContext *src, ExecContext *dest);
857
858    void copyMiscRegs(ExecContext *src, ExecContext *dest);
859
860    int InterruptLevel(uint64_t softint);
861
862} // namespace SparcISA
863
864#endif
865