diff options
-rw-r--r-- | src/arch/sparc/faults.cc | 48 | ||||
-rw-r--r-- | src/arch/sparc/intregfile.cc | 4 | ||||
-rw-r--r-- | src/arch/sparc/isa/base.isa | 3 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 70 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/priv.isa | 140 | ||||
-rw-r--r-- | src/arch/sparc/isa/operands.isa | 1 | ||||
-rw-r--r-- | src/arch/sparc/isa_traits.hh | 5 | ||||
-rw-r--r-- | src/arch/sparc/tlb.hh | 7 |
8 files changed, 236 insertions, 42 deletions
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 57ee040f1..2564bc6a9 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -283,7 +283,7 @@ void enterREDState(ThreadContext *tc) HPSTATE |= (1 << 5); //HPSTATE.hpriv = 1 HPSTATE |= (1 << 2); - tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + tc->setMiscRegWithEffect(MISCREG_HPSTATE, HPSTATE); } /** @@ -491,11 +491,11 @@ void doNormalFault(ThreadContext *tc, TrapType tt, bool gotoHpriv) } } -void getREDVector(Addr & PC, Addr & NPC) +void getREDVector(MiscReg TT, Addr & PC, Addr & NPC) { //XXX The following constant might belong in a header file. const Addr RSTVAddr = 0xFFFFFFFFF0000000ULL; - PC = RSTVAddr | 0xA0; + PC = RSTVAddr | ((TT << 5) & 0xFF); NPC = PC + sizeof(MachInst); } @@ -519,6 +519,7 @@ void getPrivVector(ThreadContext * tc, Addr & PC, Addr & NPC, MiscReg TT, MiscRe void SparcFaultBase::invoke(ThreadContext * tc) { + panic("Invoking a second fault!\n"); FaultBase::invoke(tc); countStat()++; @@ -543,7 +544,7 @@ void SparcFaultBase::invoke(ThreadContext * tc) if(HPSTATE & (1 << 5) || TL == MaxTL - 1) { - getREDVector(PC, NPC); + getREDVector(5, PC, NPC); enterREDState(tc); doREDFault(tc, TT); } @@ -583,28 +584,41 @@ void PowerOnReset::invoke(ThreadContext * tc) //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 + tc->setMiscReg(MISCREG_TL, MaxTL); + tc->setMiscReg(MISCREG_TT, trapType()); + tc->setMiscRegWithEffect(MISCREG_GL, MaxGL); + + //Turn on pef, set everything else to 0 + tc->setMiscReg(MISCREG_PSTATE, 1 << 4); - softint = 0; // Clear all the soft interrupt bits - tick_cmprFields.int_dis = 1; // disable timer compare interrupts + //Turn on red and hpriv, set everything else to 0 + tc->setMiscReg(MISCREG_HPSTATE, (1 << 5) | (1 << 2)); + + //The tick register is unreadable by nonprivileged software + tc->setMiscReg(MISCREG_TICK, 1ULL << 63); + + Addr PC, NPC; + getREDVector(trapType(), PC, NPC); + tc->setPC(PC); + tc->setNextPC(NPC); + tc->setNextNPC(NPC + sizeof(MachInst)); + + //These registers are specified as "undefined" after a POR, and they + //should have reasonable values after the miscregfile is reset + /* + // Clear all the soft interrupt bits + softint = 0; + // disable timer compare interrupts, reset tick_cmpr + tc->setMiscReg(MISCREG_ + tick_cmprFields.int_dis = 1; 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] = _trapType; - 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 diff --git a/src/arch/sparc/intregfile.cc b/src/arch/sparc/intregfile.cc index 0e313dc94..358368e5f 100644 --- a/src/arch/sparc/intregfile.cc +++ b/src/arch/sparc/intregfile.cc @@ -83,7 +83,7 @@ IntReg IntRegFile::readReg(int intReg) else if((intReg -= NumRegularIntRegs) < NumMicroIntRegs) val = microRegs[intReg]; else - panic("Tried to read non-existant integer register\n"); + panic("Tried to read non-existant integer register %d, %d\n", NumRegularIntRegs + NumMicroIntRegs + intReg, intReg); DPRINTF(Sparc, "Read register %d = 0x%x\n", intReg, val); return val; @@ -123,7 +123,7 @@ void IntRegFile::setCWP(int cwp) void IntRegFile::setGlobals(int gl) { - DPRINTF(Sparc, "Now using %d globals", gl); + DPRINTF(Sparc, "Now using %d globals\n", gl); regView[Globals] = regGlobals[gl]; offset[Globals] = RegGlobalOffset + gl * RegsPerFrame; diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index a4c022411..122ad2b52 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -189,6 +189,7 @@ output decoder {{ const int MaxOutput = 16; const int MaxLocal = 24; const int MaxInput = 32; + const int MaxMicroReg = 33; if (reg == FramePointerReg) ccprintf(os, "%%fp"); else if (reg == StackPointerReg) @@ -201,6 +202,8 @@ output decoder {{ ccprintf(os, "%%l%d", reg - MaxOutput); else if(reg < MaxInput) ccprintf(os, "%%i%d", reg - MaxLocal); + else if(reg < MaxMicroReg) + ccprintf(os, "%%u%d", reg - MaxInput); else { ccprintf(os, "%%f%d", reg - FP_Base_DepTag); } diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 4f3ea7810..2c8e59a1d 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -41,15 +41,16 @@ decode OP default Unknown::unknown() 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); format BranchN { + //bpcc 0x1: decode COND2 { //Branch Always 0x8: decode A { - 0x0: b(19, {{ + 0x0: bpa(19, {{ NNPC = xc->readPC() + disp; }}); - 0x1: b(19, {{ + 0x1: bpa(19, {{ NPC = xc->readPC() + disp; NNPC = NPC + 4; }}, ',a'); @@ -57,10 +58,10 @@ decode OP default Unknown::unknown() //Branch Never 0x0: decode A { - 0x0: bn(19, {{ + 0x0: bpn(19, {{ NNPC = NNPC;//Don't do anything }}); - 0x1: bn(19, {{ + 0x1: bpn(19, {{ NPC = xc->readNextPC() + 4; NNPC = NPC + 4; }}, ',a'); @@ -81,12 +82,38 @@ decode OP default Unknown::unknown() }}); } } - 0x2: bicc(22, {{ - if(passesCondition(Ccr<3:0>, COND2)) - NNPC = xc->readPC() + disp; - else - handle_annul - }}); + //bicc + 0x2: decode COND2 + { + //Branch Always + 0x8: decode A + { + 0x0: ba(22, {{ + NNPC = xc->readPC() + disp; + }}); + 0x1: ba(22, {{ + NPC = xc->readPC() + disp; + NNPC = NPC + 4; + }}, ',a'); + } + //Branch Never + 0x0: decode A + { + 0x0: bn(22, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: bn(22, {{ + NPC = xc->readNextPC() + 4; + NNPC = NPC + 4; + }}, ',a'); + } + default: bicc(22, {{ + if(passesCondition(Ccr<3:0>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } } 0x3: decode RCOND2 { @@ -380,7 +407,15 @@ decode OP default Unknown::unknown() 0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}}); 0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}}); 0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}}); - //0x1A-0x1F should cause an illegal instruction exception + 0x1A: Priv::rdstrand_sts_reg({{ + if(Pstate<2:> && !Hpstate<2:>) + Rd = StrandStsReg<0:>; + else + Rd = StrandStsReg; + }}); + //0x1A is supposed to be reserved, but it reads the strand + //status register. + //0x1B-0x1F should cause an illegal instruction exception } 0x29: decode RS1 { 0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}}); @@ -515,7 +550,16 @@ decode OP default Unknown::unknown() Stick = Rs1 ^ Rs2_or_imm13; }}); 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); - //0x1A-0x1F should cause an illegal instruction exception + 0x1A: Priv::wrstrand_sts_reg({{ + if(Pstate<2:> && !Hpstate<2:>) + StrandStsReg = StrandStsReg<63:1> | + (Rs1 ^ Rs2_or_imm13)<0:>; + else + StrandStsReg = Rs1 ^ Rs2_or_imm13; + }}); + //0x1A is supposed to be reserved, but it writes the strand + //status register. + //0x1B-0x1F should cause an illegal instruction exception } 0x31: decode FCN { 0x0: Priv::saved({{ @@ -527,7 +571,7 @@ decode OP default Unknown::unknown() else Otherwin = Otherwin - 1; }}); - 0x1: BasicOperate::restored({{ + 0x1: Priv::restored({{ assert(Cansave || Otherwin); assert(Canrestore < NWindows - 2); Canrestore = Canrestore + 1; diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 55bf968f4..94a68aebe 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -50,6 +50,42 @@ output header {{ const SymbolTable *symtab) const; }; + //This class is for instructions that explicitly read control + //registers. It provides a special generateDisassembly function. + class RdPriv : public Priv + { + protected: + //Constructor + RdPriv(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + Priv(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; + + //This class is for instructions that explicitly write control + //registers. It provides a special generateDisassembly function. + class WrPriv : public Priv + { + protected: + //Constructor + WrPriv(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + Priv(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; + /** * Base class for privelege mode operations with immediates. */ @@ -66,6 +102,23 @@ output header {{ int32_t imm; }; + //This class is for instructions that explicitly write control + //registers. It provides a special generateDisassembly function. + class WrPrivImm : public PrivImm + { + protected: + //Constructor + WrPrivImm(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + PrivImm(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; }}; output decoder {{ @@ -78,6 +131,58 @@ output decoder {{ return response.str(); } + + std::string RdPriv::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " %%%s, ", regName); + printDestReg(response, 0); + + return response.str(); + } + + std::string WrPriv::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " "); + printSrcReg(response, 0); + ccprintf(response, ", "); + printSrcReg(response, 1); + ccprintf(response, ", %%%s", regName); + + return response.str(); + } + + std::string WrPrivImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " "); + printSrcReg(response, 0); + ccprintf(response, ", 0x%x, %%%s", imm, regName); + + return response.str(); + } +}}; + +def template ControlRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, + %(op_class)s, "%(reg_name)s") + { + %(constructor)s; + } }}; def template PrivExecute {{ @@ -102,16 +207,39 @@ let {{ def doPrivFormat(code, checkCode, name, Name, opt_flags): (usesImm, code, immCode, rString, iString) = splitOutImm(code) - iop = InstObjParams(name, Name, 'Priv', code, - opt_flags, {"check": checkCode}) + #If these are rd, rdpr, rdhpr, wr, wrpr, or wrhpr instructions, + #cut any other info out of the mnemonic. Also pick a different + #base class. + regBase = 'Priv' + regName = '' + for mnem in ["rdhpr", "rdpr", "rd"]: + if name.startswith(mnem): + regName = name[len(mnem):] + name = mnem + regBase = 'RdPriv' + break + for mnem in ["wrhpr", "wrpr", "wr"]: + if name.startswith(mnem): + regName = name[len(mnem):] + name = mnem + regBase = 'WrPriv' + break + iop = InstObjParams(name, Name, regBase, code, + opt_flags, {"check": checkCode, "reg_name": regName}) header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) + if regName == '': + decoder_output = BasicConstructor.subst(iop) + else: + decoder_output = ControlRegConstructor.subst(iop) exec_output = PrivExecute.subst(iop) if usesImm: - imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm', - immCode, opt_flags, {"check": checkCode}) + imm_iop = InstObjParams(name, Name + 'Imm', regBase + 'Imm', + immCode, opt_flags, {"check": checkCode, "reg_name": regName}) header_output += BasicDeclare.subst(imm_iop) - decoder_output += BasicConstructor.subst(imm_iop) + if regName == '': + decoder_output += BasicConstructor.subst(imm_iop) + else: + decoder_output += ControlRegConstructor.subst(imm_iop) exec_output += PrivExecute.subst(imm_iop) decode_block = ROrImmDecode.subst(iop) else: diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index caee20b0c..2d200f568 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -123,6 +123,7 @@ def operands {{ 'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72), 'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73), 'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74), + 'StrandStsReg': ('ControlReg', 'udw', 'MISCREG_STRAND_STS_REG', None, 75), 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80), # Mem gets a large number so it's always last diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 46a0ebbfb..1433ba3f8 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -76,10 +76,7 @@ namespace SparcISA // 0..31 are the integer regs 0..31 // 32..95 are the FP regs 0..31, i.e. use (reg + FP_Base_DepTag) FP_Base_DepTag = NumIntRegs, - Ctrl_Base_DepTag = NumIntRegs + NumFloatRegs, - //XXX These are here solely to get compilation and won't work - Fpcr_DepTag = 0, - Uniq_DepTag = 0 + Ctrl_Base_DepTag = NumIntRegs + NumMicroIntRegs + NumFloatRegs, }; diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh index 0fdba6baf..7a9a6aea1 100644 --- a/src/arch/sparc/tlb.hh +++ b/src/arch/sparc/tlb.hh @@ -31,6 +31,7 @@ #ifndef __ARCH_SPARC_TLB_HH__ #define __ARCH_SPARC_TLB_HH__ +#include "base/misc.hh" #include "mem/request.hh" #include "sim/faults.hh" #include "sim/sim_object.hh" @@ -56,6 +57,9 @@ namespace SparcISA Fault translate(RequestPtr &req, ThreadContext *tc) const { + //For now, always assume the address is already physical. + //Also assume that there are 40 bits of physical address space. + req->setPaddr(req->getVaddr() & ((1ULL << 40) - 1)); return NoFault; } }; @@ -69,6 +73,9 @@ namespace SparcISA Fault translate(RequestPtr &req, ThreadContext *tc, bool write) const { + //For now, always assume the address is already physical. + //Also assume that there are 40 bits of physical address space. + req->setPaddr(req->getVaddr() & ((1ULL << 40) - 1)); return NoFault; } }; |