kern,arch: Refactor SkipFuncEvent to not use skipFunction.
Replace it with a new virtual function. Change-Id: I9d516d21ab3b1d1d70ea1297f984f868d3e7c3fb Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/24111 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -69,7 +69,7 @@ FsFreebsd::FsFreebsd(Params *p) : ArmISA::FsWorkload(p),
|
||||
"oops_exit", "Kernel oops in guest");
|
||||
}
|
||||
|
||||
uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
|
||||
uDelaySkipEvent = addKernelFuncEvent<UDelayEvent<ArmISA::SkipFunc>>(
|
||||
"DELAY", "DELAY", 1000, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class FsFreebsd : public ArmISA::FsWorkload
|
||||
* processor for the appropriate amount of time. This is not functionally
|
||||
* required but does speed up simulation.
|
||||
*/
|
||||
FreeBSD::UDelayEvent *uDelaySkipEvent = nullptr;
|
||||
FreeBSD::UDelayEvent<SkipFunc> *uDelaySkipEvent = nullptr;
|
||||
|
||||
/** These variables store addresses of important data structures
|
||||
* that are normaly kept coherent at boot with cache mainetence operations.
|
||||
|
||||
@@ -51,6 +51,24 @@
|
||||
namespace ArmISA
|
||||
{
|
||||
|
||||
void
|
||||
SkipFunc::returnFromFuncIn(ThreadContext *tc)
|
||||
{
|
||||
PCState newPC = tc->pcState();
|
||||
if (inAArch64(tc)) {
|
||||
newPC.set(tc->readIntReg(INTREG_X30));
|
||||
} else {
|
||||
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
|
||||
}
|
||||
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
tc->pcStateNoRecord(newPC);
|
||||
} else {
|
||||
tc->pcState(newPC);
|
||||
}
|
||||
}
|
||||
|
||||
FsWorkload::FsWorkload(Params *p) : OsKernel(*p)
|
||||
{
|
||||
bootLoaders.reserve(p->boot_loader.size());
|
||||
|
||||
@@ -52,6 +52,13 @@
|
||||
namespace ArmISA
|
||||
{
|
||||
|
||||
class SkipFunc : public SkipFuncBase
|
||||
{
|
||||
public:
|
||||
using SkipFuncBase::SkipFuncBase;
|
||||
void returnFromFuncIn(ThreadContext *tc) override;
|
||||
};
|
||||
|
||||
class FsWorkload : public OsKernel
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -224,21 +224,23 @@ FsLinux::startup()
|
||||
|
||||
// With ARM udelay() is #defined to __udelay
|
||||
// newer kernels use __loop_udelay and __loop_const_udelay symbols
|
||||
uDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
|
||||
uDelaySkipEvent = addKernelFuncEvent<UDelayEvent<SkipFunc>>(
|
||||
"__loop_udelay", "__udelay", 1000, 0);
|
||||
if (!uDelaySkipEvent)
|
||||
uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
|
||||
uDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent<SkipFunc>>(
|
||||
"__udelay", "__udelay", 1000, 0);
|
||||
|
||||
// constant arguments to udelay() have some precomputation done ahead of
|
||||
// time. Constant comes from code.
|
||||
constUDelaySkipEvent = addKernelFuncEvent<UDelayEvent>(
|
||||
constUDelaySkipEvent = addKernelFuncEvent<UDelayEvent<SkipFunc>>(
|
||||
"__loop_const_udelay", "__const_udelay", 1000, 107374);
|
||||
if (!constUDelaySkipEvent)
|
||||
constUDelaySkipEvent = addKernelFuncEventOrPanic<UDelayEvent>(
|
||||
constUDelaySkipEvent =
|
||||
addKernelFuncEventOrPanic<UDelayEvent<SkipFunc>>(
|
||||
"__const_udelay", "__const_udelay", 1000, 107374);
|
||||
|
||||
debugPrintkEvent = addKernelFuncEvent<DebugPrintkEvent>("dprintk");
|
||||
debugPrintkEvent =
|
||||
addKernelFuncEvent<DebugPrintkEvent<SkipFunc>>("dprintk");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -63,7 +63,7 @@ class FsLinux : public ArmISA::FsWorkload
|
||||
* PC based event to skip the dprink() call and emulate its
|
||||
* functionality
|
||||
*/
|
||||
Linux::DebugPrintkEvent *debugPrintkEvent = nullptr;
|
||||
Linux::DebugPrintkEvent<SkipFunc> *debugPrintkEvent = nullptr;
|
||||
|
||||
DumpStatsPCEvent *dumpStatsPCEvent = nullptr;
|
||||
|
||||
@@ -119,14 +119,14 @@ class FsLinux : public ArmISA::FsWorkload
|
||||
* processor for the appropriate amount of time. This is not functionally
|
||||
* required but does speed up simulation.
|
||||
*/
|
||||
Linux::UDelayEvent *uDelaySkipEvent;
|
||||
Linux::UDelayEvent<SkipFunc> *uDelaySkipEvent = nullptr;
|
||||
|
||||
/** Another PC based skip event for const_udelay(). Similar to the udelay
|
||||
* skip, but this function precomputes the first multiply that is done
|
||||
* in the generic case since the parameter is known at compile time.
|
||||
* Thus we need to do some division to get back to us.
|
||||
*/
|
||||
Linux::UDelayEvent *constUDelaySkipEvent;
|
||||
Linux::UDelayEvent<SkipFunc> *constUDelaySkipEvent = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -115,24 +115,6 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
|
||||
panic("getArgument() should always return\n");
|
||||
}
|
||||
|
||||
void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
PCState newPC = tc->pcState();
|
||||
if (inAArch64(tc)) {
|
||||
newPC.set(tc->readIntReg(INTREG_X30));
|
||||
} else {
|
||||
newPC.set(tc->readIntReg(ReturnAddressReg) & ~ULL(1));
|
||||
}
|
||||
|
||||
CheckerCPU *checker = tc->getCheckerCpuPtr();
|
||||
if (checker) {
|
||||
tc->pcStateNoRecord(newPC);
|
||||
} else {
|
||||
tc->pcState(newPC);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copyVecRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
|
||||
@@ -389,8 +389,6 @@ bool SPAlignmentCheckEnabled(ThreadContext* tc);
|
||||
|
||||
uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp);
|
||||
|
||||
void skipFunction(ThreadContext *tc);
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -77,7 +77,7 @@ LinuxMipsSystem::setDelayLoop(ThreadContext *tc)
|
||||
void
|
||||
LinuxMipsSystem::SkipDelayLoopEvent::process(ThreadContext *tc)
|
||||
{
|
||||
SkipFuncEvent::process(tc);
|
||||
MipsISA::SkipFunc::process(tc);
|
||||
// calculate and set loops_per_jiffy
|
||||
((LinuxMipsSystem *)tc->getSystemPtr())->setDelayLoop(tc);
|
||||
}
|
||||
|
||||
@@ -47,11 +47,13 @@ class IdleStartEvent;
|
||||
class LinuxMipsSystem : public MipsSystem
|
||||
{
|
||||
private:
|
||||
class SkipDelayLoopEvent : public SkipFuncEvent
|
||||
using SkipFunc = MipsISA::SkipFunc;
|
||||
|
||||
class SkipDelayLoopEvent : public SkipFunc
|
||||
{
|
||||
public:
|
||||
SkipDelayLoopEvent(PCEventScope *s, const std::string &desc, Addr addr)
|
||||
: SkipFuncEvent(s, desc, addr) {}
|
||||
: SkipFunc(s, desc, addr) {}
|
||||
virtual void process(ThreadContext *tc);
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
|
||||
#include "arch/mips/system.hh"
|
||||
|
||||
#include "arch/vtophys.hh"
|
||||
#include "arch/mips/registers.hh"
|
||||
#include "arch/mips/vtophys.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "base/trace.hh"
|
||||
@@ -37,6 +38,14 @@
|
||||
#include "params/MipsSystem.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
|
||||
void
|
||||
MipsISA::SkipFunc::returnFromFuncIn(ThreadContext *tc)
|
||||
{
|
||||
MipsISA::PCState newPC = tc->pcState();
|
||||
newPC.set(tc->readIntReg(MipsISA::ReturnAddressReg));
|
||||
tc->pcState(newPC);
|
||||
}
|
||||
|
||||
MipsSystem::MipsSystem(Params *p) : System(p)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +40,20 @@
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
|
||||
namespace MipsISA
|
||||
{
|
||||
|
||||
class SkipFunc : public SkipFuncBase
|
||||
{
|
||||
public:
|
||||
using SkipFuncBase::SkipFuncBase;
|
||||
|
||||
void returnFromFuncIn(ThreadContext *tc) override;
|
||||
};
|
||||
|
||||
} // namespace MipsaISA
|
||||
|
||||
class MipsSystem : public System
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -242,13 +242,5 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
panic("Copy Misc. Regs Not Implemented Yet\n");
|
||||
}
|
||||
void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
PCState newPC = tc->pcState();
|
||||
newPC.set(tc->readIntReg(ReturnAddressReg));
|
||||
tc->pcState(newPC);
|
||||
}
|
||||
|
||||
|
||||
} // namespace MipsISA
|
||||
|
||||
@@ -102,8 +102,6 @@ RoundPage(Addr addr)
|
||||
void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void skipFunction(ThreadContext *tc);
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -62,10 +62,4 @@ getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
panic("Not Implemented for POWER");
|
||||
}
|
||||
|
||||
} // namespace PowerISA
|
||||
|
||||
@@ -52,8 +52,6 @@ copyMiscRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
}
|
||||
|
||||
void skipFunction(ThreadContext *tc);
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -152,12 +152,6 @@ registerName(RegId reg)
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
panic("Not Implemented for Riscv");
|
||||
}
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -242,12 +242,4 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||
dest->pcState(src->pcState());
|
||||
}
|
||||
|
||||
void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
PCState newPC = tc->pcState();
|
||||
newPC.set(tc->readIntReg(ReturnAddressReg));
|
||||
tc->pcState(newPC);
|
||||
}
|
||||
|
||||
} // namespace SPARC_ISA
|
||||
|
||||
@@ -64,8 +64,6 @@ void copyRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void skipFunction(ThreadContext *tc);
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -106,12 +106,6 @@ copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||
dest->pcState(src->pcState());
|
||||
}
|
||||
|
||||
void
|
||||
skipFunction(ThreadContext *tc)
|
||||
{
|
||||
panic("Not implemented for x86\n");
|
||||
}
|
||||
|
||||
uint64_t
|
||||
getRFlags(ThreadContext *tc)
|
||||
{
|
||||
|
||||
@@ -71,8 +71,6 @@ namespace X86ISA
|
||||
|
||||
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
|
||||
|
||||
void skipFunction(ThreadContext *tc);
|
||||
|
||||
inline void
|
||||
advancePC(PCState &pc, const StaticInstPtr &inst)
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
namespace FreeBSD {
|
||||
|
||||
void
|
||||
UDelayEvent::process(ThreadContext *tc)
|
||||
onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul)
|
||||
{
|
||||
int arg_num;
|
||||
|
||||
@@ -57,12 +57,10 @@ UDelayEvent::process(ThreadContext *tc)
|
||||
//DPRINTFN("DELAY(%d)\n", time);
|
||||
|
||||
// convert parameter to ns
|
||||
if (argDivToNs)
|
||||
time /= argDivToNs;
|
||||
if (div)
|
||||
time /= div;
|
||||
|
||||
time *= argMultToNs;
|
||||
|
||||
SkipFuncEvent::process(tc);
|
||||
time *= mul;
|
||||
|
||||
// Currently, only ARM full-system simulation uses UDelayEvents to skip
|
||||
// __delay and __loop_delay functions. One form involves setting quiesce
|
||||
|
||||
@@ -37,12 +37,15 @@
|
||||
|
||||
namespace FreeBSD {
|
||||
|
||||
void onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul);
|
||||
|
||||
/** A class to skip udelay() and related calls in the kernel.
|
||||
* This class has two additional parameters that take the argument to udelay and
|
||||
* manipulated it to come up with ns and eventually ticks to quiesce for.
|
||||
* See descriptions of argDivToNs and argMultToNs below.
|
||||
*/
|
||||
class UDelayEvent : public SkipFuncEvent
|
||||
template <typename Base>
|
||||
class UDelayEvent : public Base
|
||||
{
|
||||
private:
|
||||
/** value to divide arg by to create ns. This is present beacues the linux
|
||||
@@ -59,8 +62,14 @@ class UDelayEvent : public SkipFuncEvent
|
||||
public:
|
||||
UDelayEvent(PCEventScope *s, const std::string &desc, Addr addr,
|
||||
uint64_t mult, uint64_t div)
|
||||
: SkipFuncEvent(s, desc, addr), argDivToNs(div), argMultToNs(mult) {}
|
||||
virtual void process(ThreadContext *xc);
|
||||
: Base(s, desc, addr), argDivToNs(div), argMultToNs(mult) {}
|
||||
|
||||
void
|
||||
process(ThreadContext *tc) override
|
||||
{
|
||||
onUDelay(tc, argDivToNs, argMultToNs);
|
||||
Base::process(tc);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
namespace Linux {
|
||||
|
||||
void
|
||||
DebugPrintkEvent::process(ThreadContext *tc)
|
||||
onDebugPrintk(ThreadContext *tc)
|
||||
{
|
||||
if (DTRACE(DebugPrintf)) {
|
||||
std::stringstream ss;
|
||||
@@ -67,38 +67,11 @@ DebugPrintkEvent::process(ThreadContext *tc)
|
||||
StringWrap name(tc->getSystemPtr()->name() + ".dprintk");
|
||||
DPRINTFN("%s", ss.str());
|
||||
}
|
||||
SkipFuncEvent::process(tc);
|
||||
}
|
||||
|
||||
void
|
||||
UDelayEvent::process(ThreadContext *tc)
|
||||
{
|
||||
int arg_num = 0;
|
||||
|
||||
// Get the time in native size
|
||||
uint64_t time = TheISA::getArgument(tc, arg_num, (uint16_t)-1, false);
|
||||
|
||||
// convert parameter to ns
|
||||
if (argDivToNs)
|
||||
time /= argDivToNs;
|
||||
|
||||
time *= argMultToNs;
|
||||
|
||||
SkipFuncEvent::process(tc);
|
||||
|
||||
// Currently, only ARM full-system simulation uses UDelayEvents to skip
|
||||
// __delay and __loop_delay functions. One form involves setting quiesce
|
||||
// time to 0 with the assumption that quiesce will not happen. To avoid
|
||||
// the quiesce handling in this case, only execute the quiesce if time > 0.
|
||||
if (time > 0)
|
||||
tc->quiesceTick(curTick() + SimClock::Int::ns * time);
|
||||
}
|
||||
|
||||
void
|
||||
DmesgDumpEvent::process(ThreadContext *tc)
|
||||
{
|
||||
StringWrap name(tc->getCpuPtr()->name() + ".dmesg_dump_event");
|
||||
|
||||
inform("Dumping kernel dmesg buffer to %s...\n", fname);
|
||||
OutputStream *os = simout.create(fname);
|
||||
dumpDmesg(tc, *os->stream());
|
||||
@@ -110,8 +83,6 @@ DmesgDumpEvent::process(ThreadContext *tc)
|
||||
void
|
||||
KernelPanicEvent::process(ThreadContext *tc)
|
||||
{
|
||||
StringWrap name(tc->getCpuPtr()->name() + ".dmesg_dump_event");
|
||||
|
||||
inform("Dumping kernel dmesg buffer to %s...\n", fname);
|
||||
OutputStream *os = simout.create(fname);
|
||||
dumpDmesg(tc, *os->stream());
|
||||
@@ -120,4 +91,26 @@ KernelPanicEvent::process(ThreadContext *tc)
|
||||
panic(descr());
|
||||
}
|
||||
|
||||
void
|
||||
onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul)
|
||||
{
|
||||
int arg_num = 0;
|
||||
|
||||
// Get the time in native size
|
||||
uint64_t time = TheISA::getArgument(tc, arg_num, (uint16_t)-1, false);
|
||||
|
||||
// convert parameter to ns
|
||||
if (div)
|
||||
time /= div;
|
||||
|
||||
time *= mul;
|
||||
|
||||
// Currently, only ARM full-system simulation uses UDelayEvents to skip
|
||||
// __delay and __loop_delay functions. One form involves setting quiesce
|
||||
// time to 0 with the assumption that quiesce will not happen. To avoid
|
||||
// the quiesce handling in this case, only execute the quiesce if time > 0.
|
||||
if (time > 0)
|
||||
tc->quiesceTick(curTick() + SimClock::Int::ns * time);
|
||||
}
|
||||
|
||||
} // namespace linux
|
||||
|
||||
@@ -45,12 +45,20 @@
|
||||
|
||||
namespace Linux {
|
||||
|
||||
class DebugPrintkEvent : public SkipFuncEvent
|
||||
void onDebugPrintk(ThreadContext *tc);
|
||||
|
||||
template <typename Base>
|
||||
class DebugPrintkEvent : public Base
|
||||
{
|
||||
public:
|
||||
DebugPrintkEvent(PCEventScope *s, const std::string &desc, Addr addr)
|
||||
: SkipFuncEvent(s, desc, addr) {}
|
||||
virtual void process(ThreadContext *xc);
|
||||
: Base(s, desc, addr) {}
|
||||
virtual void
|
||||
process(ThreadContext *tc)
|
||||
{
|
||||
onDebugPrintk(tc);
|
||||
Base::process(tc);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -70,7 +78,7 @@ class DmesgDumpEvent : public PCEvent
|
||||
DmesgDumpEvent(PCEventScope *s, const std::string &desc, Addr addr,
|
||||
const std::string &_fname)
|
||||
: PCEvent(s, desc, addr), fname(_fname) {}
|
||||
virtual void process(ThreadContext *xc);
|
||||
virtual void process(ThreadContext *tc);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -90,15 +98,19 @@ class KernelPanicEvent : public PCEvent
|
||||
KernelPanicEvent(PCEventScope *s, const std::string &desc, Addr addr,
|
||||
const std::string &_fname)
|
||||
: PCEvent(s, desc, addr), fname(_fname) {}
|
||||
virtual void process(ThreadContext *xc);
|
||||
virtual void process(ThreadContext *tc);
|
||||
};
|
||||
|
||||
/** A class to skip udelay() and related calls in the kernel.
|
||||
* This class has two additional parameters that take the argument to udelay and
|
||||
* manipulated it to come up with ns and eventually ticks to quiesce for.
|
||||
void onUDelay(ThreadContext *tc, uint64_t div, uint64_t mul);
|
||||
|
||||
/**
|
||||
* A class to skip udelay() and related calls in the kernel.
|
||||
* This class has two additional parameters that take the argument to udelay
|
||||
* and manipulated it to come up with ns and eventually ticks to quiesce for.
|
||||
* See descriptions of argDivToNs and argMultToNs below.
|
||||
*/
|
||||
class UDelayEvent : public SkipFuncEvent
|
||||
template <typename Base>
|
||||
class UDelayEvent : public Base
|
||||
{
|
||||
private:
|
||||
/** value to divide arg by to create ns. This is present beacues the linux
|
||||
@@ -115,10 +127,15 @@ class UDelayEvent : public SkipFuncEvent
|
||||
public:
|
||||
UDelayEvent(PCEventScope *s, const std::string &desc, Addr addr,
|
||||
uint64_t mult, uint64_t div)
|
||||
: SkipFuncEvent(s, desc, addr), argDivToNs(div), argMultToNs(mult) {}
|
||||
virtual void process(ThreadContext *xc);
|
||||
};
|
||||
: Base(s, desc, addr), argDivToNs(div), argMultToNs(mult) {}
|
||||
|
||||
virtual void
|
||||
process(ThreadContext *tc)
|
||||
{
|
||||
onUDelay(tc, argDivToNs, argMultToNs);
|
||||
Base::process(tc);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -28,19 +28,17 @@
|
||||
|
||||
#include "kern/system_events.hh"
|
||||
|
||||
#include "arch/utility.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "config/the_isa.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "debug/PCEvent.hh"
|
||||
|
||||
void
|
||||
SkipFuncEvent::process(ThreadContext *tc)
|
||||
SkipFuncBase::process(ThreadContext *tc)
|
||||
{
|
||||
TheISA::PCState oldPC M5_VAR_USED = tc->pcState();
|
||||
|
||||
// Call ISA specific code to do the skipping
|
||||
TheISA::skipFunction(tc);
|
||||
returnFromFuncIn(tc);
|
||||
|
||||
DPRINTF(PCEvent, "skipping %s: pc = %s, newpc = %s\n", description,
|
||||
oldPC, tc->pcState());
|
||||
}
|
||||
|
||||
@@ -31,12 +31,16 @@
|
||||
|
||||
#include "cpu/pc_event.hh"
|
||||
|
||||
class SkipFuncEvent : public PCEvent
|
||||
class SkipFuncBase : public PCEvent
|
||||
{
|
||||
protected:
|
||||
virtual void returnFromFuncIn(ThreadContext *tc) = 0;
|
||||
|
||||
public:
|
||||
SkipFuncEvent(PCEventScope *s, const std::string &desc, Addr addr)
|
||||
SkipFuncBase(PCEventScope *s, const std::string &desc, Addr addr)
|
||||
: PCEvent(s, desc, addr)
|
||||
{}
|
||||
|
||||
void process(ThreadContext *tc) override;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user