summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/arm/faults.cc21
-rw-r--r--src/arch/arm/faults.hh14
-rw-r--r--src/arch/arm/isa/decoder/arm.isa15
3 files changed, 39 insertions, 11 deletions
diff --git a/src/arch/arm/faults.cc b/src/arch/arm/faults.cc
index 9e32a23a3..9b3657909 100644
--- a/src/arch/arm/faults.cc
+++ b/src/arch/arm/faults.cc
@@ -160,6 +160,27 @@ UndefinedInstruction::invoke(ThreadContext *tc)
}
}
+void
+SupervisorCall::invoke(ThreadContext *tc)
+{
+ // As of now, there isn't a 32 bit thumb version of this instruction.
+ assert(!machInst.bigThumb);
+ uint32_t callNum;
+ if (machInst.thumb) {
+ callNum = bits(machInst, 7, 0);
+ } else {
+ callNum = bits(machInst, 23, 0);
+ }
+ if (callNum == 0) {
+ callNum = tc->readIntReg(INTREG_R7);
+ }
+ tc->syscall(callNum);
+
+ // Advance the PC since that won't happen automatically.
+ tc->setPC(tc->readNextPC());
+ tc->setNextPC(tc->readNextNPC());
+}
+
#endif // FULL_SYSTEM
// return via SUBS pc, lr, xxx; rfe, movs, ldm
diff --git a/src/arch/arm/faults.hh b/src/arch/arm/faults.hh
index 90a730507..64940dd26 100644
--- a/src/arch/arm/faults.hh
+++ b/src/arch/arm/faults.hh
@@ -125,7 +125,19 @@ class UndefinedInstruction : public ArmFault<UndefinedInstruction>
#endif
};
-class SupervisorCall : public ArmFault<SupervisorCall> {};
+class SupervisorCall : public ArmFault<SupervisorCall>
+{
+#if !FULL_SYSTEM
+ protected:
+ ExtMachInst machInst;
+
+ public:
+ SupervisorCall(ExtMachInst _machInst) : machInst(_machInst)
+ {}
+
+ void invoke(ThreadContext *tc);
+#endif
+};
class PrefetchAbort : public ArmFault<PrefetchAbort> {};
class DataAbort : public ArmFault<DataAbort> {};
class Interrupt : public ArmFault<Interrupt> {};
diff --git a/src/arch/arm/isa/decoder/arm.isa b/src/arch/arm/isa/decoder/arm.isa
index 050571240..fe7e67b11 100644
--- a/src/arch/arm/isa/decoder/arm.isa
+++ b/src/arch/arm/isa/decoder/arm.isa
@@ -286,18 +286,13 @@ format DataOp {
} // CPNUM (OP4 == 1)
} //OPCODE_4
+ 1: PredOp::swi({{
#if FULL_SYSTEM
- 1: PredOp::swi({{ fault = new SupervisorCall; }}, IsSerializeAfter, IsNonSpeculative, IsSyscall);
+ fault = new SupervisorCall();
#else
- 1: PredOp::swi({{ if (testPredicate(CondCodes, condCode))
- {
- if (IMMED_23_0)
- xc->syscall(IMMED_23_0);
- else
- xc->syscall(R7);
- }
- }});
-#endif // FULL_SYSTEM
+ fault = new SupervisorCall(machInst);
+#endif
+ }}, IsSyscall);
} // OPCODE_24
}