| /* |
| * Copyright (c) 2003-2005 The Regents of The University of Michigan |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Authors: Gabe Black |
| * Ali Saidi |
| */ |
| |
| #ifndef __ARCH_SPARC_REGFILE_HH__ |
| #define __ARCH_SPARC_REGFILE_HH__ |
| |
| #include "arch/sparc/exceptions.hh" |
| #include "arch/sparc/faults.hh" |
| #include "base/trace.hh" |
| #include "sim/byteswap.hh" |
| #include "cpu/cpuevent.hh" |
| #include "sim/host.hh" |
| |
| class Checkpoint; |
| |
| namespace SparcISA |
| { |
| |
| typedef uint8_t RegIndex; |
| |
| // MAXTL - maximum trap level |
| const int MaxPTL = 2; |
| const int MaxTL = 6; |
| const int MaxGL = 3; |
| const int MaxPGL = 2; |
| |
| // NWINDOWS - number of register windows, can be 3 to 32 |
| const int NWindows = 32; |
| |
| |
| const int AsrStart = 0; |
| const int PrStart = 32; |
| const int HprStart = 64; |
| const int MiscStart = 96; |
| |
| |
| const uint64_t Bit64 = 0x8000000000000000; |
| |
| class IntRegFile |
| { |
| protected: |
| static const int FrameOffsetBits = 3; |
| static const int FrameNumBits = 2; |
| |
| static const int RegsPerFrame = 1 << FrameOffsetBits; |
| static const int FrameNumMask = |
| (FrameNumBits == sizeof(int)) ? |
| (unsigned int)(-1) : |
| (1 << FrameNumBits) - 1; |
| static const int FrameOffsetMask = |
| (FrameOffsetBits == sizeof(int)) ? |
| (unsigned int)(-1) : |
| (1 << FrameOffsetBits) - 1; |
| |
| IntReg regGlobals[MaxGL][RegsPerFrame]; |
| IntReg regSegments[2 * NWindows][RegsPerFrame]; |
| |
| enum regFrame {Globals, Outputs, Locals, Inputs, NumFrames}; |
| |
| IntReg * regView[NumFrames]; |
| |
| static const int RegGlobalOffset = 0; |
| static const int FrameOffset = MaxGL * RegsPerFrame; |
| int offset[NumFrames]; |
| |
| public: |
| |
| int flattenIndex(int reg) |
| { |
| int flatIndex = offset[reg >> FrameOffsetBits] |
| | (reg & FrameOffsetMask); |
| DPRINTF(Sparc, "Flattened index %d into %d.\n", reg, flatIndex); |
| return flatIndex; |
| } |
| |
| void clear() |
| { |
| int x; |
| for (x = 0; x < MaxGL; x++) |
| memset(regGlobals[x], 0, sizeof(regGlobals[x])); |
| for(int x = 0; x < 2 * NWindows; x++) |
| bzero(regSegments[x], sizeof(regSegments[x])); |
| } |
| |
| IntRegFile() |
| { |
| offset[Globals] = 0; |
| regView[Globals] = regGlobals[0]; |
| setCWP(0); |
| clear(); |
| } |
| |
| IntReg readReg(int intReg) |
| { |
| IntReg val = |
| regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask]; |
| DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); |
| return val; |
| } |
| |
| Fault setReg(int intReg, const IntReg &val) |
| { |
| if(intReg) |
| DPRINTF(Sparc, "Wrote register %d = 0x%x\n", intReg, val); |
| regView[intReg >> FrameOffsetBits][intReg & FrameOffsetMask] = val; |
| return NoFault; |
| } |
| |
| //This doesn't effect the actual CWP register. |
| //It's purpose is to adjust the view of the register file |
| //to what it would be if CWP = cwp. |
| void setCWP(int cwp) |
| { |
| int index = ((NWindows - cwp) % NWindows) * 2; |
| offset[Outputs] = FrameOffset + (index * RegsPerFrame); |
| offset[Locals] = FrameOffset + ((index+1) * RegsPerFrame); |
| offset[Inputs] = FrameOffset + |
| (((index+2) % (NWindows * 2)) * RegsPerFrame); |
| regView[Outputs] = regSegments[index]; |
| regView[Locals] = regSegments[index+1]; |
| regView[Inputs] = regSegments[(index+2) % (NWindows * 2)]; |
| |
| DPRINTF(Sparc, "Changed the CWP value to %d\n", cwp); |
| } |
| |
| void setGlobals(int gl) |
| { |
| |
| DPRINTF(Sparc, "Now using %d globals", gl); |
| |
| regView[Globals] = regGlobals[gl]; |
| offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; |
| } |
| |
| void serialize(std::ostream &os); |
| |
| void unserialize(Checkpoint *cp, const std::string §ion); |
| }; |
| |
| typedef float float32_t; |
| typedef double float64_t; |
| //FIXME long double refers to a 10 byte float, rather than a |
| //16 byte float as required. This data type may have to be emulated. |
| typedef double float128_t; |
| |
| class FloatRegFile |
| { |
| public: |
| static const int SingleWidth = 32; |
| static const int DoubleWidth = 64; |
| static const int QuadWidth = 128; |
| |
| protected: |
| |
| //Since the floating point registers overlap each other, |
| //A generic storage space is used. The float to be returned is |
| //pulled from the appropriate section of this region. |
| char regSpace[SingleWidth / 8 * NumFloatRegs]; |
| |
| public: |
| |
| void clear() |
| { |
| bzero(regSpace, sizeof(regSpace)); |
| } |
| |
| FloatReg readReg(int floatReg, int width) |
| { |
| //In each of these cases, we have to copy the value into a temporary |
| //variable. This is because we may otherwise try to access an |
| //unaligned portion of memory. |
| switch(width) |
| { |
| case SingleWidth: |
| float32_t result32; |
| memcpy(&result32, regSpace + 4 * floatReg, width); |
| return htog(result32); |
| case DoubleWidth: |
| float64_t result64; |
| memcpy(&result64, regSpace + 4 * floatReg, width); |
| return htog(result64); |
| case QuadWidth: |
| float128_t result128; |
| memcpy(&result128, regSpace + 4 * floatReg, width); |
| return htog(result128); |
| default: |
| panic("Attempted to read a %d bit floating point register!", width); |
| } |
| } |
| |
| FloatRegBits readRegBits(int floatReg, int width) |
| { |
| //In each of these cases, we have to copy the value into a temporary |
| //variable. This is because we may otherwise try to access an |
| //unaligned portion of memory. |
| switch(width) |
| { |
| case SingleWidth: |
| uint32_t result32; |
| memcpy(&result32, regSpace + 4 * floatReg, width); |
| return htog(result32); |
| case DoubleWidth: |
| uint64_t result64; |
| memcpy(&result64, regSpace + 4 * floatReg, width); |
| return htog(result64); |
| case QuadWidth: |
| uint64_t result128; |
| memcpy(&result128, regSpace + 4 * floatReg, width); |
| return htog(result128); |
| default: |
| panic("Attempted to read a %d bit floating point register!", width); |
| } |
| } |
| |
| Fault setReg(int floatReg, const FloatReg &val, int width) |
| { |
| //In each of these cases, we have to copy the value into a temporary |
| //variable. This is because we may otherwise try to access an |
| //unaligned portion of memory. |
| switch(width) |
| { |
| case SingleWidth: |
| uint32_t result32 = gtoh((uint32_t)val); |
| memcpy(regSpace + 4 * floatReg, &result32, width); |
| case DoubleWidth: |
| uint64_t result64 = gtoh((uint64_t)val); |
| memcpy(regSpace + 4 * floatReg, &result64, width); |
| case QuadWidth: |
| uint64_t result128 = gtoh((uint64_t)val); |
| memcpy(regSpace + 4 * floatReg, &result128, width); |
| default: |
| panic("Attempted to read a %d bit floating point register!", width); |
| } |
| return NoFault; |
| } |
| |
| Fault setRegBits(int floatReg, const FloatRegBits &val, int width) |
| { |
| //In each of these cases, we have to copy the value into a temporary |
| //variable. This is because we may otherwise try to access an |
| //unaligned portion of memory. |
| switch(width) |
| { |
| case SingleWidth: |
| uint32_t result32 = gtoh((uint32_t)val); |
| memcpy(regSpace + 4 * floatReg, &result32, width); |
| case DoubleWidth: |
| uint64_t result64 = gtoh((uint64_t)val); |
| memcpy(regSpace + 4 * floatReg, &result64, width); |
| case QuadWidth: |
| uint64_t result128 = gtoh((uint64_t)val); |
| memcpy(regSpace + 4 * floatReg, &result128, width); |
| default: |
| panic("Attempted to read a %d bit floating point register!", width); |
| } |
| return NoFault; |
| } |
| |
| void serialize(std::ostream &os); |
| |
| void unserialize(Checkpoint *cp, const std::string §ion); |
| }; |
| |
| enum MiscRegIndex |
| { |
| /** Ancillary State Registers */ |
| MISCREG_Y = AsrStart + 0, |
| MISCREG_CCR = AsrStart + 2, |
| MISCREG_ASI = AsrStart + 3, |
| MISCREG_TICK = AsrStart + 4, |
| MISCREG_PC = AsrStart + 5, |
| MISCREG_FPRS = AsrStart + 6, |
| MISCREG_PCR = AsrStart + 16, |
| MISCREG_PIC = AsrStart + 17, |
| MISCREG_GSR = AsrStart + 19, |
| MISCREG_SOFTINT_SET = AsrStart + 20, |
| MISCREG_SOFTINT_CLR = AsrStart + 21, |
| MISCREG_SOFTINT = AsrStart + 22, |
| MISCREG_TICK_CMPR = AsrStart + 23, |
| MISCREG_STICK = AsrStart + 24, |
| MISCREG_STICK_CMPR = AsrStart + 25, |
| |
| /** Privilged Registers */ |
| MISCREG_TPC = PrStart + 0, |
| MISCREG_TNPC = PrStart + 1, |
| MISCREG_TSTATE = PrStart + 2, |
| MISCREG_TT = PrStart + 3, |
| MISCREG_PRIVTICK = PrStart + 4, |
| MISCREG_TBA = PrStart + 5, |
| MISCREG_PSTATE = PrStart + 6, |
| MISCREG_TL = PrStart + 7, |
| MISCREG_PIL = PrStart + 8, |
| MISCREG_CWP = PrStart + 9, |
| MISCREG_CANSAVE = PrStart + 10, |
| MISCREG_CANRESTORE = PrStart + 11, |
| MISCREG_CLEANWIN = PrStart + 12, |
| MISCREG_OTHERWIN = PrStart + 13, |
| MISCREG_WSTATE = PrStart + 14, |
| MISCREG_GL = PrStart + 16, |
| |
| /** Hyper privileged registers */ |
| MISCREG_HPSTATE = HprStart + 0, |
| MISCREG_HTSTATE = HprStart + 1, |
| MISCREG_HINTP = HprStart + 3, |
| MISCREG_HTBA = HprStart + 5, |
| MISCREG_HVER = HprStart + 6, |
| MISCREG_STRAND_STS_REG = HprStart + 16, |
| MISCREG_HSTICK_CMPR = HprStart + 31, |
| |
| /** Floating Point Status Register */ |
| MISCREG_FSR = MiscStart + 0 |
| |
| }; |
| |
| // The control registers, broken out into fields |
| class MiscRegFile |
| { |
| private: |
| |
| /* ASR Registers */ |
| union { |
| uint64_t y; // Y (used in obsolete multiplication) |
| struct { |
| uint64_t value:32; // The actual value stored in y |
| uint64_t :32; // reserved bits |
| } yFields; |
| }; |
| union { |
| uint8_t ccr; // Condition Code Register |
| struct { |
| union { |
| uint8_t icc:4; // 32-bit condition codes |
| struct { |
| uint8_t c:1; // Carry |
| uint8_t v:1; // Overflow |
| uint8_t z:1; // Zero |
| uint8_t n:1; // Negative |
| } iccFields; |
| }; |
| union { |
| uint8_t xcc:4; // 64-bit condition codes |
| struct { |
| uint8_t c:1; // Carry |
| uint8_t v:1; // Overflow |
| uint8_t z:1; // Zero |
| uint8_t n:1; // Negative |
| } xccFields; |
| }; |
| } ccrFields; |
| }; |
| uint8_t asi; // Address Space Identifier |
| union { |
| uint64_t tick; // Hardware clock-tick counter |
| struct { |
| int64_t counter:63; // Clock-tick count |
| uint64_t npt:1; // Non-priveleged trap |
| } tickFields; |
| }; |
| union { |
| uint8_t fprs; // Floating-Point Register State |
| struct { |
| uint8_t dl:1; // Dirty lower |
| uint8_t du:1; // Dirty upper |
| uint8_t fef:1; // FPRS enable floating-Point |
| } fprsFields; |
| }; |
| union { |
| uint64_t softint; |
| struct { |
| uint64_t tm:1; |
| uint64_t int_level:14; |
| uint64_t sm:1; |
| } softintFields; |
| }; |
| union { |
| uint64_t tick_cmpr; // Hardware tick compare registers |
| struct { |
| uint64_t tick_cmpr:63; // Clock-tick count |
| uint64_t int_dis:1; // Non-priveleged trap |
| } tick_cmprFields; |
| }; |
| union { |
| uint64_t stick; // Hardware clock-tick counter |
| struct { |
| int64_t :63; // Not used, storage in SparcSystem |
| uint64_t npt:1; // Non-priveleged trap |
| } stickFields; |
| }; |
| union { |
| uint64_t stick_cmpr; // Hardware tick compare registers |
| struct { |
| uint64_t tick_cmpr:63; // Clock-tick count |
| uint64_t int_dis:1; // Non-priveleged trap |
| } stick_cmprFields; |
| }; |
| |
| |
| /* Privileged Registers */ |
| uint64_t tpc[MaxTL]; // Trap Program Counter (value from |
| // previous trap level) |
| uint64_t tnpc[MaxTL]; // Trap Next Program Counter (value from |
| // previous trap level) |
| union { |
| uint64_t tstate[MaxTL]; // Trap State |
| struct { |
| //Values are from previous trap level |
| uint64_t cwp:5; // Current Window Pointer |
| uint64_t :3; // Reserved bits |
| uint64_t pstate:13; // Process State |
| uint64_t :3; // Reserved bits |
| uint64_t asi:8; // Address Space Identifier |
| uint64_t ccr:8; // Condition Code Register |
| uint64_t gl:8; // Global level |
| } tstateFields[MaxTL]; |
| }; |
| uint16_t tt[MaxTL]; // Trap Type (Type of trap which occured |
| // on the previous level) |
| uint64_t tba; // Trap Base Address |
| |
| union { |
| uint16_t pstate; // Process State Register |
| struct { |
| uint16_t :1; // reserved |
| uint16_t ie:1; // Interrupt enable |
| uint16_t priv:1; // Privelege mode |
| uint16_t am:1; // Address mask |
| uint16_t pef:1; // PSTATE enable floating-point |
| uint16_t :1; // reserved2 |
| uint16_t mm:2; // Memory Model |
| uint16_t tle:1; // Trap little-endian |
| uint16_t cle:1; // Current little-endian |
| } pstateFields; |
| }; |
| uint8_t tl; // Trap Level |
| uint8_t pil; // Process Interrupt Register |
| uint8_t cwp; // Current Window Pointer |
| uint8_t cansave; // Savable windows |
| uint8_t canrestore; // Restorable windows |
| uint8_t cleanwin; // Clean windows |
| uint8_t otherwin; // Other windows |
| union { |
| uint8_t wstate; // Window State |
| struct { |
| uint8_t normal:3; // Bits TT<4:2> are set to on a normal |
| // register window trap |
| uint8_t other:3; // Bits TT<4:2> are set to on an "otherwin" |
| // register window trap |
| } wstateFields; |
| }; |
| uint8_t gl; // Global level register |
| |
| |
| /** Hyperprivileged Registers */ |
| union { |
| uint64_t hpstate; // Hyperprivileged State Register |
| struct { |
| uint8_t tlz: 1; |
| uint8_t :1; |
| uint8_t hpriv:1; |
| uint8_t :2; |
| uint8_t red:1; |
| uint8_t :4; |
| uint8_t ibe:1; |
| uint8_t id:1; |
| } hpstateFields; |
| }; |
| |
| uint64_t htstate[MaxTL]; // Hyperprivileged Trap State Register |
| uint64_t hintp; |
| uint64_t htba; // Hyperprivileged Trap Base Address register |
| union { |
| uint64_t hstick_cmpr; // Hardware tick compare registers |
| struct { |
| uint64_t tick_cmpr:63; // Clock-tick count |
| uint64_t int_dis:1; // Non-priveleged trap |
| } hstick_cmprFields; |
| }; |
| |
| uint64_t strandStatusReg; // Per strand status register |
| |
| |
| /** Floating point misc registers. */ |
| union { |
| uint64_t fsr; // Floating-Point State Register |
| struct { |
| union { |
| uint64_t cexc:5; // Current excpetion |
| struct { |
| uint64_t nxc:1; // Inexact |
| uint64_t dzc:1; // Divide by zero |
| uint64_t ufc:1; // Underflow |
| uint64_t ofc:1; // Overflow |
| uint64_t nvc:1; // Invalid operand |
| } cexcFields; |
| }; |
| union { |
| uint64_t aexc:5; // Accrued exception |
| struct { |
| uint64_t nxc:1; // Inexact |
| uint64_t dzc:1; // Divide by zero |
| uint64_t ufc:1; // Underflow |
| uint64_t ofc:1; // Overflow |
| uint64_t nvc:1; // Invalid operand |
| } aexcFields; |
| }; |
| uint64_t fcc0:2; // Floating-Point condtion codes |
| uint64_t :1; // Reserved bits |
| uint64_t qne:1; // Deferred trap queue not empty |
| // with no queue, it should read 0 |
| uint64_t ftt:3; // Floating-Point trap type |
| uint64_t ver:3; // Version (of the FPU) |
| uint64_t :2; // Reserved bits |
| uint64_t ns:1; // Nonstandard floating point |
| union { |
| uint64_t tem:5; // Trap Enable Mask |
| struct { |
| uint64_t nxm:1; // Inexact |
| uint64_t dzm:1; // Divide by zero |
| uint64_t ufm:1; // Underflow |
| uint64_t ofm:1; // Overflow |
| uint64_t nvm:1; // Invalid operand |
| } temFields; |
| }; |
| uint64_t :2; // Reserved bits |
| uint64_t rd:2; // Rounding direction |
| uint64_t fcc1:2; // Floating-Point condition codes |
| uint64_t fcc2:2; // Floating-Point condition codes |
| uint64_t fcc3:2; // Floating-Point condition codes |
| uint64_t :26; // Reserved bits |
| } fsrFields; |
| }; |
| |
| // These need to check the int_dis field and if 0 then |
| // set appropriate bit in softint and checkinterrutps on the cpu |
| #if FULL_SYSTEM |
| /** Process a tick compare event and generate an interrupt on the cpu if |
| * appropriate. */ |
| void processTickCompare(ExecContext *xc); |
| void processSTickCompare(ExecContext *xc); |
| void processHSTickCompare(ExecContext *xc); |
| |
| typedef CpuEventWrapper<MiscRegFile, |
| &MiscRegFile::processTickCompare> TickCompareEvent; |
| TickCompareEvent *tickCompare; |
| |
| typedef CpuEventWrapper<MiscRegFile, |
| &MiscRegFile::processSTickCompare> STickCompareEvent; |
| STickCompareEvent *sTickCompare; |
| |
| typedef CpuEventWrapper<MiscRegFile, |
| &MiscRegFile::processHSTickCompare> HSTickCompareEvent; |
| HSTickCompareEvent *hSTickCompare; |
| |
| /** Fullsystem only register version of ReadRegWithEffect() */ |
| MiscReg readFSRegWithEffect(int miscReg, Fault &fault, ExecContext *xc); |
| /** Fullsystem only register version of SetRegWithEffect() */ |
| Fault setFSRegWithEffect(int miscReg, const MiscReg &val, |
| ExecContext * xc); |
| #endif |
| public: |
| |
| void reset() |
| { |
| pstateFields.pef = 0; //No FPU |
| //pstateFields.pef = 1; //FPU |
| #if FULL_SYSTEM |
| //For SPARC, when a system is first started, there is a power |
| //on reset Trap which sets the processor into the following state. |
| //Bits that aren't set aren't defined on startup. |
| tl = MaxTL; |
| gl = MaxGL; |
| |
| tickFields.counter = 0; //The TICK register is unreadable bya |
| tickFields.npt = 1; //The TICK register is unreadable by by !priv |
| |
| softint = 0; // Clear all the soft interrupt bits |
| tick_cmprFields.int_dis = 1; // disable timer compare interrupts |
| tick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing |
| stickFields.npt = 1; //The TICK register is unreadable by by !priv |
| stick_cmprFields.int_dis = 1; // disable timer compare interrupts |
| stick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing |
| |
| |
| tt[tl] = power_on_reset; |
| pstate = 0; // fields 0 but pef |
| pstateFields.pef = 1; |
| |
| hpstate = 0; |
| hpstateFields.red = 1; |
| hpstateFields.hpriv = 1; |
| hpstateFields.tlz = 0; // this is a guess |
| |
| hintp = 0; // no interrupts pending |
| hstick_cmprFields.int_dis = 1; // disable timer compare interrupts |
| hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing |
| |
| #else |
| /* //This sets up the initial state of the processor for usermode processes |
| pstateFields.priv = 0; //Process runs in user mode |
| pstateFields.ie = 1; //Interrupts are enabled |
| fsrFields.rd = 0; //Round to nearest |
| fsrFields.tem = 0; //Floating point traps not enabled |
| fsrFields.ns = 0; //Non standard mode off |
| fsrFields.qne = 0; //Floating point queue is empty |
| fsrFields.aexc = 0; //No accrued exceptions |
| fsrFields.cexc = 0; //No current exceptions |
| |
| //Register window management registers |
| otherwin = 0; //No windows contain info from other programs |
| canrestore = 0; //There are no windows to pop |
| cansave = MaxTL - 2; //All windows are available to save into |
| cleanwin = MaxTL;*/ |
| #endif |
| } |
| |
| MiscRegFile() |
| { |
| reset(); |
| } |
| |
| /** read a value out of an either an SE or FS IPR. No checking is done |
| * about SE vs. FS as this is mostly used to copy the regfile. Thus more |
| * register are copied that are necessary for FS. However this prevents |
| * a bunch of ifdefs and is rarely called so is not performance |
| * criticial. */ |
| MiscReg readReg(int miscReg); |
| |
| /** Read a value from an IPR. Only the SE iprs are here and the rest |
| * are are readFSRegWithEffect (which is called by readRegWithEffect()). |
| * Checking is done for permission based on state bits in the miscreg |
| * file. */ |
| MiscReg readRegWithEffect(int miscReg, Fault &fault, ExecContext *xc); |
| |
| /** write a value into an either an SE or FS IPR. No checking is done |
| * about SE vs. FS as this is mostly used to copy the regfile. Thus more |
| * register are copied that are necessary for FS. However this prevents |
| * a bunch of ifdefs and is rarely called so is not performance |
| * criticial.*/ |
| Fault setReg(int miscReg, const MiscReg &val); |
| |
| /** Write a value into an IPR. Only the SE iprs are here and the rest |
| * are are setFSRegWithEffect (which is called by setRegWithEffect()). |
| * Checking is done for permission based on state bits in the miscreg |
| * file. */ |
| Fault setRegWithEffect(int miscReg, |
| const MiscReg &val, ExecContext * xc); |
| |
| void serialize(std::ostream & os); |
| |
| void unserialize(Checkpoint * cp, const std::string & section); |
| |
| void copyMiscRegs(ExecContext * xc); |
| |
| bool isHyperPriv() { return hpstateFields.hpriv; } |
| bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; } |
| bool isNonPriv() { return !isPriv(); } |
| }; |
| |
| typedef union |
| { |
| IntReg intreg; |
| FloatReg fpreg; |
| MiscReg ctrlreg; |
| } AnyReg; |
| |
| class RegFile |
| { |
| protected: |
| Addr pc; // Program Counter |
| Addr npc; // Next Program Counter |
| Addr nnpc; |
| |
| public: |
| Addr readPC() |
| { |
| return pc; |
| } |
| |
| void setPC(Addr val) |
| { |
| pc = val; |
| } |
| |
| Addr readNextPC() |
| { |
| return npc; |
| } |
| |
| void setNextPC(Addr val) |
| { |
| npc = val; |
| } |
| |
| Addr readNextNPC() |
| { |
| return nnpc; |
| } |
| |
| void setNextNPC(Addr val) |
| { |
| nnpc = val; |
| } |
| |
| protected: |
| IntRegFile intRegFile; // integer register file |
| FloatRegFile floatRegFile; // floating point register file |
| MiscRegFile miscRegFile; // control register file |
| |
| public: |
| |
| void clear() |
| { |
| intRegFile.clear(); |
| floatRegFile.clear(); |
| } |
| |
| int FlattenIntIndex(int reg) |
| { |
| return intRegFile.flattenIndex(reg); |
| } |
| |
| MiscReg readMiscReg(int miscReg) |
| { |
| return miscRegFile.readReg(miscReg); |
| } |
| |
| MiscReg readMiscRegWithEffect(int miscReg, |
| Fault &fault, ExecContext *xc) |
| { |
| return miscRegFile.readRegWithEffect(miscReg, fault, xc); |
| } |
| |
| Fault setMiscReg(int miscReg, const MiscReg &val) |
| { |
| return miscRegFile.setReg(miscReg, val); |
| } |
| |
| Fault setMiscRegWithEffect(int miscReg, const MiscReg &val, |
| ExecContext * xc) |
| { |
| return miscRegFile.setRegWithEffect(miscReg, val, xc); |
| } |
| |
| FloatReg readFloatReg(int floatReg, int width) |
| { |
| return floatRegFile.readReg(floatReg, width); |
| } |
| |
| FloatReg readFloatReg(int floatReg) |
| { |
| //Use the "natural" width of a single float |
| return floatRegFile.readReg(floatReg, FloatRegFile::SingleWidth); |
| } |
| |
| FloatRegBits readFloatRegBits(int floatReg, int width) |
| { |
| return floatRegFile.readRegBits(floatReg, width); |
| } |
| |
| FloatRegBits readFloatRegBits(int floatReg) |
| { |
| //Use the "natural" width of a single float |
| return floatRegFile.readRegBits(floatReg, |
| FloatRegFile::SingleWidth); |
| } |
| |
| Fault setFloatReg(int floatReg, const FloatReg &val, int width) |
| { |
| return floatRegFile.setReg(floatReg, val, width); |
| } |
| |
| Fault setFloatReg(int floatReg, const FloatReg &val) |
| { |
| //Use the "natural" width of a single float |
| return setFloatReg(floatReg, val, FloatRegFile::SingleWidth); |
| } |
| |
| Fault setFloatRegBits(int floatReg, const FloatRegBits &val, int width) |
| { |
| return floatRegFile.setRegBits(floatReg, val, width); |
| } |
| |
| Fault setFloatRegBits(int floatReg, const FloatRegBits &val) |
| { |
| //Use the "natural" width of a single float |
| return floatRegFile.setRegBits(floatReg, val, |
| FloatRegFile::SingleWidth); |
| } |
| |
| IntReg readIntReg(int intReg) |
| { |
| return intRegFile.readReg(intReg); |
| } |
| |
| Fault setIntReg(int intReg, const IntReg &val) |
| { |
| return intRegFile.setReg(intReg, val); |
| } |
| |
| void serialize(std::ostream &os); |
| void unserialize(Checkpoint *cp, const std::string §ion); |
| |
| public: |
| |
| enum ContextParam |
| { |
| CONTEXT_CWP, |
| CONTEXT_GLOBALS |
| }; |
| typedef int ContextVal; |
| |
| void changeContext(ContextParam param, ContextVal val) |
| { |
| switch(param) |
| { |
| case CONTEXT_CWP: |
| intRegFile.setCWP(val); |
| break; |
| case CONTEXT_GLOBALS: |
| intRegFile.setGlobals(val); |
| break; |
| default: |
| panic("Tried to set illegal context parameter in the SPARC regfile.\n"); |
| } |
| } |
| }; |
| |
| void copyRegs(ExecContext *src, ExecContext *dest); |
| |
| void copyMiscRegs(ExecContext *src, ExecContext *dest); |
| |
| int InterruptLevel(uint64_t softint); |
| |
| } // namespace SparcISA |
| |
| #endif |