diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/arch/isa_parser.py | 2 | ||||
-rw-r--r-- | src/arch/sparc/faults.cc | 163 | ||||
-rw-r--r-- | src/arch/sparc/faults.hh | 6 | ||||
-rw-r--r-- | src/arch/sparc/isa/bitfields.isa | 2 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 75 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/priv.isa | 5 | ||||
-rw-r--r-- | src/arch/sparc/isa/operands.isa | 21 | ||||
-rw-r--r-- | src/arch/sparc/isa_traits.hh | 9 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.cc | 224 | ||||
-rw-r--r-- | src/arch/sparc/miscregfile.hh | 29 | ||||
-rw-r--r-- | src/arch/sparc/process.cc | 106 | ||||
-rw-r--r-- | src/arch/sparc/process.hh | 9 | ||||
-rw-r--r-- | src/arch/sparc/regfile.cc | 9 | ||||
-rw-r--r-- | src/base/bitfield.hh | 24 |
14 files changed, 424 insertions, 260 deletions
diff --git a/src/arch/isa_parser.py b/src/arch/isa_parser.py index b235398f1..6504c7b32 100755 --- a/src/arch/isa_parser.py +++ b/src/arch/isa_parser.py @@ -1316,7 +1316,7 @@ class ControlRegOperand(Operand): def makeWrite(self): if (self.ctype == 'float' or self.ctype == 'double'): error(0, 'Attempt to write control register as FP') - wb = 'xc->setMiscReg(%s, %s);\n' % (self.reg_spec, self.base_name) + wb = 'xc->setMiscRegWithEffect(%s, %s);\n' % (self.reg_spec, self.base_name) wb += 'if (traceData) { traceData->setData(%s); }' % \ self.base_name return wb diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index 7b7765935..2c8da44c5 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -29,15 +29,22 @@ * Kevin Lim */ +#include <algorithm> + #include "arch/sparc/faults.hh" -#include "cpu/thread_context.hh" -#include "cpu/base.hh" +#include "arch/sparc/isa_traits.hh" +#include "arch/sparc/process.hh" +#include "base/bitfield.hh" #include "base/trace.hh" +#include "cpu/base.hh" +#include "cpu/thread_context.hh" #if !FULL_SYSTEM -#include "sim/process.hh" #include "mem/page_table.hh" +#include "sim/process.hh" #endif +using namespace std; + namespace SparcISA { @@ -229,6 +236,121 @@ FaultPriority PageTableFault::_priority = 0; FaultStat PageTableFault::_count; #endif +/** + * This sets everything up for a normal trap except for actually jumping to + * the handler. It will need to be expanded to include the state machine in + * the manual. Right now it assumes that traps will always be to the + * privileged level. + */ + +void doNormalFault(ThreadContext *tc, TrapType tt) +{ + uint64_t TL = tc->readMiscReg(MISCREG_TL); + uint64_t TSTATE = tc->readMiscReg(MISCREG_TSTATE); + uint64_t PSTATE = tc->readMiscReg(MISCREG_PSTATE); + uint64_t HPSTATE = tc->readMiscReg(MISCREG_HPSTATE); + uint64_t CCR = tc->readMiscReg(MISCREG_CCR); + uint64_t ASI = tc->readMiscReg(MISCREG_ASI); + uint64_t CWP = tc->readMiscReg(MISCREG_CWP); + uint64_t CANSAVE = tc->readMiscReg(MISCREG_CANSAVE); + uint64_t GL = tc->readMiscReg(MISCREG_GL); + uint64_t PC = tc->readPC(); + uint64_t NPC = tc->readNextPC(); + + //Increment the trap level + TL++; + tc->setMiscReg(MISCREG_TL, TL); + + //Save off state + + //set TSTATE.gl to gl + replaceBits(TSTATE, 42, 40, GL); + //set TSTATE.ccr to ccr + replaceBits(TSTATE, 39, 32, CCR); + //set TSTATE.asi to asi + replaceBits(TSTATE, 31, 24, ASI); + //set TSTATE.pstate to pstate + replaceBits(TSTATE, 20, 8, PSTATE); + //set TSTATE.cwp to cwp + replaceBits(TSTATE, 4, 0, CWP); + + //Write back TSTATE + tc->setMiscReg(MISCREG_TSTATE, TSTATE); + + //set TPC to PC + tc->setMiscReg(MISCREG_TPC, PC); + //set TNPC to NPC + tc->setMiscReg(MISCREG_TNPC, NPC); + + //set HTSTATE.hpstate to hpstate + tc->setMiscReg(MISCREG_HTSTATE, HPSTATE); + + //TT = trap type; + tc->setMiscReg(MISCREG_TT, tt); + + //Update the global register level + if(1/*We're delivering the trap in priveleged mode*/) + tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxGL)); + else + tc->setMiscReg(MISCREG_GL, max<int>(GL+1, MaxPGL)); + + //PSTATE.mm is unchanged + //PSTATE.pef = whether or not an fpu is present + //XXX We'll say there's one present, even though there aren't + //implementations for a decent number of the instructions + PSTATE |= (1 << 4); + //PSTATE.am = 0 + PSTATE &= ~(1 << 3); + if(1/*We're delivering the trap in priveleged mode*/) + { + //PSTATE.priv = 1 + PSTATE |= (1 << 2); + //PSTATE.cle = PSTATE.tle + replaceBits(PSTATE, 9, 9, PSTATE >> 8); + } + else + { + //PSTATE.priv = 0 + PSTATE &= ~(1 << 2); + //PSTATE.cle = 0 + PSTATE &= ~(1 << 9); + } + //PSTATE.ie = 0 + PSTATE &= ~(1 << 1); + //PSTATE.tle is unchanged + //PSTATE.tct = 0 + //XXX Where exactly is this field? + tc->setMiscReg(MISCREG_PSTATE, PSTATE); + + if(0/*We're delivering the trap in hyperprivileged mode*/) + { + //HPSTATE.red = 0 + HPSTATE &= ~(1 << 5); + //HPSTATE.hpriv = 1 + HPSTATE |= (1 << 2); + //HPSTATE.ibe = 0 + HPSTATE &= ~(1 << 10); + //HPSTATE.tlz is unchanged + tc->setMiscReg(MISCREG_HPSTATE, HPSTATE); + } + + bool changedCWP = true; + if(tt == 0x24) + CWP++; + else if(0x80 <= tt && tt <= 0xbf) + CWP += (CANSAVE + 2); + else if(0xc0 <= tt && tt <= 0xff) + CWP--; + else + changedCWP = false; + + if(changedCWP) + { + CWP = (CWP + NWindows) % NWindows; + tc->setMiscRegWithEffect(MISCREG_CWP, CWP); + } +} + #if FULL_SYSTEM void SparcFault::invoke(ThreadContext * tc) @@ -263,6 +385,40 @@ void TrapInstruction::invoke(ThreadContext * tc) // Should be handled in ISA. } +void SpillNNormal::invoke(ThreadContext *tc) +{ + doNormalFault(tc, trapType()); + + Process *p = tc->getProcessPtr(); + + //This will only work in faults from a SparcLiveProcess + SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); + assert(lp); + + //Then adjust the PC and NPC + Addr spillStart = lp->readSpillStart(); + tc->setPC(spillStart); + tc->setNextPC(spillStart + sizeof(MachInst)); + tc->setNextNPC(spillStart + 2*sizeof(MachInst)); +} + +void FillNNormal::invoke(ThreadContext *tc) +{ + doNormalFault(tc, trapType()); + + Process * p = tc->getProcessPtr(); + + //This will only work in faults from a SparcLiveProcess + SparcLiveProcess *lp = dynamic_cast<SparcLiveProcess *>(p); + assert(lp); + + //The adjust the PC and NPC + Addr fillStart = lp->readFillStart(); + tc->setPC(fillStart); + tc->setNextPC(fillStart + sizeof(MachInst)); + tc->setNextNPC(fillStart + 2*sizeof(MachInst)); +} + void PageTableFault::invoke(ThreadContext *tc) { Process *p = tc->getProcessPtr(); @@ -282,6 +438,7 @@ void PageTableFault::invoke(ThreadContext *tc) FaultBase::invoke(tc); } } + #endif } // namespace SparcISA diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh index b279f4911..394a06294 100644 --- a/src/arch/sparc/faults.hh +++ b/src/arch/sparc/faults.hh @@ -39,8 +39,8 @@ namespace SparcISA { -typedef const uint32_t TrapType; -typedef const uint32_t FaultPriority; +typedef uint32_t TrapType; +typedef uint32_t FaultPriority; class SparcFault : public FaultBase { @@ -547,6 +547,7 @@ class SpillNNormal : public EnumeratedFault FaultName name() {return _name;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); }; class SpillNOther : public EnumeratedFault @@ -577,6 +578,7 @@ class FillNNormal : public EnumeratedFault FaultName name() {return _name;} FaultPriority priority() {return _priority;} FaultStat & countStat() {return _count;} + void invoke(ThreadContext * tc); }; class FillNOther : public EnumeratedFault diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index 372f5c4ef..7e884866c 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -50,7 +50,7 @@ def bitfield D16LO <13:0>; def bitfield DISP19 <18:0>; def bitfield DISP22 <21:0>; def bitfield DISP30 <29:0>; -def bitfield FCN <29:26>; +def bitfield FCN <29:25>; def bitfield I <13>; def bitfield IMM_ASI <12:5>; def bitfield IMM22 <21:0>; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 45d3616d9..dc7597e5e 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -357,13 +357,9 @@ decode OP default Unknown::unknown() }}); } 0x29: HPriv::rdhpr({{ - // XXX Need to protect with format that traps non-priv/priv - // access Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault); }}); 0x2A: Priv::rdpr({{ - // XXX Need to protect with format that traps non-priv - // access Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault); }}); 0x2B: BasicOperate::flushw({{ @@ -425,18 +421,34 @@ decode OP default Unknown::unknown() xc->setMiscRegWithEffect(RD + AsrStart, Rs1 ^ Rs2_or_imm13); }}); 0x31: decode FCN { - 0x0: BasicOperate::saved({{/*Boogy Boogy*/}}); - 0x1: BasicOperate::restored({{/*Boogy Boogy*/}}); + 0x0: Priv::saved({{ + assert(Cansave < NWindows - 2); + assert(Otherwin || Canrestore); + Cansave = Cansave + 1; + if(Otherwin == 0) + Canrestore = Canrestore - 1; + else + Otherwin = Otherwin - 1; + }}); + 0x1: BasicOperate::restored({{ + assert(Cansave || Otherwin); + assert(Canrestore < NWindows - 2); + Canrestore = Canrestore + 1; + if(Otherwin == 0) + Cansave = Cansave - 1; + else + Otherwin = Otherwin - 1; + }}); } 0x32: Priv::wrpr({{ // XXX Need to protect with format that traps non-priv // access - fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); + xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13); }}); 0x33: HPriv::wrhpr({{ // XXX Need to protect with format that traps non-priv/priv // access - fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); + xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13); }}); 0x34: decode OPF{ format BasicOperate{ @@ -684,10 +696,6 @@ decode OP default Unknown::unknown() NNPC = target; if(fault == NoFault) { - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one - Cwp = (Cwp - 1 + NWindows) % NWindows; if(Canrestore == 0) { if(Otherwin) @@ -697,14 +705,17 @@ decode OP default Unknown::unknown() } else { - Rd = Rs1 + Rs2_or_imm13; + //CWP should be set directly so that it always happens + //Also, this will allow writing to the new window and + //reading from the old one + Cwp = (Cwp - 1 + NWindows) % NWindows; Cansave = Cansave + 1; Canrestore = Canrestore - 1; + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } }}); 0x3A: decode CC @@ -747,11 +758,11 @@ decode OP default Unknown::unknown() fault = new SpillNOther(Wstate<5:3>); else fault = new SpillNNormal(Wstate<2:0>); - Cwp = (Cwp + 2) % NWindows; + //Cwp = (Cwp + 2) % NWindows; } else if(Cleanwin - Canrestore == 0) { - Cwp = (Cwp + 1) % NWindows; + //Cwp = (Cwp + 1) % NWindows; fault = new CleanWindow; } else @@ -760,17 +771,13 @@ decode OP default Unknown::unknown() Rd = Rs1 + Rs2_or_imm13; Cansave = Cansave - 1; Canrestore = Canrestore + 1; + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); }}); 0x3D: restore({{ - //CWP should be set directly so that it always happens - //Also, this will allow writing to the new window and - //reading from the old one - Cwp = (Cwp - 1 + NWindows) % NWindows; if(Canrestore == 0) { if(Otherwin) @@ -780,14 +787,18 @@ decode OP default Unknown::unknown() } else { + //CWP should be set directly so that it always happens + //Also, this will allow writing to the new window and + //reading from the old one + Cwp = (Cwp - 1 + NWindows) % NWindows; Rd = Rs1 + Rs2_or_imm13; Cansave = Cansave + 1; Canrestore = Canrestore - 1; + //This is here to make sure the CWP is written + //no matter what. This ensures that the results + //are written in the new window as well. + xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); } - //This is here to make sure the CWP is written - //no matter what. This ensures that the results - //are written in the new window as well. - xc->setMiscRegWithEffect(MISCREG_CWP, Cwp); }}); 0x3E: decode FCN { 0x0: Priv::done({{ @@ -812,7 +823,7 @@ decode OP default Unknown::unknown() Ccr = Tstate<39:32>; Gl = Tstate<42:40>; NPC = Tpc; - NNPC = Tnpc + 4; + NNPC = Tnpc; Tl = Tl - 1; }}); } diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 2a38422a7..04c67d332 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -121,15 +121,14 @@ let {{ // Primary format for integer operate instructions: def format Priv(code, *opt_flags) {{ - checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) || - ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)''' + checkCode = "!(Pstate<2:2> || Hpstate<2:2>)" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, checkCode, name, Name, opt_flags + ('IprAccessOp',)) }}; def format HPriv(code, *opt_flags) {{ - checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)" + checkCode = "!Hpstate<2:2>" (header_output, decoder_output, exec_output, decode_block) = doPrivFormat(code, checkCode, name, Name, opt_flags + ('IprAccessOp',)) diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index b8b75170b..ba2c38e91 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -95,18 +95,19 @@ def operands {{ 'Tnpc': ('ControlReg', 'udw', 'MISCREG_TNPC', None, 44), 'Tstate': ('ControlReg', 'udw', 'MISCREG_TSTATE', None, 45), 'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 46), - 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 47), + 'Hpstate': ('ControlReg', 'udw', 'MISCREG_HPSTATE', None, 47), + 'Tl': ('ControlReg', 'udw', 'MISCREG_TL', None, 48), - 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 48), - 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 49), - 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 50), - 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 51), - 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 52), - 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 53), - 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 54), + 'Cwp': ('ControlReg', 'udw', 'MISCREG_CWP', None, 49), + 'Cansave': ('ControlReg', 'udw', 'MISCREG_CANSAVE', None, 50), + 'Canrestore': ('ControlReg', 'udw', 'MISCREG_CANRESTORE', None, 51), + 'Cleanwin': ('ControlReg', 'udw', 'MISCREG_CLEANWIN', None, 52), + 'Otherwin': ('ControlReg', 'udw', 'MISCREG_OTHERWIN', None, 53), + 'Wstate': ('ControlReg', 'udw', 'MISCREG_WSTATE', None, 54), + 'Gl': ('ControlReg', 'udw', 'MISCREG_GL', None, 55), - 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 55), - 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 56), + 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 56), + 'Gsr': ('ControlReg', 'udw', 'MISCREG_GSR', None, 57), # Mem gets a large number so it's always last 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 100) diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh index 6d5aa4251..fb09121a3 100644 --- a/src/arch/sparc/isa_traits.hh +++ b/src/arch/sparc/isa_traits.hh @@ -57,12 +57,11 @@ namespace SparcISA //This makes sure the big endian versions of certain functions are used. using namespace BigEndianGuest; - // Alpha Does NOT have a delay slot + // SPARC have a delay slot #define ISA_HAS_DELAY_SLOT 1 - //TODO this needs to be a SPARC Noop - // Alpha UNOP (ldq_u r31,0(r0)) - const MachInst NoopMachInst = 0x2ffe0000; + // SPARC NOP (sethi %(hi(0), g0) + const MachInst NoopMachInst = 0x01000000; const int NumIntRegs = 32; const int NumFloatRegs = 64; @@ -87,7 +86,7 @@ namespace SparcISA const int MaxPGL = 2; // NWINDOWS - number of register windows, can be 3 to 32 - const int NWindows = 32; + const int NWindows = 8; // semantically meaningful register indices const int ZeroReg = 0; // architecturally meaningful diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc index 8041e45c0..bf4572878 100644 --- a/src/arch/sparc/miscregfile.cc +++ b/src/arch/sparc/miscregfile.cc @@ -202,282 +202,164 @@ MiscReg MiscRegFile::readReg(int miscReg) } } -MiscReg MiscRegFile::readRegWithEffect(int miscReg, - Fault &fault, ThreadContext * tc) +MiscReg MiscRegFile::readRegWithEffect(int miscReg, ThreadContext * tc) { - fault = NoFault; switch (miscReg) { - case MISCREG_Y: - case MISCREG_CCR: - case MISCREG_ASI: - return readReg(miscReg); - case MISCREG_TICK: case MISCREG_PRIVTICK: - // Check for reading privilege - if (tickFields.npt && !isNonPriv()) { - fault = new PrivilegedAction; - return 0; - } return tc->getCpuPtr()->curCycle() - tickFields.counter | tickFields.npt << 63; - case MISCREG_PC: - return tc->readPC(); case MISCREG_FPRS: - fault = new UnimpFault("FPU not implemented\n"); - return 0; + panic("FPU not implemented\n"); case MISCREG_PCR: - fault = new UnimpFault("Performance Instrumentation not impl\n"); - return 0; case MISCREG_PIC: - fault = new UnimpFault("Performance Instrumentation not impl\n"); - return 0; - case MISCREG_GSR: - return readReg(miscReg); - - /** Privilged Registers */ - case MISCREG_TPC: - case MISCREG_TNPC: - case MISCREG_TSTATE: - case MISCREG_TT: - if (tl == 0) { - fault = new IllegalInstruction; - return 0; - } // NOTE THE FALL THROUGH! - case MISCREG_PSTATE: - case MISCREG_TL: - return readReg(miscReg); - - case MISCREG_TBA: - return readReg(miscReg) & ULL(~0x7FFF); - - case MISCREG_PIL: - - case MISCREG_CWP: - case MISCREG_CANSAVE: - case MISCREG_CANRESTORE: - case MISCREG_CLEANWIN: - case MISCREG_OTHERWIN: - case MISCREG_WSTATE: - case MISCREG_GL: - return readReg(miscReg); + panic("Performance Instrumentation not impl\n"); /** Floating Point Status Register */ case MISCREG_FSR: panic("Floating Point not implemented\n"); - default: -#if FULL_SYSTEM - return readFSRegWithEffect(miscReg, fault, tc); -#else - fault = new IllegalInstruction; - return 0; -#endif } + return readReg(miscReg); } -Fault MiscRegFile::setReg(int miscReg, const MiscReg &val) +void MiscRegFile::setReg(int miscReg, const MiscReg &val) { switch (miscReg) { case MISCREG_Y: y = val; - return NoFault; + break; case MISCREG_CCR: ccr = val; - return NoFault; + break; case MISCREG_ASI: asi = val; - return NoFault; + break; case MISCREG_FPRS: fprs = val; - return NoFault; + break; case MISCREG_TICK: - tick = val; - return NoFault; + tick = val; + break; case MISCREG_PCR: case MISCREG_PIC: panic("ASR number %d not implemented\n", miscReg - AsrStart); case MISCREG_GSR: gsr = val; + break; case MISCREG_SOFTINT: - softint = val; - return NoFault; + softint = val; + break; case MISCREG_TICK_CMPR: - tick_cmpr = val; - return NoFault; + tick_cmpr = val; + break; case MISCREG_STICK: - stick = val; - return NoFault; + stick = val; + break; case MISCREG_STICK_CMPR: - stick_cmpr = val; - return NoFault; + stick_cmpr = val; + break; /** Privilged Registers */ case MISCREG_TPC: tpc[tl-1] = val; - return NoFault; + break; case MISCREG_TNPC: tnpc[tl-1] = val; - return NoFault; + break; case MISCREG_TSTATE: tstate[tl-1] = val; - return NoFault; + break; case MISCREG_TT: tt[tl-1] = val; - return NoFault; + break; case MISCREG_PRIVTICK: panic("Priviliged access to tick regesiters not implemented\n"); case MISCREG_TBA: - tba = val; - return NoFault; + // clear lower 7 bits on writes. + tba = val & ULL(~0x7FFF); + break; case MISCREG_PSTATE: pstate = val; - return NoFault; + break; case MISCREG_TL: tl = val; - return NoFault; + break; case MISCREG_PIL: pil = val; - return NoFault; + break; case MISCREG_CWP: cwp = val; - return NoFault; + break; case MISCREG_CANSAVE: cansave = val; - return NoFault; + break; case MISCREG_CANRESTORE: canrestore = val; - return NoFault; + break; case MISCREG_CLEANWIN: cleanwin = val; - return NoFault; + break; case MISCREG_OTHERWIN: otherwin = val; - return NoFault; + break; case MISCREG_WSTATE: wstate = val; - return NoFault; + break; case MISCREG_GL: gl = val; - return NoFault; + break; /** Hyper privileged registers */ case MISCREG_HPSTATE: hpstate = val; - return NoFault; + break; case MISCREG_HTSTATE: htstate[tl-1] = val; - return NoFault; + break; case MISCREG_HINTP: panic("HINTP not implemented\n"); case MISCREG_HTBA: htba = val; - return NoFault; + break; case MISCREG_STRAND_STS_REG: strandStatusReg = val; - return NoFault; + break; case MISCREG_HSTICK_CMPR: hstick_cmpr = val; - return NoFault; + break; /** Floating Point Status Register */ case MISCREG_FSR: fsr = val; - return NoFault; + break; default: panic("Miscellaneous register %d not implemented\n", miscReg); } } -Fault MiscRegFile::setRegWithEffect(int miscReg, +void MiscRegFile::setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { const uint64_t Bit64 = (1ULL << 63); switch (miscReg) { - case MISCREG_Y: - case MISCREG_CCR: - case MISCREG_ASI: - setReg(miscReg, val); - return NoFault; - case MISCREG_PRIVTICK: case MISCREG_TICK: - if (isNonPriv()) - return new PrivilegedOpcode; - if (isPriv()) - return new PrivilegedAction; tickFields.counter = tc->getCpuPtr()->curCycle() - val & ~Bit64; tickFields.npt = val & Bit64 ? 1 : 0; - return NoFault; - case MISCREG_PC: - return new IllegalInstruction; + break; case MISCREG_FPRS: - return new UnimpFault("FPU not implemented\n"); + //Configure the fpu based on the fprs + break; case MISCREG_PCR: - return new UnimpFault("Performance Instrumentation not impl\n"); - case MISCREG_PIC: - return new UnimpFault("Performance Instrumentation not impl\n"); - case MISCREG_GSR: - return setReg(miscReg, val); - - /** Privilged Registers */ - case MISCREG_TPC: - case MISCREG_TNPC: - case MISCREG_TSTATE: - case MISCREG_TT: - if (tl == 0) - return new IllegalInstruction; - setReg(miscReg, val); - return NoFault; - - case MISCREG_TBA: - // clear lower 7 bits on writes. - setReg(miscReg, val & ULL(~0x7FFF)); - return NoFault; - - case MISCREG_PSTATE: - setReg(miscReg, val); - return NoFault; - - case MISCREG_TL: - if (isHyperPriv() && val > MaxTL) - setReg(miscReg, MaxTL); - else if (isPriv() && !isHyperPriv() && val > MaxPTL) - setReg(miscReg, MaxPTL); - else - setReg(miscReg, val); - return NoFault; - + //Set up performance counting based on pcr value + break; case MISCREG_CWP: tc->changeRegFileContext(CONTEXT_CWP, val); - case MISCREG_CANSAVE: - case MISCREG_CANRESTORE: - case MISCREG_CLEANWIN: - case MISCREG_OTHERWIN: - case MISCREG_WSTATE: - setReg(miscReg, val); - return NoFault; - + break; case MISCREG_GL: - int newval; - if (isHyperPriv() && val > MaxGL) - newval = MaxGL; - else if (isPriv() && !isHyperPriv() && val > MaxPGL) - newval = MaxPGL; - else - newval = val; - tc->changeRegFileContext(CONTEXT_GLOBALS, newval); - setReg(miscReg, newval); - return NoFault; - - /** Floating Point Status Register */ - case MISCREG_FSR: - panic("Floating Point not implemented\n"); - default: -#if FULL_SYSTEM - setFSRegWithEffect(miscReg, val, tc); -#else - return new IllegalInstruction; -#endif + tc->changeRegFileContext(CONTEXT_GLOBALS, val); + break; } + setReg(miscReg, val); } void MiscRegFile::serialize(std::ostream & os) diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh index be143311f..771cb1ed6 100644 --- a/src/arch/sparc/miscregfile.hh +++ b/src/arch/sparc/miscregfile.hh @@ -56,7 +56,6 @@ namespace SparcISA 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, @@ -366,31 +365,13 @@ namespace SparcISA 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, ThreadContext *tc); - - /** 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, + MiscReg readRegWithEffect(int miscReg, ThreadContext *tc); + + void setReg(int miscReg, const MiscReg &val); + + void setRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc); void serialize(std::ostream & os); diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 3323ba7a0..a3b7dde7c 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -66,6 +66,10 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile, // Set pointer for next thread stack. Reserve 8M for main stack. next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + //Initialize these to 0s + fillStart = 0; + spillStart = 0; } void @@ -88,15 +92,19 @@ SparcLiveProcess::startup() */ //No windows contain info from other programs - threadContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0); + threadContexts[0]->setMiscReg(MISCREG_OTHERWIN, 0); //There are no windows to pop - threadContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0); + threadContexts[0]->setMiscReg(MISCREG_CANRESTORE, 0); //All windows are available to save into - threadContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2); + threadContexts[0]->setMiscReg(MISCREG_CANSAVE, NWindows - 2); //All windows are "clean" - threadContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows); + threadContexts[0]->setMiscReg(MISCREG_CLEANWIN, NWindows); //Start with register window 0 - threadContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0); + threadContexts[0]->setMiscReg(MISCREG_CWP, 0); + //Always use spill and fill traps 0 + threadContexts[0]->setMiscReg(MISCREG_WSTATE, 0); + //Set the trap level to 0 + threadContexts[0]->setMiscReg(MISCREG_TL, 0); } m5_auxv_t buildAuxVect(int64_t type, int64_t val) @@ -107,6 +115,83 @@ m5_auxv_t buildAuxVect(int64_t type, int64_t val) return result; } +//We only use 19 instructions for the trap handlers, but there would be +//space for 32 in a real SPARC trap table. +const int numFillInsts = 32; +const int numSpillInsts = 32; + +MachInst fillHandler[numFillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0dba7ff), //ldxa [%sp + BIAS + (0*8)] %asi, %l0 + htog(0xe2dba807), //ldxa [%sp + BIAS + (1*8)] %asi, %l1 + htog(0xe4dba80f), //ldxa [%sp + BIAS + (2*8)] %asi, %l2 + htog(0xe6dba817), //ldxa [%sp + BIAS + (3*8)] %asi, %l3 + htog(0xe8dba81f), //ldxa [%sp + BIAS + (4*8)] %asi, %l4 + htog(0xeadba827), //ldxa [%sp + BIAS + (5*8)] %asi, %l5 + htog(0xecdba82f), //ldxa [%sp + BIAS + (6*8)] %asi, %l6 + htog(0xeedba837), //ldxa [%sp + BIAS + (7*8)] %asi, %l7 + htog(0xf0dba83f), //ldxa [%sp + BIAS + (8*8)] %asi, %i0 + htog(0xf2dba847), //ldxa [%sp + BIAS + (9*8)] %asi, %i1 + htog(0xf4dba84f), //ldxa [%sp + BIAS + (10*8)] %asi, %i2 + htog(0xf6dba857), //ldxa [%sp + BIAS + (11*8)] %asi, %i3 + htog(0xf8dba85f), //ldxa [%sp + BIAS + (12*8)] %asi, %i4 + htog(0xfadba867), //ldxa [%sp + BIAS + (13*8)] %asi, %i5 + htog(0xfcdba86f), //ldxa [%sp + BIAS + (14*8)] %asi, %i6 + htog(0xfedba877), //ldxa [%sp + BIAS + (15*8)] %asi, %i7 + htog(0x83880000), //restored + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + +MachInst spillHandler[numSpillInsts] = +{ + htog(0x87802018), //wr %g0, ASI_AIUP, %asi + htog(0xe0f3a7ff), //stxa %l0, [%sp + BIAS + (0*8)] %asi + htog(0xe2f3a807), //stxa %l1, [%sp + BIAS + (1*8)] %asi + htog(0xe4f3a80f), //stxa %l2, [%sp + BIAS + (2*8)] %asi + htog(0xe6f3a817), //stxa %l3, [%sp + BIAS + (3*8)] %asi + htog(0xe8f3a81f), //stxa %l4, [%sp + BIAS + (4*8)] %asi + htog(0xeaf3a827), //stxa %l5, [%sp + BIAS + (5*8)] %asi + htog(0xecf3a82f), //stxa %l6, [%sp + BIAS + (6*8)] %asi + htog(0xeef3a837), //stxa %l7, [%sp + BIAS + (7*8)] %asi + htog(0xf0f3a83f), //stxa %i0, [%sp + BIAS + (8*8)] %asi + htog(0xf2f3a847), //stxa %i1, [%sp + BIAS + (9*8)] %asi + htog(0xf4f3a84f), //stxa %i2, [%sp + BIAS + (10*8)] %asi + htog(0xf6f3a857), //stxa %i3, [%sp + BIAS + (11*8)] %asi + htog(0xf8f3a85f), //stxa %i4, [%sp + BIAS + (12*8)] %asi + htog(0xfaf3a867), //stxa %i5, [%sp + BIAS + (13*8)] %asi + htog(0xfcf3a86f), //stxa %i6, [%sp + BIAS + (14*8)] %asi + htog(0xfef3a877), //stxa %i7, [%sp + BIAS + (15*8)] %asi + htog(0x81880000), //saved + htog(0x83F00000), //retry + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000), //illtrap + htog(0x00000000) //illtrap +}; + void SparcLiveProcess::argsInit(int intSize, int pageSize) { @@ -317,6 +402,17 @@ SparcLiveProcess::argsInit(int intSize, int pageSize) initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize); + //Stuff the trap handlers into the processes address space. + //Since the stack grows down and is the highest area in the processes + //address space, we can put stuff above it and stay out of the way. + int fillSize = sizeof(MachInst) * numFillInsts; + int spillSize = sizeof(MachInst) * numSpillInsts; + fillStart = stack_base; + spillStart = fillStart + fillSize; + initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler, fillSize); + initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler, spillSize); + + //Set up the thread context to start running the process threadContexts[0]->setIntReg(ArgumentReg0, argc); threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base); threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias); diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 7cc52e241..2320810c7 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -55,6 +55,9 @@ class SparcLiveProcess : public LiveProcess static const Addr StackBias = 2047; + //The locations of the fill and spill handlers + Addr fillStart, spillStart; + std::vector<m5_auxv_t> auxv; SparcLiveProcess(const std::string &nm, ObjectFile *objFile, @@ -71,6 +74,12 @@ class SparcLiveProcess : public LiveProcess void argsInit(int intSize, int pageSize); + Addr readFillStart() + { return fillStart; } + + Addr readSpillStart() + { return spillStart; } + }; #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc index 747426781..5eb874d39 100644 --- a/src/arch/sparc/regfile.cc +++ b/src/arch/sparc/regfile.cc @@ -82,18 +82,21 @@ MiscReg RegFile::readMiscReg(int miscReg) MiscReg RegFile::readMiscRegWithEffect(int miscReg, Fault &fault, ThreadContext *tc) { - return miscRegFile.readRegWithEffect(miscReg, fault, tc); + fault = NoFault; + return miscRegFile.readRegWithEffect(miscReg, tc); } Fault RegFile::setMiscReg(int miscReg, const MiscReg &val) { - return miscRegFile.setReg(miscReg, val); + miscRegFile.setReg(miscReg, val); + return NoFault; } Fault RegFile::setMiscRegWithEffect(int miscReg, const MiscReg &val, ThreadContext * tc) { - return miscRegFile.setRegWithEffect(miscReg, val, tc); + miscRegFile.setRegWithEffect(miscReg, val, tc); + return NoFault; } FloatReg RegFile::readFloatReg(int floatReg, int width) diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 879780d56..177279678 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -69,4 +69,28 @@ sext(uint64_t val) return sign_bit ? (val | ~mask(N)) : val; } +/** + * Return val with bits first to last set to bit_val + */ +template <class T, class B> +inline +T +insertBits(T val, int first, int last, B bit_val) +{ + T bmask = mask(first - last + 1) << last; + return ((bit_val << last) & bmask) | (val & ~bmask); +} + +/** + * A convenience function to replace bits first to last of val with bit_val + * in place. + */ +template <class T, class B> +inline +void +replaceBits(T& val, int first, int last, B bit_val) +{ + val = insertBits(val, first, last, bit_val); +} + #endif // __BASE_BITFIELD_HH__ |