summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/sparc/faults.cc48
-rw-r--r--src/arch/sparc/intregfile.cc4
-rw-r--r--src/arch/sparc/isa/base.isa3
-rw-r--r--src/arch/sparc/isa/decoder.isa70
-rw-r--r--src/arch/sparc/isa/formats/priv.isa140
-rw-r--r--src/arch/sparc/isa/operands.isa1
-rw-r--r--src/arch/sparc/isa_traits.hh5
-rw-r--r--src/arch/sparc/tlb.hh7
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;
}
};