diff options
-rw-r--r-- | src/arch/arm/faults.cc | 21 | ||||
-rw-r--r-- | src/arch/arm/faults.hh | 14 | ||||
-rw-r--r-- | src/arch/arm/isa/decoder/arm.isa | 15 |
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 } |