ARM: Fix RFE macrop.
This changes the RFE macroop into 3 microops: URa = [sp]; URb = [sp+4]; // load CPSR,PC values from stack sp = sp + offset; // optionally auto-increment PC = URa; CPSR = URb; // write to the PC and CPSR. Importantly: - writing to PC is handled in the last micro-op. - loading occurs prior to state changes.
This commit is contained in:
parent
e65f480d62
commit
031f396c71
9 changed files with 146 additions and 34 deletions
|
@ -895,6 +895,15 @@ MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
MicroSetPCCPSR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
printMnemonic(ss);
|
||||
ss << "[PC,CPSR]";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
MicroIntMov::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
|
|
|
@ -134,6 +134,27 @@ class MicroNeonMixLaneOp : public MicroNeonMixOp
|
|||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Microops of the form
|
||||
* PC = IntRegA
|
||||
* CPSR = IntRegB
|
||||
*/
|
||||
class MicroSetPCCPSR : public MicroOp
|
||||
{
|
||||
protected:
|
||||
IntRegIndex ura, urb, urc;
|
||||
|
||||
MicroSetPCCPSR(const char *mnem, ExtMachInst machInst, OpClass __opClass,
|
||||
IntRegIndex _ura, IntRegIndex _urb, IntRegIndex _urc)
|
||||
: MicroOp(mnem, machInst, __opClass),
|
||||
ura(_ura), urb(_urb), urc(_urc)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Microops of the form IntRegA = IntRegB
|
||||
*/
|
||||
|
|
|
@ -97,14 +97,18 @@ class RfeOp : public MightBeMicro
|
|||
IntRegIndex base;
|
||||
AddrMode mode;
|
||||
bool wb;
|
||||
static const unsigned numMicroops = 2;
|
||||
IntRegIndex ura, urb, urc;
|
||||
static const unsigned numMicroops = 3;
|
||||
|
||||
StaticInstPtr *uops;
|
||||
|
||||
RfeOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
|
||||
IntRegIndex _base, AddrMode _mode, bool _wb)
|
||||
: MightBeMicro(mnem, _machInst, __opClass),
|
||||
base(_base), mode(_mode), wb(_wb), uops(NULL)
|
||||
base(_base), mode(_mode), wb(_wb),
|
||||
ura(INTREG_UREG0), urb(INTREG_UREG1),
|
||||
urc(INTREG_UREG2),
|
||||
uops(NULL)
|
||||
{}
|
||||
|
||||
virtual
|
||||
|
|
|
@ -110,6 +110,8 @@ enum IntRegIndex
|
|||
|
||||
INTREG_ZERO, // Dummy zero reg since there has to be one.
|
||||
INTREG_UREG0,
|
||||
INTREG_UREG1,
|
||||
INTREG_UREG2,
|
||||
INTREG_CONDCODES,
|
||||
INTREG_FPCONDCODES,
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ let {{
|
|||
self.memFlags = ["ArmISA::TLB::MustBeOne"]
|
||||
self.codeBlobs = {"postacc_code" : ""}
|
||||
|
||||
def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = []):
|
||||
def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None):
|
||||
|
||||
global header_output, decoder_output, exec_output
|
||||
|
||||
|
@ -76,7 +76,8 @@ let {{
|
|||
(newHeader,
|
||||
newDecoder,
|
||||
newExec) = self.fillTemplates(self.name, self.Name, codeBlobs,
|
||||
self.memFlags, instFlags, base, wbDecl)
|
||||
self.memFlags, instFlags, base,
|
||||
wbDecl, pcDecl)
|
||||
|
||||
header_output += newHeader
|
||||
decoder_output += newDecoder
|
||||
|
@ -104,26 +105,18 @@ let {{
|
|||
wbDiff = 8
|
||||
accCode = '''
|
||||
CPSR cpsr = Cpsr;
|
||||
SCTLR sctlr = Sctlr;
|
||||
// Use the version of NPC that gets set before NextThumb
|
||||
pNPC = cSwap<uint32_t>(Mem.ud, cpsr.e);
|
||||
uint32_t tempSpsr = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(cpsr | CondCodes, tempSpsr,
|
||||
0xF, true, sctlr.nmfi);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
NextThumb = ((CPSR)newCpsr).t;
|
||||
NextJazelle = ((CPSR)newCpsr).j;
|
||||
ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC)
|
||||
| (((CPSR)tempSpsr).it1 & 0x3);
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
URc = cpsr | CondCodes;
|
||||
URa = cSwap<uint32_t>(Mem.ud, cpsr.e);
|
||||
URb = cSwap<uint32_t>(Mem.ud >> 32, cpsr.e);
|
||||
'''
|
||||
self.codeBlobs["memacc_code"] = accCode
|
||||
|
||||
wbDecl = None
|
||||
pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);"
|
||||
|
||||
if self.writeback:
|
||||
wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff
|
||||
self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"])
|
||||
self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl)
|
||||
|
||||
class LoadImmInst(LoadInst):
|
||||
def __init__(self, *args, **kargs):
|
||||
|
|
|
@ -608,23 +608,48 @@ let {{
|
|||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
setPCCPSRDecl = '''
|
||||
CPSR cpsrOrCondCodes = URc;
|
||||
SCTLR sctlr = Sctlr;
|
||||
pNPC = URa;
|
||||
uint32_t newCpsr =
|
||||
cpsrWriteByInstr(cpsrOrCondCodes, URb,
|
||||
0xF, true, sctlr.nmfi);
|
||||
Cpsr = ~CondCodesMask & newCpsr;
|
||||
NextThumb = ((CPSR)newCpsr).t;
|
||||
NextJazelle = ((CPSR)newCpsr).j;
|
||||
ForcedItState = ((((CPSR)URb).it2 << 2) & 0xFC)
|
||||
| (((CPSR)URb).it1 & 0x3);
|
||||
CondCodes = CondCodesMask & newCpsr;
|
||||
'''
|
||||
|
||||
microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR',
|
||||
'MicroSetPCCPSR',
|
||||
{'code': setPCCPSRDecl,
|
||||
'predicate_test': predicateTest},
|
||||
['IsMicroop'])
|
||||
|
||||
header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \
|
||||
MicroIntImmDeclare.subst(microSubiUopIop) + \
|
||||
MicroIntRegDeclare.subst(microAddUopIop) + \
|
||||
MicroIntRegDeclare.subst(microSubUopIop) + \
|
||||
MicroIntMovDeclare.subst(microUopRegMovIop)
|
||||
MicroIntMovDeclare.subst(microUopRegMovIop) + \
|
||||
MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop)
|
||||
|
||||
decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \
|
||||
MicroIntImmConstructor.subst(microSubiUopIop) + \
|
||||
MicroIntRegConstructor.subst(microAddUopIop) + \
|
||||
MicroIntRegConstructor.subst(microSubUopIop) + \
|
||||
MicroIntMovConstructor.subst(microUopRegMovIop)
|
||||
MicroIntMovConstructor.subst(microUopRegMovIop) + \
|
||||
MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop)
|
||||
|
||||
exec_output = PredOpExecute.subst(microAddiUopIop) + \
|
||||
PredOpExecute.subst(microSubiUopIop) + \
|
||||
PredOpExecute.subst(microAddUopIop) + \
|
||||
PredOpExecute.subst(microSubUopIop) + \
|
||||
PredOpExecute.subst(microUopRegMovIop)
|
||||
PredOpExecute.subst(microUopRegMovIop) + \
|
||||
PredOpExecute.subst(microUopSetPCCPSRIop)
|
||||
|
||||
}};
|
||||
|
||||
let {{
|
||||
|
|
|
@ -48,7 +48,7 @@ let {{
|
|||
self.constructTemplate = eval(self.decConstBase + 'Constructor')
|
||||
|
||||
def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags,
|
||||
base = 'Memory', wbDecl = None):
|
||||
base = 'Memory', wbDecl = None, pcDecl = None):
|
||||
# Make sure flags are in lists (convert to lists if not).
|
||||
memFlags = makeList(memFlags)
|
||||
instFlags = makeList(instFlags)
|
||||
|
@ -65,12 +65,26 @@ let {{
|
|||
macroName = Name
|
||||
instFlagsCopy = list(instFlags)
|
||||
codeBlobsCopy = dict(codeBlobs)
|
||||
if wbDecl is not None:
|
||||
|
||||
use_uops = 0
|
||||
if wbDecl is not None or pcDecl is not None:
|
||||
instFlagsCopy.append('IsMicroop')
|
||||
Name = Name + 'Acc'
|
||||
use_uops = 1
|
||||
|
||||
use_wb = 0
|
||||
use_pc = 0
|
||||
if wbDecl is not None:
|
||||
use_wb = 1
|
||||
if pcDecl is not None:
|
||||
use_pc = 1
|
||||
|
||||
codeBlobsCopy['acc_name'] = Name
|
||||
codeBlobsCopy['wb_decl'] = wbDecl
|
||||
codeBlobsCopy['pc_decl'] = pcDecl
|
||||
codeBlobsCopy['use_uops'] = 0
|
||||
codeBlobsCopy['use_wb'] = 0
|
||||
codeBlobsCopy['use_pc'] = 0
|
||||
|
||||
iop = InstObjParams(name, Name, base,
|
||||
codeBlobsCopy, instFlagsCopy)
|
||||
|
@ -81,11 +95,14 @@ let {{
|
|||
self.initiateAccTemplate.subst(iop) + \
|
||||
self.completeAccTemplate.subst(iop)
|
||||
|
||||
if wbDecl is not None:
|
||||
if wbDecl is not None or pcDecl is not None:
|
||||
iop = InstObjParams(name, macroName, base,
|
||||
{ "wb_decl" : wbDecl,
|
||||
"pc_decl" : pcDecl,
|
||||
"acc_name" : Name,
|
||||
"use_uops" : 1 },
|
||||
"use_uops" : use_uops,
|
||||
"use_pc" : use_pc,
|
||||
"use_wb" : use_wb },
|
||||
['IsMacroop'])
|
||||
header_output += self.declareTemplate.subst(iop)
|
||||
decoder_output += self.constructTemplate.subst(iop)
|
||||
|
|
|
@ -107,6 +107,41 @@ def template MicroNeonMemDeclare {{
|
|||
};
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PC = Integer(ura)
|
||||
// CPSR = Integer(urb)
|
||||
//
|
||||
|
||||
def template MicroSetPCCPSRDeclare {{
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
public:
|
||||
%(class_name)s(ExtMachInst machInst,
|
||||
IntRegIndex _ura,
|
||||
IntRegIndex _urb,
|
||||
IntRegIndex _urc);
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
def template MicroSetPCCPSRConstructor {{
|
||||
%(class_name)s::%(class_name)s(ExtMachInst machInst,
|
||||
IntRegIndex _ura,
|
||||
IntRegIndex _urb,
|
||||
IntRegIndex _urc)
|
||||
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||
_ura, _urb, _urc)
|
||||
{
|
||||
%(constructor)s;
|
||||
if (!(condCode == COND_AL || condCode == COND_UC)) {
|
||||
for (int x = 0; x < _numDestRegs; x++) {
|
||||
_srcRegIdx[_numSrcRegs++] = _destRegIdx[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Integer = Integer op Integer microops
|
||||
|
|
|
@ -917,9 +917,9 @@ def template CompleteAccDeclare {{
|
|||
|
||||
def template RfeConstructor {{
|
||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst,
|
||||
uint32_t _base, int _mode, bool _wb)
|
||||
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||
(IntRegIndex)_base, (AddrMode)_mode, _wb)
|
||||
uint32_t _base, int _mode, bool _wb)
|
||||
: %(base_class)s("%(mnemonic)s", machInst, %(op_class)s,
|
||||
(IntRegIndex)_base, (AddrMode)_mode, _wb)
|
||||
{
|
||||
%(constructor)s;
|
||||
if (!(condCode == COND_AL || condCode == COND_UC)) {
|
||||
|
@ -928,12 +928,18 @@ def template RfeConstructor {{
|
|||
}
|
||||
}
|
||||
#if %(use_uops)d
|
||||
assert(numMicroops >= 2);
|
||||
uops = new StaticInstPtr[numMicroops];
|
||||
uops[0] = new %(acc_name)s(machInst, _base, _mode, _wb);
|
||||
uops[0]->setDelayedCommit();
|
||||
uops[1] = new %(wb_decl)s;
|
||||
uops[1]->setLastMicroop();
|
||||
uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d];
|
||||
int uopIdx = 0;
|
||||
uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb);
|
||||
uops[uopIdx]->setDelayedCommit();
|
||||
#if %(use_wb)d
|
||||
uops[++uopIdx] = new %(wb_decl)s;
|
||||
uops[uopIdx]->setDelayedCommit();
|
||||
#endif
|
||||
#if %(use_pc)d
|
||||
uops[++uopIdx] = new %(pc_decl)s;
|
||||
#endif
|
||||
uops[uopIdx]->setLastMicroop();
|
||||
#endif
|
||||
}
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue