summaryrefslogtreecommitdiff
path: root/src/cpu/simple
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/simple')
-rw-r--r--src/cpu/simple/atomic.cc14
-rw-r--r--src/cpu/simple/base.cc50
-rw-r--r--src/cpu/simple/base.hh1
-rw-r--r--src/cpu/simple/timing.cc3
4 files changed, 52 insertions, 16 deletions
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index 38a8ba097..edba55b0d 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -183,11 +183,14 @@ AtomicSimpleCPU::unserialize(Checkpoint *cp, const string &section)
void
AtomicSimpleCPU::resume()
{
- changeState(SimObject::Running);
- if (thread->status() == ThreadContext::Active) {
+ if (_status != SwitchedOut && _status != Idle) {
assert(system->getMemoryMode() == System::Atomic);
- if (!tickEvent.scheduled())
- tickEvent.schedule(curTick);
+
+ changeState(SimObject::Running);
+ if (thread->status() == ThreadContext::Active) {
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+ }
}
}
@@ -448,7 +451,8 @@ AtomicSimpleCPU::tick()
for (int i = 0; i < width; ++i) {
numCycles++;
- checkForInterrupts();
+ if (!curStaticInst || !curStaticInst->isDelayedCommit())
+ checkForInterrupts();
Fault fault = setupFetchRequest(ifetch_req);
diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc
index a79d3c542..cbb3980cb 100644
--- a/src/cpu/simple/base.cc
+++ b/src/cpu/simple/base.cc
@@ -396,7 +396,20 @@ BaseSimpleCPU::preExecute()
// decode the instruction
inst = gtoh(inst);
- curStaticInst = StaticInst::decode(makeExtMI(inst, thread->readPC()));
+ //If we're not in the middle of a macro instruction
+ if (!curMacroStaticInst) {
+ StaticInstPtr instPtr = StaticInst::decode(makeExtMI(inst, thread->getTC()));
+ if (instPtr->isMacroOp()) {
+ curMacroStaticInst = instPtr;
+ curStaticInst = curMacroStaticInst->fetchMicroOp(0);
+ } else {
+ curStaticInst = instPtr;
+ }
+ } else {
+ //Read the next micro op from the macro op
+ curStaticInst = curMacroStaticInst->fetchMicroOp(thread->readMicroPC());
+ }
+
traceData = Trace::getInstRecord(curTick, tc, curStaticInst,
thread->readPC());
@@ -446,18 +459,35 @@ BaseSimpleCPU::advancePC(Fault fault)
{
if (fault != NoFault) {
fault->invoke(tc);
- }
- else {
- // go to the next instruction
- thread->setPC(thread->readNextPC());
+ } else {
+ //If we're at the last micro op for this instruction
+ if (curStaticInst->isLastMicroOp()) {
+ //We should be working with a macro op
+ assert(curMacroStaticInst);
+ //Close out this macro op, and clean up the
+ //microcode state
+ curMacroStaticInst = StaticInst::nullStaticInstPtr;
+ thread->setMicroPC(0);
+ thread->setNextMicroPC(1);
+ }
+ //If we're still in a macro op
+ if (curMacroStaticInst) {
+ //Advance the micro pc
+ thread->setMicroPC(thread->readNextMicroPC());
+ //Advance the "next" micro pc. Note that there are no delay
+ //slots, and micro ops are "word" addressed.
+ thread->setNextMicroPC(thread->readNextMicroPC() + 1);
+ } else {
+ // go to the next instruction
+ thread->setPC(thread->readNextPC());
#if ISA_HAS_DELAY_SLOT
- thread->setNextPC(thread->readNextNPC());
- thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
- assert(thread->readNextPC() != thread->readNextNPC());
+ thread->setNextPC(thread->readNextNPC());
+ thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+ assert(thread->readNextPC() != thread->readNextNPC());
#else
- thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+ thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
#endif
-
+ }
}
#if FULL_SYSTEM
diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh
index 57cfa3c2c..af6b6f835 100644
--- a/src/cpu/simple/base.hh
+++ b/src/cpu/simple/base.hh
@@ -128,6 +128,7 @@ class BaseSimpleCPU : public BaseCPU
TheISA::IntReg dataReg;
StaticInstPtr curStaticInst;
+ StaticInstPtr curMacroStaticInst;
void checkForInterrupts();
Fault setupFetchRequest(Request *req);
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 97df0e5d5..fe6775ea4 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -427,7 +427,8 @@ TimingSimpleCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
void
TimingSimpleCPU::fetch()
{
- checkForInterrupts();
+ if (!curStaticInst || !curStaticInst->isDelayedCommit())
+ checkForInterrupts();
Request *ifetch_req = new Request();
ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0);