summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Horsnell <Matt.Horsnell@arm.com>2011-03-17 19:20:19 -0500
committerMatt Horsnell <Matt.Horsnell@arm.com>2011-03-17 19:20:19 -0500
commit031f396c71e750fede19651ba3a14e262a87e117 (patch)
treebfd6520d87f36775200aff930b632bfe3c80af1e
parente65f480d62e0112e89af6130e2f2024d89417df0 (diff)
downloadgem5-031f396c71e750fede19651ba3a14e262a87e117.tar.xz
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.
-rw-r--r--src/arch/arm/insts/macromem.cc9
-rw-r--r--src/arch/arm/insts/macromem.hh21
-rw-r--r--src/arch/arm/insts/mem.hh8
-rw-r--r--src/arch/arm/intregs.hh2
-rw-r--r--src/arch/arm/isa/insts/ldr.isa25
-rw-r--r--src/arch/arm/isa/insts/macromem.isa31
-rw-r--r--src/arch/arm/isa/insts/mem.isa25
-rw-r--r--src/arch/arm/isa/templates/macromem.isa35
-rw-r--r--src/arch/arm/isa/templates/mem.isa24
9 files changed, 146 insertions, 34 deletions
diff --git a/src/arch/arm/insts/macromem.cc b/src/arch/arm/insts/macromem.cc
index 2a45cf2e6..c03b7ccc1 100644
--- a/src/arch/arm/insts/macromem.cc
+++ b/src/arch/arm/insts/macromem.cc
@@ -896,6 +896,15 @@ MicroIntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
}
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
{
std::stringstream ss;
diff --git a/src/arch/arm/insts/macromem.hh b/src/arch/arm/insts/macromem.hh
index 1a2db8b9a..4933a1e7c 100644
--- a/src/arch/arm/insts/macromem.hh
+++ b/src/arch/arm/insts/macromem.hh
@@ -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
*/
diff --git a/src/arch/arm/insts/mem.hh b/src/arch/arm/insts/mem.hh
index a4fc62603..324d86fed 100644
--- a/src/arch/arm/insts/mem.hh
+++ b/src/arch/arm/insts/mem.hh
@@ -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
diff --git a/src/arch/arm/intregs.hh b/src/arch/arm/intregs.hh
index 4b2cc560d..2cbed6c59 100644
--- a/src/arch/arm/intregs.hh
+++ b/src/arch/arm/intregs.hh
@@ -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,
diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa
index c60a91a50..2e45f2875 100644
--- a/src/arch/arm/isa/insts/ldr.isa
+++ b/src/arch/arm/isa/insts/ldr.isa
@@ -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):
diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa
index 0e3bcc648..d6c929353 100644
--- a/src/arch/arm/isa/insts/macromem.isa
+++ b/src/arch/arm/isa/insts/macromem.isa
@@ -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 {{
diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa
index 507f8cd4b..d0c0f0710 100644
--- a/src/arch/arm/isa/insts/mem.isa
+++ b/src/arch/arm/isa/insts/mem.isa
@@ -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)
diff --git a/src/arch/arm/isa/templates/macromem.isa b/src/arch/arm/isa/templates/macromem.isa
index b7ca7fa48..a7f7f0da8 100644
--- a/src/arch/arm/isa/templates/macromem.isa
+++ b/src/arch/arm/isa/templates/macromem.isa
@@ -109,6 +109,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
//
diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa
index 3d073b322..dcfd47ace 100644
--- a/src/arch/arm/isa/templates/mem.isa
+++ b/src/arch/arm/isa/templates/mem.isa
@@ -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
}
}};