ARM: Trigger system calls from the SupervisorCall invoke method.

This simplifies the decoder slightly, and makes the system call mechanism
very slightly more realistic.
This commit is contained in:
Gabe Black 2010-06-02 12:58:05 -05:00
parent 52460938cb
commit 34032f97d6
3 changed files with 39 additions and 11 deletions

View file

@ -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

View file

@ -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> {};

View file

@ -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
}