ARM: Use fewer micro-ops for register update loads if possible.

Allow some loads that update the base register to use just two micro-ops. three
micro-ops are only used if the destination register matches the offset register
or the PC is the destination regsiter. If the PC is updated it needs to be
the last micro-op otherwise O3 will mispredict.
This commit is contained in:
Gene WU 2010-08-25 19:10:42 -05:00
parent c2d5d2b53d
commit 4d8f4db8d1
10 changed files with 555 additions and 70 deletions

View file

@ -185,7 +185,7 @@ VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
if (wb) { if (wb) {
if (rm != 15 && rm != 13) { if (rm != 15 && rm != 13) {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddUop(machInst, rn, rn, rm); new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
} else { } else {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddiUop(machInst, rn, rn, regs * 8); new MicroAddiUop(machInst, rn, rn, regs * 8);
@ -320,7 +320,7 @@ VldSingleOp::VldSingleOp(const char *mnem, ExtMachInst machInst,
if (wb) { if (wb) {
if (rm != 15 && rm != 13) { if (rm != 15 && rm != 13) {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddUop(machInst, rn, rn, rm); new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
} else { } else {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddiUop(machInst, rn, rn, loadSize); new MicroAddiUop(machInst, rn, rn, loadSize);
@ -566,7 +566,7 @@ VstMultOp::VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
if (wb) { if (wb) {
if (rm != 15 && rm != 13) { if (rm != 15 && rm != 13) {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddUop(machInst, rn, rn, rm); new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
} else { } else {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddiUop(machInst, rn, rn, regs * 8); new MicroAddiUop(machInst, rn, rn, regs * 8);
@ -762,7 +762,7 @@ VstSingleOp::VstSingleOp(const char *mnem, ExtMachInst machInst,
if (wb) { if (wb) {
if (rm != 15 && rm != 13) { if (rm != 15 && rm != 13) {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddUop(machInst, rn, rn, rm); new MicroAddUop(machInst, rn, rn, rm, 0, ArmISA::LSL);
} else { } else {
microOps[uopIdx++] = microOps[uopIdx++] =
new MicroAddiUop(machInst, rn, rn, storeSize); new MicroAddiUop(machInst, rn, rn, storeSize);
@ -877,6 +877,17 @@ MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
return ss.str(); return ss.str();
} }
std::string
MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
printMnemonic(ss);
printReg(ss, ura);
ss << ", ";
printReg(ss, urb);
return ss.str();
}
std::string std::string
MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const MicroIntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{ {

View file

@ -128,6 +128,23 @@ class MicroNeonMixLaneOp : public MicroNeonMixOp
{ {
} }
}; };
/**
* Microops of the form IntRegA = IntRegB
*/
class MicroIntMov : public MicroOp
{
protected:
RegIndex ura, urb;
MicroIntMov(const char *mnem, ExtMachInst machInst, OpClass __opClass,
RegIndex _ura, RegIndex _urb)
: MicroOp(mnem, machInst, __opClass),
ura(_ura), urb(_urb)
{
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/** /**
* Microops of the form IntRegA = IntRegB op Imm * Microops of the form IntRegA = IntRegB op Imm
@ -136,10 +153,10 @@ class MicroIntImmOp : public MicroOp
{ {
protected: protected:
RegIndex ura, urb; RegIndex ura, urb;
uint8_t imm; uint32_t imm;
MicroIntImmOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, MicroIntImmOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
RegIndex _ura, RegIndex _urb, uint8_t _imm) RegIndex _ura, RegIndex _urb, uint32_t _imm)
: MicroOp(mnem, machInst, __opClass), : MicroOp(mnem, machInst, __opClass),
ura(_ura), urb(_urb), imm(_imm) ura(_ura), urb(_urb), imm(_imm)
{ {
@ -166,6 +183,26 @@ class MicroIntOp : public MicroOp
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
}; };
/**
* Microops of the form IntRegA = IntRegB op shifted IntRegC
*/
class MicroIntRegOp : public MicroOp
{
protected:
RegIndex ura, urb, urc;
int32_t shiftAmt;
ArmShiftType shiftType;
MicroIntRegOp(const char *mnem, ExtMachInst machInst, OpClass __opClass,
RegIndex _ura, RegIndex _urb, RegIndex _urc,
int32_t _shiftAmt, ArmShiftType _shiftType)
: MicroOp(mnem, machInst, __opClass),
ura(_ura), urb(_urb), urc(_urc),
shiftAmt(_shiftAmt), shiftType(_shiftType)
{
}
};
/** /**
* Memory microops which use IntReg + Imm addressing * Memory microops which use IntReg + Imm addressing
*/ */

View file

@ -77,13 +77,29 @@ class RfeOp : public PredOp
IntRegIndex base; IntRegIndex base;
AddrMode mode; AddrMode mode;
bool wb; bool wb;
static const unsigned numMicroops = 2;
StaticInstPtr *uops;
RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _base, AddrMode _mode, bool _wb) IntRegIndex _base, AddrMode _mode, bool _wb)
: PredOp(mnem, _machInst, __opClass), : PredOp(mnem, _machInst, __opClass),
base(_base), mode(_mode), wb(_wb) base(_base), mode(_mode), wb(_wb), uops(NULL)
{} {}
virtual
~RfeOp()
{
delete uops;
}
StaticInstPtr
fetchMicroop(MicroPC microPC)
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
}; };
@ -101,13 +117,29 @@ class SrsOp : public PredOp
uint32_t regMode; uint32_t regMode;
AddrMode mode; AddrMode mode;
bool wb; bool wb;
static const unsigned numMicroops = 2;
StaticInstPtr *uops;
SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass, SrsOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
uint32_t _regMode, AddrMode _mode, bool _wb) uint32_t _regMode, AddrMode _mode, bool _wb)
: PredOp(mnem, _machInst, __opClass), : PredOp(mnem, _machInst, __opClass),
regMode(_regMode), mode(_mode), wb(_wb) regMode(_regMode), mode(_mode), wb(_wb), uops(NULL)
{} {}
virtual
~SrsOp()
{
delete uops;
}
StaticInstPtr
fetchMicroop(MicroPC microPC)
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
}
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
}; };
@ -125,13 +157,29 @@ class Memory : public PredOp
IntRegIndex dest; IntRegIndex dest;
IntRegIndex base; IntRegIndex base;
bool add; bool add;
static const unsigned numMicroops = 3;
StaticInstPtr *uops;
Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass, Memory(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _base, bool _add) IntRegIndex _dest, IntRegIndex _base, bool _add)
: PredOp(mnem, _machInst, __opClass), : PredOp(mnem, _machInst, __opClass),
dest(_dest), base(_base), add(_add) dest(_dest), base(_base), add(_add), uops(NULL)
{} {}
virtual
~Memory()
{
delete [] uops;
}
StaticInstPtr
fetchMicroop(MicroPC microPC)
{
assert(uops != NULL && microPC < numMicroops);
return uops[microPC];
}
virtual void virtual void
printOffset(std::ostream &os) const printOffset(std::ostream &os) const
{} {}

View file

@ -67,7 +67,7 @@ let {{
self.memFlags = ["ArmISA::TLB::MustBeOne"] self.memFlags = ["ArmISA::TLB::MustBeOne"]
self.codeBlobs = {"postacc_code" : ""} self.codeBlobs = {"postacc_code" : ""}
def emitHelper(self, base = 'Memory'): def emitHelper(self, base = 'Memory', wbDecl = None):
global header_output, decoder_output, exec_output global header_output, decoder_output, exec_output
@ -76,7 +76,7 @@ let {{
(newHeader, (newHeader,
newDecoder, newDecoder,
newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
self.memFlags, [], base) self.memFlags, [], base, wbDecl)
header_output += newHeader header_output += newHeader
decoder_output += newDecoder decoder_output += newDecoder
@ -113,22 +113,36 @@ let {{
Cpsr = ~CondCodesMask & newCpsr; Cpsr = ~CondCodesMask & newCpsr;
CondCodes = CondCodesMask & newCpsr; CondCodes = CondCodesMask & newCpsr;
''' '''
if self.writeback:
accCode += "Base = Base + %s;\n" % wbDiff
self.codeBlobs["memacc_code"] = accCode self.codeBlobs["memacc_code"] = accCode
self.emitHelper('RfeOp') wbDecl = None
if self.writeback:
wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
self.emitHelper('RfeOp', wbDecl)
class LoadImmInst(LoadInst): class LoadImmInst(LoadInst):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
super(LoadImmInst, self).__init__(*args, **kargs) super(LoadImmInst, self).__init__(*args, **kargs)
self.offset = self.op + " imm" self.offset = self.op + " imm"
if self.add:
self.wbDecl = "MicroAddiUop(machInst, base, base, imm);"
else:
self.wbDecl = "MicroSubiUop(machInst, base, base, imm);"
class LoadRegInst(LoadInst): class LoadRegInst(LoadInst):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
super(LoadRegInst, self).__init__(*args, **kargs) super(LoadRegInst, self).__init__(*args, **kargs)
self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \
" shiftType, CondCodes<29:>)" " shiftType, CondCodes<29:>)"
if self.add:
self.wbDecl = '''
MicroAddUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
'''
else:
self.wbDecl = '''
MicroSubUop(machInst, base, base, wbIndexReg, shiftAmt, shiftType);
'''
class LoadSingle(LoadInst): class LoadSingle(LoadInst):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
@ -175,20 +189,20 @@ let {{
accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);" accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
accCode = accCode % buildMemSuffix(self.sign, self.size) accCode = accCode % buildMemSuffix(self.sign, self.size)
if self.writeback:
accCode += "Base = Base %s;\n" % self.offset
self.codeBlobs["memacc_code"] = accCode self.codeBlobs["memacc_code"] = accCode
# Push it out to the output files # Push it out to the output files
base = buildMemBase(self.basePrefix, self.post, self.writeback) base = buildMemBase(self.basePrefix, self.post, self.writeback)
self.emitHelper(base) wbDecl = None
if self.writeback:
wbDecl = self.wbDecl
self.emitHelper(base, wbDecl)
def loadImmClassName(post, add, writeback, size=4, sign=False, user=False): def loadImmClassName(post, add, writeback, size=4, sign=False, user=False):
return memClassName("LOAD_IMM", post, add, writeback, size, sign, user) return memClassName("LOAD_IMM", post, add, writeback, size, sign, user)
class LoadImm(LoadImmInst, LoadSingle): class LoadImm(LoadImmInst, LoadSingle):
decConstBase = 'LoadStoreImm' decConstBase = 'LoadImm'
basePrefix = 'MemoryImm' basePrefix = 'MemoryImm'
nameFunc = staticmethod(loadImmClassName) nameFunc = staticmethod(loadImmClassName)
@ -196,7 +210,7 @@ let {{
return memClassName("LOAD_REG", post, add, writeback, size, sign, user) return memClassName("LOAD_REG", post, add, writeback, size, sign, user)
class LoadReg(LoadRegInst, LoadSingle): class LoadReg(LoadRegInst, LoadSingle):
decConstBase = 'LoadStoreReg' decConstBase = 'LoadReg'
basePrefix = 'MemoryReg' basePrefix = 'MemoryReg'
nameFunc = staticmethod(loadRegClassName) nameFunc = staticmethod(loadRegClassName)
@ -244,14 +258,14 @@ let {{
FpDest2.uw = (uint32_t)(swappedMem >> 32); FpDest2.uw = (uint32_t)(swappedMem >> 32);
''' '''
if self.writeback:
accCode += "Base = Base %s;\n" % self.offset
self.codeBlobs["memacc_code"] = accCode self.codeBlobs["memacc_code"] = accCode
# Push it out to the output files # Push it out to the output files
base = buildMemBase(self.basePrefix, self.post, self.writeback) base = buildMemBase(self.basePrefix, self.post, self.writeback)
self.emitHelper(base) wbDecl = None
if self.writeback:
wbDecl = self.wbDecl
self.emitHelper(base, wbDecl)
def loadDoubleImmClassName(post, add, writeback): def loadDoubleImmClassName(post, add, writeback):
return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False) return memClassName("LOAD_IMMD", post, add, writeback, 4, False, False)
@ -265,7 +279,7 @@ let {{
return memClassName("LOAD_REGD", post, add, writeback, 4, False, False) return memClassName("LOAD_REGD", post, add, writeback, 4, False, False)
class LoadDoubleReg(LoadRegInst, LoadDouble): class LoadDoubleReg(LoadRegInst, LoadDouble):
decConstBase = 'LoadStoreDReg' decConstBase = 'LoadDReg'
basePrefix = 'MemoryDReg' basePrefix = 'MemoryDReg'
nameFunc = staticmethod(loadDoubleRegClassName) nameFunc = staticmethod(loadDoubleRegClassName)

View file

@ -575,8 +575,12 @@ let {{
['IsMicroop']) ['IsMicroop'])
microAddUopIop = InstObjParams('add_uop', 'MicroAddUop', microAddUopIop = InstObjParams('add_uop', 'MicroAddUop',
'MicroIntOp', 'MicroIntRegOp',
{'code': 'Ra = Rb + Rc;', {'code':
'''Ra = Rb + shift_rm_imm(Rc, shiftAmt,
shiftType,
CondCodes<29:>);
''',
'predicate_test': predicateTest}, 'predicate_test': predicateTest},
['IsMicroop']) ['IsMicroop'])
@ -586,15 +590,39 @@ let {{
'predicate_test': predicateTest}, 'predicate_test': predicateTest},
['IsMicroop']) ['IsMicroop'])
microSubUopIop = InstObjParams('sub_uop', 'MicroSubUop',
'MicroIntRegOp',
{'code':
'''Ra = Rb - shift_rm_imm(Rc, shiftAmt,
shiftType,
CondCodes<29:>);
''',
'predicate_test': predicateTest},
['IsMicroop'])
microUopRegMovIop = InstObjParams('uopReg_uop', 'MicroUopRegMov',
'MicroIntMov',
{'code': 'IWRa = Rb;',
'predicate_test': predicateTest},
['IsMicroop'])
header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
MicroIntImmDeclare.subst(microSubiUopIop) + \ MicroIntImmDeclare.subst(microSubiUopIop) + \
MicroIntDeclare.subst(microAddUopIop) MicroIntRegDeclare.subst(microAddUopIop) + \
MicroIntRegDeclare.subst(microSubUopIop) + \
MicroIntMovDeclare.subst(microUopRegMovIop)
decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
MicroIntImmConstructor.subst(microSubiUopIop) + \ MicroIntImmConstructor.subst(microSubiUopIop) + \
MicroIntConstructor.subst(microAddUopIop) MicroIntRegConstructor.subst(microAddUopIop) + \
MicroIntRegConstructor.subst(microSubUopIop) + \
MicroIntMovConstructor.subst(microUopRegMovIop)
exec_output = PredOpExecute.subst(microAddiUopIop) + \ exec_output = PredOpExecute.subst(microAddiUopIop) + \
PredOpExecute.subst(microSubiUopIop) + \ PredOpExecute.subst(microSubiUopIop) + \
PredOpExecute.subst(microAddUopIop) PredOpExecute.subst(microAddUopIop) + \
PredOpExecute.subst(microSubUopIop) + \
PredOpExecute.subst(microUopRegMovIop)
}}; }};
let {{ let {{

View file

@ -48,7 +48,7 @@ let {{
self.constructTemplate = eval(self.decConstBase + 'Constructor') self.constructTemplate = eval(self.decConstBase + 'Constructor')
def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags, def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags,
base = 'Memory'): base = 'Memory', wbDecl = None):
# Make sure flags are in lists (convert to lists if not). # Make sure flags are in lists (convert to lists if not).
memFlags = makeList(memFlags) memFlags = makeList(memFlags)
instFlags = makeList(instFlags) instFlags = makeList(instFlags)
@ -62,14 +62,38 @@ let {{
codeBlobs["ea_code"] = eaCode codeBlobs["ea_code"] = eaCode
iop = InstObjParams(name, Name, base, codeBlobs, instFlags) macroName = Name
instFlagsCopy = list(instFlags)
codeBlobsCopy = dict(codeBlobs)
if wbDecl is not None:
instFlagsCopy.append('IsMicroop')
Name = Name + 'Acc'
codeBlobsCopy['acc_name'] = Name
codeBlobsCopy['wb_decl'] = wbDecl
codeBlobsCopy['use_uops'] = 0
# (header_output, decoder_output, decode_block, exec_output) iop = InstObjParams(name, Name, base,
return (self.declareTemplate.subst(iop), codeBlobsCopy, instFlagsCopy)
self.constructTemplate.subst(iop),
self.fullExecTemplate.subst(iop) header_output = self.declareTemplate.subst(iop)
+ self.initiateAccTemplate.subst(iop) decoder_output = self.constructTemplate.subst(iop)
+ self.completeAccTemplate.subst(iop)) exec_output = self.fullExecTemplate.subst(iop) + \
self.initiateAccTemplate.subst(iop) + \
self.completeAccTemplate.subst(iop)
if wbDecl is not None:
iop = InstObjParams(name, macroName, base,
{ "wb_decl" : wbDecl,
"acc_name" : Name,
"use_uops" : 1 },
['IsMacroop'])
header_output += self.declareTemplate.subst(iop)
decoder_output += self.constructTemplate.subst(iop)
exec_output += PanicExecute.subst(iop) + \
PanicInitiateAcc.subst(iop) + \
PanicCompleteAcc.subst(iop)
return (header_output, decoder_output, exec_output)
def pickPredicate(blobs): def pickPredicate(blobs):
for val in blobs.values(): for val in blobs.values():

View file

@ -67,7 +67,7 @@ let {{
self.memFlags = ["ArmISA::TLB::MustBeOne"] self.memFlags = ["ArmISA::TLB::MustBeOne"]
self.codeBlobs = { "postacc_code" : "" } self.codeBlobs = { "postacc_code" : "" }
def emitHelper(self, base = 'Memory'): def emitHelper(self, base = 'Memory', wbDecl = None):
global header_output, decoder_output, exec_output global header_output, decoder_output, exec_output
@ -76,7 +76,7 @@ let {{
(newHeader, (newHeader,
newDecoder, newDecoder,
newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
self.memFlags, [], base) self.memFlags, [], base, wbDecl)
header_output += newHeader header_output += newHeader
decoder_output += newDecoder decoder_output += newDecoder
@ -137,11 +137,24 @@ let {{
super(StoreImmInst, self).__init__(*args, **kargs) super(StoreImmInst, self).__init__(*args, **kargs)
self.offset = self.op + " imm" self.offset = self.op + " imm"
if self.add:
self.wbDecl = "MicroAddiUop(machInst, base, base, imm);"
else:
self.wbDecl = "MicroSubiUop(machInst, base, base, imm);"
class StoreRegInst(StoreInst): class StoreRegInst(StoreInst):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
super(StoreRegInst, self).__init__(*args, **kargs) super(StoreRegInst, self).__init__(*args, **kargs)
self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \ self.offset = self.op + " shift_rm_imm(Index, shiftAmt," + \
" shiftType, CondCodes<29:>)" " shiftType, CondCodes<29:>)"
if self.add:
self.wbDecl = '''
MicroAddUop(machInst, base, base, index, shiftAmt, shiftType);
'''
else:
self.wbDecl = '''
MicroSubUop(machInst, base, base, index, shiftAmt, shiftType);
'''
class StoreSingle(StoreInst): class StoreSingle(StoreInst):
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
@ -186,14 +199,14 @@ let {{
accCode = accCode % \ accCode = accCode % \
{ "suffix" : buildMemSuffix(self.sign, self.size) } { "suffix" : buildMemSuffix(self.sign, self.size) }
if self.writeback:
accCode += "Base = Base %s;\n" % self.offset
self.codeBlobs["memacc_code"] = accCode self.codeBlobs["memacc_code"] = accCode
# Push it out to the output files # Push it out to the output files
base = buildMemBase(self.basePrefix, self.post, self.writeback) base = buildMemBase(self.basePrefix, self.post, self.writeback)
self.emitHelper(base) wbDecl = None
if self.writeback:
wbDecl = self.wbDecl
self.emitHelper(base, wbDecl)
def storeImmClassName(post, add, writeback, size=4, sign=False, user=False): def storeImmClassName(post, add, writeback, size=4, sign=False, user=False):
return memClassName("STORE_IMM", post, add, writeback, size, sign, user) return memClassName("STORE_IMM", post, add, writeback, size, sign, user)
@ -217,7 +230,7 @@ let {{
return memClassName("STORE_REG", post, add, writeback, size, sign, user) return memClassName("STORE_REG", post, add, writeback, size, sign, user)
class StoreReg(StoreRegInst, StoreSingle): class StoreReg(StoreRegInst, StoreSingle):
decConstBase = 'LoadStoreReg' decConstBase = 'StoreReg'
basePrefix = 'MemoryReg' basePrefix = 'MemoryReg'
nameFunc = staticmethod(storeRegClassName) nameFunc = staticmethod(storeRegClassName)
@ -265,14 +278,14 @@ let {{
((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32); ((uint64_t)cSwap(Dest2.uw, cpsr.e) << 32);
''' '''
if self.writeback:
accCode += "Base = Base %s;\n" % self.offset
self.codeBlobs["memacc_code"] = accCode self.codeBlobs["memacc_code"] = accCode
# Push it out to the output files # Push it out to the output files
base = buildMemBase(self.basePrefix, self.post, self.writeback) base = buildMemBase(self.basePrefix, self.post, self.writeback)
self.emitHelper(base) wbDecl = None
if self.writeback:
wbDecl = self.wbDecl
self.emitHelper(base, wbDecl)
def storeDoubleImmClassName(post, add, writeback): def storeDoubleImmClassName(post, add, writeback):
return memClassName("STORE_IMMD", post, add, writeback, 4, False, False) return memClassName("STORE_IMMD", post, add, writeback, 4, False, False)
@ -296,7 +309,7 @@ let {{
return memClassName("STORE_REGD", post, add, writeback, 4, False, False) return memClassName("STORE_REGD", post, add, writeback, 4, False, False)
class StoreDoubleReg(StoreRegInst, StoreDouble): class StoreDoubleReg(StoreRegInst, StoreDouble):
decConstBase = 'LoadStoreDReg' decConstBase = 'StoreDReg'
basePrefix = 'MemoryDReg' basePrefix = 'MemoryDReg'
nameFunc = staticmethod(storeDoubleRegClassName) nameFunc = staticmethod(storeDoubleRegClassName)

View file

@ -214,6 +214,31 @@ def template MicroNeonMixLaneDeclare {{
}; };
}}; }};
////////////////////////////////////////////////////////////////////
//
// Integer = Integer
//
def template MicroIntMovDeclare {{
class %(class_name)s : public %(base_class)s
{
public:
%(class_name)s(ExtMachInst machInst,
RegIndex _ura, RegIndex _urb);
%(BasicExecDeclare)s
};
}};
def template MicroIntMovConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
RegIndex _ura,
RegIndex _urb)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_ura, _urb)
{
%(constructor)s;
}
}};
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// //
// Integer = Integer op Immediate microops // Integer = Integer op Immediate microops
@ -225,7 +250,7 @@ def template MicroIntImmDeclare {{
public: public:
%(class_name)s(ExtMachInst machInst, %(class_name)s(ExtMachInst machInst,
RegIndex _ura, RegIndex _urb, RegIndex _ura, RegIndex _urb,
uint8_t _imm); int32_t _imm);
%(BasicExecDeclare)s %(BasicExecDeclare)s
}; };
}}; }};
@ -234,7 +259,7 @@ def template MicroIntImmConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst, %(class_name)s::%(class_name)s(ExtMachInst machInst,
RegIndex _ura, RegIndex _ura,
RegIndex _urb, RegIndex _urb,
uint8_t _imm) int32_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_ura, _urb, _imm) _ura, _urb, _imm)
{ {
@ -242,6 +267,28 @@ def template MicroIntImmConstructor {{
} }
}}; }};
def template MicroIntRegDeclare {{
class %(class_name)s : public %(base_class)s
{
public:
%(class_name)s(ExtMachInst machInst,
RegIndex _ura, RegIndex _urb, RegIndex _urc,
int32_t _shiftAmt, ArmShiftType _shiftType);
%(BasicExecDeclare)s
};
}};
def template MicroIntRegConstructor {{
%(class_name)s::%(class_name)s(ExtMachInst machInst,
RegIndex _ura, RegIndex _urb, RegIndex _urc,
int32_t _shiftAmt, ArmShiftType _shiftType)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
_ura, _urb, _urc, _shiftAmt, _shiftType)
{
%(constructor)s;
}
}};
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// //
// Macro Memory-format instructions // Macro Memory-format instructions

View file

@ -41,6 +41,35 @@
// Authors: Stephen Hines // Authors: Stephen Hines
def template PanicExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
panic("Execute function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template PanicInitiateAcc {{
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
panic("InitiateAcc function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template PanicCompleteAcc {{
Fault %(class_name)s::completeAcc(PacketPtr pkt,
%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
panic("CompleteAcc function executed when it shouldn't be!\n");
return NoFault;
}
}};
def template SwapExecute {{ def template SwapExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const Trace::InstRecord *traceData) const
@ -73,7 +102,8 @@ def template SwapExecute {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -109,7 +139,8 @@ def template SwapInitiateAcc {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -172,7 +203,8 @@ def template LoadExecute {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -208,7 +240,8 @@ def template NeonLoadExecute {{
} }
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -245,7 +278,8 @@ def template StoreExecute {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -285,7 +319,8 @@ def template NeonStoreExecute {{
} }
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -328,7 +363,8 @@ def template StoreExExecute {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -365,8 +401,8 @@ def template StoreExInitiateAcc {{
} else { } else {
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0 &&
if (fault == NoFault && machInst.itstateMask != 0) { (!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -404,7 +440,8 @@ def template StoreInitiateAcc {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -443,7 +480,8 @@ def template NeonStoreInitiateAcc {{
} }
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -469,7 +507,8 @@ def template LoadInitiateAcc {{
} }
} else { } else {
xc->setPredicate(false); xc->setPredicate(false);
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
} }
@ -495,7 +534,8 @@ def template NeonLoadInitiateAcc {{
if (fault == NoFault) { if (fault == NoFault) {
fault = xc->readBytes(EA, NULL, %(size)d, memAccessFlags); fault = xc->readBytes(EA, NULL, %(size)d, memAccessFlags);
} }
} else if (fault == NoFault && machInst.itstateMask != 0) { } else if (fault == NoFault && machInst.itstateMask != 0 &&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }
@ -791,7 +831,7 @@ def template StoreExImmDeclare {{
}; };
}}; }};
def template LoadStoreDRegDeclare {{ def template StoreDRegDeclare {{
/** /**
* Static instruction class for "%(mnemonic)s". * Static instruction class for "%(mnemonic)s".
*/ */
@ -814,7 +854,7 @@ def template LoadStoreDRegDeclare {{
}; };
}}; }};
def template LoadStoreRegDeclare {{ def template StoreRegDeclare {{
/** /**
* Static instruction class for "%(mnemonic)s". * Static instruction class for "%(mnemonic)s".
*/ */
@ -836,6 +876,71 @@ def template LoadStoreRegDeclare {{
}; };
}}; }};
def template LoadDRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2,
uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
};
}};
def template LoadRegDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType,
uint32_t _index);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
};
}};
def template LoadImmDeclare {{
/**
* Static instruction class for "%(mnemonic)s".
*/
class %(class_name)s : public %(base_class)s
{
public:
/// Constructor.
%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm);
%(BasicExecDeclare)s
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
};
}};
def template InitiateAccDeclare {{ def template InitiateAccDeclare {{
Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}}; }};
@ -851,6 +956,13 @@ def template RfeConstructor {{
(IntRegIndex)_base, (AddrMode)_mode, _wb) (IntRegIndex)_base, (AddrMode)_mode, _wb)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _base, _mode, _wb);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
@ -861,6 +973,13 @@ def template SrsConstructor {{
(OperatingMode)_regMode, (AddrMode)_mode, _wb) (OperatingMode)_regMode, (AddrMode)_mode, _wb)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _regMode, _mode, _wb);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
@ -883,6 +1002,13 @@ def template LoadStoreDImmConstructor {{
(IntRegIndex)_base, _add, _imm) (IntRegIndex)_base, _add, _imm)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add, _imm);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
@ -896,6 +1022,14 @@ def template StoreExDImmConstructor {{
(IntRegIndex)_base, _add, _imm) (IntRegIndex)_base, _add, _imm)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _result, _dest, _dest2,
_base, _add, _imm);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
@ -906,6 +1040,13 @@ def template LoadStoreImmConstructor {{
(IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm) (IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
@ -918,10 +1059,18 @@ def template StoreExImmConstructor {{
(IntRegIndex)_base, _add, _imm) (IntRegIndex)_base, _add, _imm)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _result, _dest,
_base, _add, _imm);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
def template LoadStoreDRegConstructor {{ def template StoreDRegConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst, inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add, uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
@ -932,10 +1081,18 @@ def template LoadStoreDRegConstructor {{
(IntRegIndex)_index) (IntRegIndex)_index)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
def template LoadStoreRegConstructor {{ def template StoreRegConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst, inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index) int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
@ -945,5 +1102,110 @@ def template LoadStoreRegConstructor {{
(IntRegIndex)_index) (IntRegIndex)_index)
{ {
%(constructor)s; %(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
#endif
} }
}}; }};
def template LoadDRegConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _dest2, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(IntRegIndex)_dest, (IntRegIndex)_dest2,
(IntRegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(IntRegIndex)_index)
{
%(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if ((_dest == _index) || (_dest2 == _index)) {
IntRegIndex wbIndexReg = INTREG_UREG0;
uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
uops[1] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[2] = new %(wb_decl)s;
uops[2]->setLastMicroop();
} else {
IntRegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, _dest, _dest2, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#endif
}
}};
def template LoadRegConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add,
int32_t _shiftAmt, uint32_t _shiftType, uint32_t _index)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(IntRegIndex)_dest, (IntRegIndex)_base, _add,
_shiftAmt, (ArmShiftType)_shiftType,
(IntRegIndex)_index)
{
%(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if (_dest == INTREG_PC) {
IntRegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1] = new %(wb_decl)s;
uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
uops[2]->setLastMicroop();
} else if(_dest == _index) {
IntRegIndex wbIndexReg = INTREG_UREG0;
uops[0] = new MicroUopRegMov(machInst, INTREG_UREG0, _index);
uops[1] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[2] = new %(wb_decl)s;
uops[2]->setLastMicroop();
} else {
IntRegIndex wbIndexReg = index;
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add,
_shiftAmt, _shiftType, _index);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#endif
}
}};
def template LoadImmConstructor {{
inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
uint32_t _dest, uint32_t _base, bool _add, int32_t _imm)
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
(IntRegIndex)_dest, (IntRegIndex)_base, _add, _imm)
{
%(constructor)s;
#if %(use_uops)d
assert(numMicroops >= 2);
uops = new StaticInstPtr[numMicroops];
if (_dest == INTREG_PC) {
uops[0] = new %(acc_name)s(machInst, INTREG_UREG0, _base, _add,
_imm);
uops[1] = new %(wb_decl)s;
uops[2] = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG0);
uops[2]->setLastMicroop();
} else {
uops[0] = new %(acc_name)s(machInst, _dest, _base, _add, _imm);
uops[1] = new %(wb_decl)s;
uops[1]->setLastMicroop();
}
#endif
}
}};

View file

@ -146,7 +146,8 @@ def template PredOpExecute {{
xc->setPredicate(false); xc->setPredicate(false);
} }
if (fault == NoFault && machInst.itstateMask != 0) { if (fault == NoFault && machInst.itstateMask != 0&&
(!isMicroop() || isLastMicroop())) {
xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate); xc->setMiscReg(MISCREG_ITSTATE, machInst.newItstate);
} }