summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/sparc/isa/decoder.isa20
-rw-r--r--src/arch/sparc/isa/formats/mem/blockmem.isa210
-rw-r--r--src/arch/sparc/isa/formats/mem/util.isa6
-rw-r--r--src/arch/sparc/isa/operands.isa3
-rw-r--r--src/arch/sparc/system.hh6
5 files changed, 238 insertions, 7 deletions
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index 5c69598d5..e8578291c 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -1009,7 +1009,7 @@ decode OP default Unknown::unknown()
0x00: lduw({{Rd = Mem.uw;}});
0x01: ldub({{Rd = Mem.ub;}});
0x02: lduh({{Rd = Mem.uhw;}});
- 0x03: ldd({{
+ 0x03: ldtw({{
uint64_t val = Mem.udw;
RdLow = val<31:0>;
RdHigh = val<63:32>;
@@ -1019,7 +1019,7 @@ decode OP default Unknown::unknown()
0x04: stw({{Mem.uw = Rd.sw;}});
0x05: stb({{Mem.ub = Rd.sb;}});
0x06: sth({{Mem.uhw = Rd.shw;}});
- 0x07: std({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
+ 0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}});
}
format Load {
0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
@@ -1039,7 +1039,7 @@ decode OP default Unknown::unknown()
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
- 0x13: ldda({{
+ 0x13: ldtwa({{
uint64_t val = Mem.udw;
RdLow = val<31:0>;
RdHigh = val<63:32>;
@@ -1049,7 +1049,7 @@ decode OP default Unknown::unknown()
0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}});
- 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
+ 0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}});
}
format LoadAlt {
0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
@@ -1105,6 +1105,18 @@ decode OP default Unknown::unknown()
0x15: FailUnimpl::lddfa_real_io();
//ASI_REAL_IO_LITTLE
0x1D: FailUnimpl::lddfa_real_io_l();
+ //ASI_LDTX_REAL
+ 0x26: TwinLoad::ldtx_real(
+ {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ //ASI_LDTX_N
+ 0x27: TwinLoad::ldtx_n(
+ {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ //ASI_LDTX_REAL_L
+ 0x2E: TwinLoad::ldtx_real_l(
+ {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
+ //ASI_LDTX_N_L
+ 0x2F: TwinLoad::ldtx_n_l(
+ {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}});
//ASI_PRIMARY
0x80: FailUnimpl::lddfa_p();
//ASI_PRIMARY_LITTLE
diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa
index a0b235a61..25fffc02b 100644
--- a/src/arch/sparc/isa/formats/mem/blockmem.isa
+++ b/src/arch/sparc/isa/formats/mem/blockmem.isa
@@ -91,6 +91,65 @@ output header {{
};
}};
+output header {{
+
+ class TwinMem : public SparcMacroInst
+ {
+ protected:
+
+ // Constructor
+ // We make the assumption that all block memory operations
+ // Will take 8 instructions to execute
+ TwinMem(const char *mnem, ExtMachInst _machInst) :
+ SparcMacroInst(mnem, _machInst, No_OpClass, 8)
+ {}
+ };
+
+ class TwinMemImm : public BlockMem
+ {
+ protected:
+
+ // Constructor
+ TwinMemImm(const char *mnem, ExtMachInst _machInst) :
+ BlockMem(mnem, _machInst)
+ {}
+ };
+
+ class TwinMemMicro : public SparcMicroInst
+ {
+ protected:
+
+ // Constructor
+ TwinMemMicro(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, int8_t _offset) :
+ SparcMicroInst(mnem, _machInst, __opClass),
+ offset(_offset)
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int8_t offset;
+ };
+
+ class TwinMemImmMicro : public BlockMemMicro
+ {
+ protected:
+
+ // Constructor
+ TwinMemImmMicro(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, int8_t _offset) :
+ BlockMemMicro(mnem, _machInst, __opClass, _offset),
+ imm(sext<13>(SIMM13))
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int32_t imm;
+ };
+}};
+
output decoder {{
std::string BlockMemMicro::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
@@ -149,6 +208,64 @@ output decoder {{
}};
+output decoder {{
+ std::string TwinMemMicro::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[0]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[!save ? 0 : 1]);
+ ccprintf(response, " + ");
+ printReg(response, _srcRegIdx[!save ? 1 : 2]);
+ ccprintf(response, " ]");
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+ std::string TwinMemImmMicro::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+ bool load = flags[IsLoad];
+ bool save = flags[IsStore];
+
+ printMnemonic(response, mnemonic);
+ if(save)
+ {
+ printReg(response, _srcRegIdx[1]);
+ ccprintf(response, ", ");
+ }
+ ccprintf(response, "[ ");
+ printReg(response, _srcRegIdx[0]);
+ if(imm >= 0)
+ ccprintf(response, " + 0x%x ]", imm);
+ else
+ ccprintf(response, " + -0x%x ]", -imm);
+ if(load)
+ {
+ ccprintf(response, ", ");
+ printReg(response, _destRegIdx[0]);
+ }
+
+ return response.str();
+ }
+
+}};
+
def template BlockMemDeclare {{
/**
* Static instruction class for a block memory operation
@@ -242,6 +359,39 @@ def template BlockMemDeclare {{
};
}};
+def template TwinMemDeclare {{
+ /**
+ * Static instruction class for a block memory operation
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ //Constructor
+ %(class_name)s(ExtMachInst machInst);
+
+ protected:
+ class %(class_name)s_0 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_0(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ %(InitiateAccDeclare)s
+ %(CompleteAccDeclare)s
+ };
+
+ class %(class_name)s_1 : public %(base_class)sMicro
+ {
+ public:
+ //Constructor
+ %(class_name)s_1(ExtMachInst machInst);
+ %(BasicExecDeclare)s
+ %(InitiateAccDeclare)s
+ %(CompleteAccDeclare)s
+ };
+ };
+}};
+
// Basic instruction class constructor template.
def template BlockMemConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
@@ -259,6 +409,17 @@ def template BlockMemConstructor {{
}
}};
+// Basic instruction class constructor template.
+def template TwinMemConstructor {{
+ inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst)
+ {
+ %(constructor)s;
+ microOps[0] = new %(class_name)s_0(machInst);
+ microOps[1] = new %(class_name)s_1(machInst);
+ }
+}};
+
def template BlockMemMicroConstructor {{
inline %(class_name)s::
%(class_name)s_%(micro_pc)s::
@@ -312,6 +473,47 @@ let {{
asi, opt_flags);
faultCode = ''
return (header_output, decoder_output, exec_output, decode_block)
+
+
+ def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
+ addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
+ addrCalcImm = 'EA = Rs1 + imm + offset;'
+ iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
+ iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
+ header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
+ decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
+ decode_block = ROrImmDecode.subst(iop)
+ matcher = re.compile(r'RdTwin')
+ exec_output = ''
+ for microPc in range(2):
+ flag_code = ''
+ pcedCode = ''
+ if (microPc == 1):
+ flag_code = "flags[IsLastMicroOp] = true;"
+ pcedCode = matcher.sub("RdHigh", code)
+ else:
+ flag_code = "flags[IsDelayedCommit] = true;"
+ pcedCode = matcher.sub("RdLow", code)
+ iop = InstObjParams(name, Name, 'TwinMem', pcedCode,
+ opt_flags, {"ea_code": addrCalcReg,
+ "fault_check": faultCode, "micro_pc": microPc,
+ "set_flags": flag_code})
+ iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode,
+ opt_flags, {"ea_code": addrCalcImm,
+ "fault_check": faultCode, "micro_pc": microPc,
+ "set_flags": flag_code})
+ decoder_output += BlockMemMicroConstructor.subst(iop)
+ decoder_output += BlockMemMicroConstructor.subst(iop_imm)
+ exec_output += doDualSplitExecute(
+ pcedCode, addrCalcReg, addrCalcImm, LoadExecute, faultCode,
+ makeMicroName(name, microPc),
+ makeMicroName(name + "Imm", microPc),
+ makeMicroName(Name, microPc),
+ makeMicroName(Name + "Imm", microPc),
+ asi, opt_flags);
+ faultCode = ''
+ return (header_output, decoder_output, exec_output, decode_block)
+
}};
def format BlockLoad(code, asi, *opt_flags) {{
@@ -337,3 +539,11 @@ def format BlockStore(code, asi, *opt_flags) {{
decode_block) = doBlockMemFormat(code, faultCode,
StoreFuncs, name, Name, asi, opt_flags)
}};
+
+def format TwinLoad(code, asi, *opt_flags) {{
+ faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
+}};
diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa
index 03b08ae18..87a841270 100644
--- a/src/arch/sparc/isa/formats/mem/util.isa
+++ b/src/arch/sparc/isa/formats/mem/util.isa
@@ -295,6 +295,12 @@ let {{
else if(EA & 0x3f)
fault = new MemAddressNotAligned;
'''
+ TwinAlignmentFaultCheck = '''
+ if(RD & 0xe)
+ fault = new IllegalInstruction;
+ else if(EA & 0x1f)
+ fault = new MemAddressNotAligned;
+ '''
# XXX Need to take care of pstate.hpriv as well. The lower ASIs
# are split into ones that are available in priv and hpriv, and
# those that are only available in hpriv
diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa
index 256f2fa43..2d1c3d3b9 100644
--- a/src/arch/sparc/isa/operands.isa
+++ b/src/arch/sparc/isa/operands.isa
@@ -62,6 +62,9 @@ def operands {{
'Rd_prev': ('IntReg', 'udw', 'RD + NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 2),
# The Rd from the next window
'Rd_next': ('IntReg', 'udw', 'RD + 2 * NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 3),
+ # For microcoded twin load instructions, RdTwin appears in the "code"
+ # for the instruction is replaced by RdLow or RdHigh by the format
+ # before it's processed by the iop.
# The low (even) register of a two register pair
'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 4),
# The high (odd) register of a two register pair
diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh
index 5d50ea067..c81b093e8 100644
--- a/src/arch/sparc/system.hh
+++ b/src/arch/sparc/system.hh
@@ -133,21 +133,21 @@ class SparcSystem : public System
/** Add a function-based event to reset binary. */
template <class T>
- T *SparcSystem::addResetFuncEvent(const char *lbl)
+ T *addResetFuncEvent(const char *lbl)
{
return addFuncEvent<T>(resetSymtab, lbl);
}
/** Add a function-based event to the hypervisor. */
template <class T>
- T *SparcSystem::addHypervisorFuncEvent(const char *lbl)
+ T *addHypervisorFuncEvent(const char *lbl)
{
return addFuncEvent<T>(hypervisorSymtab, lbl);
}
/** Add a function-based event to the openboot. */
template <class T>
- T *SparcSystem::addOpenbootFuncEvent(const char *lbl)
+ T *addOpenbootFuncEvent(const char *lbl)
{
return addFuncEvent<T>(openbootSymtab, lbl);
}