|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #ifndef __ARCH_SPARC_ISA_TRAITS_HH__ | 
|  | #define __ARCH_SPARC_ISA_TRAITS_HH__ | 
|  |  | 
|  | #include "arch/sparc/faults.hh" | 
|  | #include "base/misc.hh" | 
|  | #include "config/full_system.hh" | 
|  | #include "sim/host.hh" | 
|  |  | 
|  | //This makes sure the big endian versions of certain functions are used. | 
|  | namespace BigEndianGuest {} | 
|  | using namespace BigEndianGuest; | 
|  |  | 
|  | class ExecContext; | 
|  | class FastCPU; | 
|  | //class FullCPU; | 
|  | class Checkpoint; | 
|  |  | 
|  | #define TARGET_SPARC | 
|  |  | 
|  | class StaticInst; | 
|  | class StaticInstPtr; | 
|  |  | 
|  | //namespace EV5 | 
|  | //{ | 
|  | //	int DTB_ASN_ASN(uint64_t reg); | 
|  | //	int ITB_ASN_ASN(uint64_t reg); | 
|  | //} | 
|  |  | 
|  | namespace SparcISA | 
|  | { | 
|  | typedef uint32_t MachInst; | 
|  | typedef uint64_t ExtMachInst; | 
|  | typedef uint8_t  RegIndex; | 
|  |  | 
|  | const int NumFloatRegs = 32; | 
|  | const int NumMiscRegs = 32; | 
|  |  | 
|  | const int // Maximum trap level | 
|  | const int MaxTL = 4; | 
|  | const int | 
|  | const int // semantically meaningful register indices | 
|  | const int ZeroReg = 0;	// architecturally meaningful | 
|  | const int // the rest of these depend on the ABI | 
|  | const int StackPointerReg = 14; | 
|  | const int ReturnAddressReg = 31; // post call, precall is 15 | 
|  | const int ReturnValueReg = 8; // Post return, 24 is pre-return. | 
|  | const int FramePointerReg = 30; | 
|  | const int ArgumentReg0 = 8; | 
|  | const int ArgumentReg1 = 9; | 
|  | const int ArgumentReg2 = 10; | 
|  | const int ArgumentReg3 = 11; | 
|  | const int ArgumentReg4 = 12; | 
|  | const int ArgumentReg5 = 13; | 
|  | // Some OS syscall sue a second register (o1) to return a second value | 
|  | const int SyscallPseudoReturnReg = ArgumentReg1; | 
|  |  | 
|  |  | 
|  | //8K. This value is implmentation specific; and should probably | 
|  | //be somewhere else. | 
|  | const int LogVMPageSize = 13; | 
|  | const int VMPageSize = (1 << LogVMPageSize); | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | typedef uint64_t IntReg; | 
|  |  | 
|  | class IntRegFile | 
|  | { | 
|  | private: | 
|  | //For right now, let's pretend the register file is static | 
|  | IntReg regs[32]; | 
|  | public: | 
|  | IntReg & operator [] (RegIndex index) | 
|  | { | 
|  | //Don't allow indexes outside of the 32 registers | 
|  | index &= 0x1F; | 
|  | return regs[index]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | void serialize(std::ostream & os); | 
|  |  | 
|  | void unserialize(Checkpoint *cp, const std::string §ion); | 
|  |  | 
|  | typedef float float32_t; | 
|  | typedef double float64_t; | 
|  | //FIXME This actually usually refers to a 10 byte float, rather than a | 
|  | //16 byte float as required. This data type may have to be emulated. | 
|  | typedef long double float128_t; | 
|  |  | 
|  | class FloatRegFile | 
|  | { | 
|  | private: | 
|  | //By using the largest data type, we ensure everything | 
|  | //is aligned correctly in memory | 
|  | union | 
|  | { | 
|  | float128_t rawRegs[16]; | 
|  | uint64_t regDump[32]; | 
|  | }; | 
|  | class QuadRegs | 
|  | { | 
|  | private: | 
|  | FloatRegFile * parent; | 
|  | public: | 
|  | QuadRegs(FloatRegFile * p) : parent(p) {;} | 
|  | float128_t & operator [] (RegIndex index) | 
|  | { | 
|  | //Quad floats are index by the single | 
|  | //precision register the start on, | 
|  | //and only 16 should be accessed | 
|  | index = (index >> 2) & 0xF; | 
|  | return parent->rawRegs[index]; | 
|  | } | 
|  | }; | 
|  | class DoubleRegs | 
|  | { | 
|  | private: | 
|  | FloatRegFile * parent; | 
|  | public: | 
|  | DoubleRegs(FloatRegFile * p) : parent(p) {;} | 
|  | float64_t & operator [] (RegIndex index) | 
|  | { | 
|  | //Double floats are index by the single | 
|  | //precision register the start on, | 
|  | //and only 32 should be accessed | 
|  | index = (index >> 1) & 0x1F; | 
|  | return ((float64_t *)parent->rawRegs)[index]; | 
|  | } | 
|  | }; | 
|  | class SingleRegs | 
|  | { | 
|  | private: | 
|  | FloatRegFile * parent; | 
|  | public: | 
|  | SingleRegs(FloatRegFile * p) : parent(p) {;} | 
|  | float32_t & operator [] (RegIndex index) | 
|  | { | 
|  | //Only 32 single floats should be accessed | 
|  | index &= 0x1F; | 
|  | return ((float32_t *)parent->rawRegs)[index]; | 
|  | } | 
|  | }; | 
|  | public: | 
|  | void serialize(std::ostream & os); | 
|  |  | 
|  | void unserialize(Checkpoint * cp, std::string & section); | 
|  |  | 
|  | QuadRegs quadRegs; | 
|  | DoubleRegs doubleRegs; | 
|  | SingleRegs singleRegs; | 
|  | FloatRegFile() : quadRegs(this), doubleRegs(this), singleRegs(this) | 
|  | {;} | 
|  | }; | 
|  |  | 
|  | // control register file contents | 
|  | typedef uint64_t MiscReg; | 
|  | // The control registers, broken out into fields | 
|  | class MiscRegFile | 
|  | { | 
|  | private: | 
|  | union | 
|  | { | 
|  | uint16_t pstate;		// Process State Register | 
|  | struct | 
|  | { | 
|  | uint16_t ag:1;		// Alternate Globals | 
|  | 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 red:1;		// RED (reset, error, debug) state | 
|  | uint16_t mm:2;		// Memory Model | 
|  | uint16_t tle:1;		// Trap little-endian | 
|  | uint16_t cle:1;		// Current little-endian | 
|  | } pstateFields; | 
|  | }; | 
|  | uint64_t tba;		// Trap Base Address | 
|  | 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; | 
|  | }; | 
|  | uint8_t pil;		// Process Interrupt Register | 
|  | uint8_t cwp;		// Current Window Pointer | 
|  | uint16_t tt[MaxTL];	// Trap Type (Type of trap which occured | 
|  | // on the previous level) | 
|  | 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 | 
|  | uint8_t tl;		// Trap Level | 
|  | 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 :2;	// Reserved bits | 
|  | uint64_t pstate:10;	// Process State | 
|  | uint64_t :6;	// Reserved bits | 
|  | uint64_t asi:8;		// Address Space Identifier | 
|  | uint64_t ccr:8;		// Condition Code Register | 
|  | } tstateFields[MaxTL]; | 
|  | }; | 
|  | union | 
|  | { | 
|  | uint64_t tick;		// Hardware clock-tick counter | 
|  | struct | 
|  | { | 
|  | uint64_t counter:63;	// Clock-tick count | 
|  | uint64_t npt:1;		// Non-priveleged trap | 
|  | } tickFields; | 
|  | }; | 
|  | uint8_t cansave;	// Savable windows | 
|  | uint8_t canrestore;	// Restorable windows | 
|  | uint8_t otherwin;	// Other windows | 
|  | uint8_t cleanwin;	// Clean 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; | 
|  | }; | 
|  | union | 
|  | { | 
|  | uint64_t ver;		// Version | 
|  | struct | 
|  | { | 
|  | uint64_t maxwin:5;	// Max CWP value | 
|  | uint64_t :2;	// Reserved bits | 
|  | uint64_t maxtl:8;	// Maximum trap level | 
|  | uint64_t :8;	// Reserved bits | 
|  | uint64_t mask:8;	// Processor mask set revision number | 
|  | uint64_t impl:16;	// Implementation identification number | 
|  | uint64_t manuf:16;	// Manufacturer code | 
|  | } verFields; | 
|  | }; | 
|  | 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 | 
|  | } cexecFields; | 
|  | }; | 
|  | 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 | 
|  | } aexecFields; | 
|  | }; | 
|  | 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; | 
|  | }; | 
|  | 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; | 
|  | }; | 
|  |  | 
|  | public: | 
|  | MiscReg readReg(int misc_reg); | 
|  |  | 
|  | MiscReg readRegWithEffect(int misc_reg, Fault &fault, ExecContext *xc); | 
|  |  | 
|  | Fault setReg(int misc_reg, const MiscReg &val); | 
|  |  | 
|  | Fault setRegWithEffect(int misc_reg, const MiscReg &val, | 
|  | ExecContext *xc); | 
|  |  | 
|  | void serialize(std::ostream & os); | 
|  |  | 
|  | void unserialize(Checkpoint * cp, std::string & section); | 
|  | }; | 
|  |  | 
|  | typedef union | 
|  | { | 
|  | float32_t singReg; | 
|  | float64_t doubReg; | 
|  | float128_t quadReg; | 
|  | } FloatReg; | 
|  |  | 
|  | typedef union | 
|  | { | 
|  | IntReg  intreg; | 
|  | FloatReg   fpreg; | 
|  | MiscReg ctrlreg; | 
|  | } AnyReg; | 
|  |  | 
|  | struct RegFile | 
|  | { | 
|  | IntRegFile intRegFile;		// (signed) integer register file | 
|  | FloatRegFile floatRegFile;	// floating point register file | 
|  | MiscRegFile miscRegFile;	// control register file | 
|  |  | 
|  | Addr pc;		// Program Counter | 
|  | Addr npc;		// Next Program Counter | 
|  | Addr nnpc; | 
|  |  | 
|  | void serialize(std::ostream &os); | 
|  | void unserialize(Checkpoint *cp, const std::string §ion); | 
|  | }; | 
|  |  | 
|  | StaticInstPtr decodeInst(MachInst); | 
|  |  | 
|  | // return a no-op instruction... used for instruction fetch faults | 
|  | extern const MachInst NoopMachInst; | 
|  |  | 
|  | // Instruction address compression hooks | 
|  | inline Addr realPCToFetchPC(const Addr &addr) | 
|  | { | 
|  | return addr; | 
|  | } | 
|  |  | 
|  | inline Addr fetchPCToRealPC(const Addr &addr) | 
|  | { | 
|  | return addr; | 
|  | } | 
|  |  | 
|  | // the size of "fetched" instructions (not necessarily the size | 
|  | // of real instructions for PISA) | 
|  | inline size_t fetchInstSize() | 
|  | { | 
|  | return sizeof(MachInst); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Function to insure ISA semantics about 0 registers. | 
|  | * @param xc The execution context. | 
|  | */ | 
|  | template <class XC> | 
|  |  | 
|  | static inline setSyscallReturn(SyscallReturn return_value, RegFile *regs) | 
|  | { | 
|  | // check for error condition.  SPARC syscall convention is to | 
|  | // indicate success/failure in reg the carry bit of the ccr | 
|  | // and put the return value itself in the standard return value reg (). | 
|  | if (return_value.successful()) { | 
|  | // no error | 
|  | regs->miscRegFile.ccrFields.iccFields.c = 0; | 
|  | regs->intRegFile[ReturnValueReg] = return_value.value(); | 
|  | } else { | 
|  | // got an error, return details | 
|  | regs->miscRegFile.ccrFields.iccFields.c = 1; | 
|  | regs->intRegFile[ReturnValueReg] = -return_value.value(); | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | #if !FULL_SYSTEM | 
|  | class SyscallReturn | 
|  | { | 
|  | public: | 
|  | template <class T> | 
|  | SyscallReturn(T v, bool s) | 
|  | { | 
|  | retval = (uint64_t)v; | 
|  | success = s; | 
|  | } | 
|  |  | 
|  | template <class T> | 
|  | SyscallReturn(T v) | 
|  | { | 
|  | success = (v >= 0); | 
|  | retval = (uint64_t)v; | 
|  | } | 
|  |  | 
|  | ~SyscallReturn() {} | 
|  |  | 
|  | SyscallReturn& operator=(const SyscallReturn& s) | 
|  | { | 
|  | retval = s.retval; | 
|  | success = s.success; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | bool successful() { return success; } | 
|  | uint64_t value() { return retval; } | 
|  |  | 
|  | private: | 
|  | uint64_t retval; | 
|  | bool success; | 
|  | }; | 
|  |  | 
|  | #endif | 
|  |  | 
|  |  | 
|  | #if FULL_SYSTEM | 
|  |  | 
|  | #include "arch/alpha/ev5.hh" | 
|  | #endif | 
|  |  | 
|  | #endif // __ARCH_SPARC_ISA_TRAITS_HH__ |