Support for twin loads.
src/arch/sparc/isa/decoder.isa: Changed the names of the twin loads to match the 2005 spec. They still use the old format though. src/arch/sparc/isa/formats/mem/blockmem.isa: Added code to generate twin loads src/arch/sparc/isa/formats/mem/util.isa: Added an alignment check for twin loads src/arch/sparc/isa/operands.isa: Comment explaining twin load operands. --HG-- extra : convert_revision : ad42821a97dcda17744875b1e5dc00a9642e59b7
This commit is contained in:
parent
fe73760388
commit
b9d069167c
4 changed files with 165 additions and 4 deletions
|
@ -1030,7 +1030,7 @@ decode OP default Unknown::unknown()
|
||||||
0x00: lduw({{Rd = Mem.uw;}});
|
0x00: lduw({{Rd = Mem.uw;}});
|
||||||
0x01: ldub({{Rd = Mem.ub;}});
|
0x01: ldub({{Rd = Mem.ub;}});
|
||||||
0x02: lduh({{Rd = Mem.uhw;}});
|
0x02: lduh({{Rd = Mem.uhw;}});
|
||||||
0x03: ldd({{
|
0x03: ldtw({{
|
||||||
uint64_t val = Mem.udw;
|
uint64_t val = Mem.udw;
|
||||||
RdLow = val<31:0>;
|
RdLow = val<31:0>;
|
||||||
RdHigh = val<63:32>;
|
RdHigh = val<63:32>;
|
||||||
|
@ -1040,7 +1040,7 @@ decode OP default Unknown::unknown()
|
||||||
0x04: stw({{Mem.uw = Rd.sw;}});
|
0x04: stw({{Mem.uw = Rd.sw;}});
|
||||||
0x05: stb({{Mem.ub = Rd.sb;}});
|
0x05: stb({{Mem.ub = Rd.sb;}});
|
||||||
0x06: sth({{Mem.uhw = Rd.shw;}});
|
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 {
|
format Load {
|
||||||
0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
|
0x08: ldsw({{Rd = (int32_t)Mem.sw;}});
|
||||||
|
@ -1060,7 +1060,7 @@ decode OP default Unknown::unknown()
|
||||||
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
||||||
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
||||||
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
|
0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}});
|
||||||
0x13: ldda({{
|
0x13: ldtwa({{
|
||||||
uint64_t val = Mem.udw;
|
uint64_t val = Mem.udw;
|
||||||
RdLow = val<31:0>;
|
RdLow = val<31:0>;
|
||||||
RdHigh = val<63:32>;
|
RdHigh = val<63:32>;
|
||||||
|
@ -1070,7 +1070,7 @@ decode OP default Unknown::unknown()
|
||||||
0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
|
0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}});
|
||||||
0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
|
0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}});
|
||||||
0x16: stha({{Mem.uhw = 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 {
|
format LoadAlt {
|
||||||
0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
|
0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}});
|
||||||
|
|
|
@ -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 {{
|
output decoder {{
|
||||||
std::string BlockMemMicro::generateDisassembly(Addr pc,
|
std::string BlockMemMicro::generateDisassembly(Addr pc,
|
||||||
const SymbolTable *symtab) const
|
const SymbolTable *symtab) const
|
||||||
|
@ -242,6 +301,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.
|
// Basic instruction class constructor template.
|
||||||
def template BlockMemConstructor {{
|
def template BlockMemConstructor {{
|
||||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
||||||
|
@ -259,6 +351,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 {{
|
def template BlockMemMicroConstructor {{
|
||||||
inline %(class_name)s::
|
inline %(class_name)s::
|
||||||
%(class_name)s_%(micro_pc)s::
|
%(class_name)s_%(micro_pc)s::
|
||||||
|
@ -312,6 +415,47 @@ let {{
|
||||||
asi, opt_flags);
|
asi, opt_flags);
|
||||||
faultCode = ''
|
faultCode = ''
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
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, execute, 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) {{
|
def format BlockLoad(code, asi, *opt_flags) {{
|
||||||
|
@ -337,3 +481,11 @@ def format BlockStore(code, asi, *opt_flags) {{
|
||||||
decode_block) = doBlockMemFormat(code, faultCode,
|
decode_block) = doBlockMemFormat(code, faultCode,
|
||||||
StoreExecute, name, Name, asi, opt_flags)
|
StoreExecute, 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)
|
||||||
|
}};
|
||||||
|
|
|
@ -284,6 +284,12 @@ let {{
|
||||||
else if(EA & 0x3f)
|
else if(EA & 0x3f)
|
||||||
fault = new MemAddressNotAligned;
|
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
|
# 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
|
# are split into ones that are available in priv and hpriv, and
|
||||||
# those that are only available in hpriv
|
# those that are only available in hpriv
|
||||||
|
|
|
@ -57,6 +57,9 @@ def operands {{
|
||||||
# For clarity, descriptions that depend on unsigned behavior should
|
# For clarity, descriptions that depend on unsigned behavior should
|
||||||
# explicitly specify '.uq'.
|
# explicitly specify '.uq'.
|
||||||
'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
|
'Rd': ('IntReg', 'udw', 'RD', 'IsInteger', 1),
|
||||||
|
# For microcoded twin load instructions, RdTwin appears in the "code"
|
||||||
|
# for the instruction and is replaced by RdLow or RdHigh by the format
|
||||||
|
# before it's processed by the iop.
|
||||||
'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2),
|
'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 2),
|
||||||
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
|
'RdHigh': ('IntReg', 'udw', 'RD | 1', 'IsInteger', 3),
|
||||||
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
|
'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4),
|
||||||
|
|
Loading…
Reference in a new issue