summaryrefslogtreecommitdiff
path: root/src/arch/sparc/isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/sparc/isa')
-rw-r--r--src/arch/sparc/isa/base.isa10
-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
4 files changed, 201 insertions, 20 deletions
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index a4c022411..aa24c75be 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);
}
@@ -241,7 +244,12 @@ output decoder {{
bool passesCondition(uint32_t codes, uint32_t condition)
{
CondCodes condCodes;
- condCodes.bits = codes;
+ condCodes.bits = 0;
+ condCodes.c = codes & 0x1 ? 1 : 0;
+ condCodes.v = codes & 0x2 ? 1 : 0;
+ condCodes.z = codes & 0x4 ? 1 : 0;
+ condCodes.n = codes & 0x8 ? 1 : 0;
+
switch(condition)
{
case Always:
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