summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/faults.cc19
-rw-r--r--src/arch/arm/faults.hh8
-rw-r--r--src/arch/arm/isa/formats/misc.isa2
-rw-r--r--src/arch/arm/isa/formats/unimp.isa30
4 files changed, 55 insertions, 4 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 79973185d..2a6b7c359 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -71,6 +71,9 @@ template<> ArmFault::FaultVals ArmFaultVals<Interrupt>::vals =
template<> ArmFault::FaultVals ArmFaultVals<FastInterrupt>::vals =
{"FIQ", 0x1C, MODE_FIQ, 4, 4, true, true};
+template<> ArmFault::FaultVals ArmFaultVals<FlushPipe>::vals =
+ {"Pipe Flush", 0x00, MODE_SVC, 0, 0, true, true}; // some dummy values
+
Addr
ArmFault::getVector(ThreadContext *tc)
{
@@ -213,12 +216,22 @@ AbortFault<T>::invoke(ThreadContext *tc)
tc->setMiscReg(T::FarIndex, faultAddr);
}
+void
+FlushPipe::invoke(ThreadContext *tc) {
+ DPRINTF(Faults, "Invoking FlushPipe Fault\n");
+
+ // Set the PC to the next instruction of the faulting instruction.
+ // Net effect is simply squashing all instructions behind and
+ // start refetching from the next instruction.
+ tc->setPC(tc->readNextPC());
+ tc->setNextPC(tc->readNextNPC());
+ tc->setMicroPC(0);
+ tc->setNextMicroPC(1);
+}
+
template void AbortFault<PrefetchAbort>::invoke(ThreadContext *tc);
template void AbortFault<DataAbort>::invoke(ThreadContext *tc);
// return via SUBS pc, lr, xxx; rfe, movs, ldm
-
-
} // namespace ArmISA
-
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index 7dd881435..3eef0e551 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -227,6 +227,14 @@ class DataAbort : public AbortFault<DataAbort>
class Interrupt : public ArmFaultVals<Interrupt> {};
class FastInterrupt : public ArmFaultVals<FastInterrupt> {};
+// A fault that flushes the pipe, excluding the faulting instructions
+class FlushPipe : public ArmFaultVals<FlushPipe>
+{
+ public:
+ FlushPipe() {}
+ void invoke(ThreadContext *tc);
+};
+
static inline Fault genMachineCheckFault()
{
return new Reset();
diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa
index 884d93066..2d47c286f 100644
--- a/src/arch/arm/isa/formats/misc.isa
+++ b/src/arch/arm/isa/formats/misc.isa
@@ -111,7 +111,7 @@ let {{
return new WarnUnimplemented(
isRead ? "mrc dcimvac" : "mcr dcimvac", machInst);
case MISCREG_DCCMVAC:
- return new WarnUnimplemented(
+ return new FlushPipeInst(
isRead ? "mrc dccmvac" : "mcr dccmvac", machInst);
case MISCREG_DCCMVAU:
return new WarnUnimplemented(
diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa
index a746f8a7b..a0e0afd32 100644
--- a/src/arch/arm/isa/formats/unimp.isa
+++ b/src/arch/arm/isa/formats/unimp.isa
@@ -101,6 +101,22 @@ output header {{
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
+
+ class FlushPipeInst : public ArmStaticInst
+ {
+ public:
+ FlushPipeInst(const char *_mnemonic, ExtMachInst _machInst)
+ : ArmStaticInst(_mnemonic, _machInst, No_OpClass)
+ {
+ flags[IsNonSpeculative] = true;
+ }
+
+ %(BasicExecDeclare)s
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
+
+ };
}};
output decoder {{
@@ -117,6 +133,13 @@ output decoder {{
{
return csprintf("%-10s (unimplemented)", mnemonic);
}
+
+ std::string
+ FlushPipeInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ return csprintf("%-10s (pipe flush)", mnemonic);
+ }
}};
output exec {{
@@ -142,6 +165,13 @@ output exec {{
return NoFault;
}
+
+ Fault
+ FlushPipeInst::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ return new FlushPipe();
+ }
}};