arch-arm: Implementation of SelfHosted Debug Software step

This commit implements SelfHosted Debug Software step as is defined in
Armv8 Reference manual chapter D2.

+ decoder.hh/cc/isa: Checks the software step bit in order to skip the instruction
              before its decode.
+ faults.hh/cc: implemented SoftwareStep exception and proper modification
                of spsr during the invoke of other exceptions
+ isa.cc: Set debug mask if needed during cpsr modification
+ tlb.cc: Checks if software step is in ACTIVE state to avoid trigger
          breakpoint or watchpoint exception
+ self_debug.hh/cc: Implementation of State change and ss bit based during eret.
+ types.hh: Define sofware step flags like step, load or stepped to check the different flags
        that triggering software step should use for the ISS code.
+ pseudo.hh/isa: Triggers the sofware step esception after decode.
+ static_inst.cc: Call debugExceptionReturnsSS durint eret routine.

Change-Id: I3a64507c64842c34c76ad7f6daa5f4306bd55d2c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30617
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Jordi Vaquero
2019-10-29 16:28:30 +01:00
parent 675e01216d
commit 9c812d5aa9
16 changed files with 364 additions and 36 deletions

View File

@@ -53,7 +53,8 @@ namespace ArmISA
GenericISA::BasicDecodeCache Decoder::defaultCache;
Decoder::Decoder(ISA* isa)
: data(0), fpscrLen(0), fpscrStride(0), decoderFlavor(isa->decoderFlavor())
: data(0), fpscrLen(0), fpscrStride(0),
decoderFlavor(isa->decoderFlavor())
{
reset();
@@ -181,7 +182,7 @@ Decoder::decode(ArmISA::PCState &pc)
pc.nextItstate(itBits);
this_emi.itstate = pc.itstate();
this_emi.illegalExecution = pc.illegalExec() ? 1 : 0;
this_emi.debugStep = pc.debugStep() ? 1 : 0;
pc.size(inst_size);
emi = 0;

View File

@@ -289,6 +289,10 @@ template<> ArmFault::FaultVals ArmFaultVals<Watchpoint>::vals(
"Watchpoint", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
0, 0, 0, 0, true, false, false, EC_WATCHPOINT
);
template<> ArmFault::FaultVals ArmFaultVals<SoftwareStepFault>::vals(
"SoftwareStep", 0x000, 0x000, 0x200, 0x400, 0x600, MODE_SVC,
0, 0, 0, 0, true, false, false, EC_SOFTWARE_STEP
);
template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals(
// Some dummy values
"ArmSev Flush", 0x000, 0x000, 0x000, 0x000, 0x000, MODE_SVC,
@@ -649,6 +653,7 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
spsr.nz = tc->readCCReg(CCREG_NZ);
spsr.c = tc->readCCReg(CCREG_C);
spsr.v = tc->readCCReg(CCREG_V);
spsr.ss = isResetSPSR() ? 0: cpsr.ss;
if (from64) {
// Force some bitfields to 0
spsr.q = 0;
@@ -662,8 +667,6 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
ITSTATE it = tc->pcState().itstate();
spsr.it2 = it.top6;
spsr.it1 = it.bottom2;
// Force some bitfields to 0
spsr.ss = 0;
}
tc->setMiscReg(spsr_idx, spsr);
@@ -705,6 +708,7 @@ ArmFault::invoke64(ThreadContext *tc, const StaticInstPtr &inst)
pc.aarch64(!cpsr.width);
pc.nextAArch64(!cpsr.width);
pc.illegalExec(false);
pc.stepped(false);
tc->pcState(pc);
// Save exception syndrome
@@ -911,7 +915,9 @@ UndefinedInstruction::ec(ThreadContext *tc) const
HypervisorCall::HypervisorCall(ExtMachInst _machInst, uint32_t _imm) :
ArmFaultVals<HypervisorCall>(_machInst, _imm)
{}
{
bStep = true;
}
ExceptionClass
HypervisorCall::ec(ThreadContext *tc) const
@@ -1739,6 +1745,52 @@ Watchpoint::ec(ThreadContext *tc) const
return EC_WATCHPOINT_LOWER_EL;
}
SoftwareStepFault::SoftwareStepFault(ExtMachInst _mach_inst, bool is_ldx,
bool _stepped)
: ArmFaultVals<SoftwareStepFault>(_mach_inst), isldx(is_ldx),
stepped(_stepped)
{
bStep = true;
}
bool
SoftwareStepFault::routeToHyp(ThreadContext *tc) const
{
const bool have_el2 = ArmSystem::haveVirtualization(tc);
const HCR hcr = tc->readMiscRegNoEffect(MISCREG_HCR_EL2);
const HDCR mdcr = tc->readMiscRegNoEffect(MISCREG_MDCR_EL2);
return have_el2 && !inSecureState(tc) && fromEL <= EL1 &&
(hcr.tge || mdcr.tde);
}
ExceptionClass
SoftwareStepFault::ec(ThreadContext *tc) const
{
// AArch64
if (toEL == fromEL)
return EC_SOFTWARE_STEP_CURR_EL;
else
return EC_SOFTWARE_STEP_LOWER_EL;
}
uint32_t
SoftwareStepFault::iss() const
{
uint32_t iss= 0x0022;
if (stepped) {
iss |= 0x1000000;
}
if (isldx) {
iss |= 0x40;
}
return iss;
}
void
ArmSev::invoke(ThreadContext *tc, const StaticInstPtr &inst) {
DPRINTF(Faults, "Invoking ArmSev Fault\n");
@@ -1774,6 +1826,7 @@ template class ArmFaultVals<SystemError>;
template class ArmFaultVals<SoftwareBreakpoint>;
template class ArmFaultVals<HardwareBreakpoint>;
template class ArmFaultVals<Watchpoint>;
template class ArmFaultVals<SoftwareStepFault>;
template class ArmFaultVals<ArmSev>;
template class AbortFault<PrefetchAbort>;
template class AbortFault<DataAbort>;

View File

@@ -64,6 +64,7 @@ class ArmFault : public FaultBase
uint32_t issRaw;
// Helper variables for ARMv8 exception handling
bool bStep; // True if the Arm Faul exception is a software Step exception
bool from64; // True if the exception is generated from the AArch64 state
bool to64; // True if the exception is taken in AArch64 state
ExceptionLevel fromEL; // Source exception level
@@ -207,8 +208,8 @@ class ArmFault : public FaultBase
};
ArmFault(ExtMachInst _machInst = 0, uint32_t _iss = 0) :
machInst(_machInst), issRaw(_iss), from64(false), to64(false),
fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED),
machInst(_machInst), issRaw(_iss), bStep(false), from64(false),
to64(false), fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED),
faultUpdated(false), hypRouted(false), span(false) {}
// Returns the actual syndrome register to use based on the target
@@ -223,6 +224,7 @@ class ArmFault : public FaultBase
void invoke64(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr);
void update(ThreadContext *tc);
bool isResetSPSR(){ return bStep; }
ArmStaticInst *instrAnnotate(const StaticInstPtr &inst);
virtual void annotate(AnnotationIDs id, uint64_t val) {}
@@ -332,7 +334,9 @@ class SupervisorCall : public ArmFaultVals<SupervisorCall>
ExceptionClass _overrideEc = EC_INVALID) :
ArmFaultVals<SupervisorCall>(_machInst, _iss),
overrideEc(_overrideEc)
{}
{
bStep = true;
}
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
@@ -346,7 +350,9 @@ class SecureMonitorCall : public ArmFaultVals<SecureMonitorCall>
public:
SecureMonitorCall(ExtMachInst _machInst) :
ArmFaultVals<SecureMonitorCall>(_machInst)
{}
{
bStep = true;
}
void invoke(ThreadContext *tc, const StaticInstPtr &inst =
StaticInst::nullStaticInstPtr) override;
@@ -632,6 +638,19 @@ class Watchpoint : public ArmFaultVals<Watchpoint>
void annotate(AnnotationIDs id, uint64_t val);
};
class SoftwareStepFault : public ArmFaultVals<SoftwareStepFault>
{
private:
bool isldx;
bool stepped;
public:
SoftwareStepFault(ExtMachInst _mach_inst, bool is_ldx, bool stepped);
bool routeToHyp(ThreadContext *tc) const override;
uint32_t iss() const override;
ExceptionClass ec(ThreadContext *tc) const override;
};
// A fault that flushes the pipe, excluding the faulting instructions
class ArmSev : public ArmFaultVals<ArmSev>
{
@@ -674,6 +693,7 @@ template<> ArmFault::FaultVals ArmFaultVals<SystemError>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SoftwareBreakpoint>::vals;
template<> ArmFault::FaultVals ArmFaultVals<HardwareBreakpoint>::vals;
template<> ArmFault::FaultVals ArmFaultVals<Watchpoint>::vals;
template<> ArmFault::FaultVals ArmFaultVals<SoftwareStepFault>::vals;
template<> ArmFault::FaultVals ArmFaultVals<ArmSev>::vals;
/**

View File

@@ -190,3 +190,20 @@ IllegalExecInst::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
return std::make_shared<IllegalInstSetStateFault>();
}
DebugStep::DebugStep(ExtMachInst _machInst)
: ArmStaticInst("DebugStep", _machInst, No_OpClass)
{ }
Fault
DebugStep::execute(ExecContext *xc, Trace::InstRecord *traceData) const
{
PCState pc_state(xc->pcState());
pc_state.debugStep(false);
xc->pcState(pc_state);
auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
bool ldx = isa->getSelfDebug()->getSstep()->getLdx();
return std::make_shared<SoftwareStepFault>(machInst, ldx,
pc_state.stepped());
}

View File

@@ -131,4 +131,12 @@ class IllegalExecInst : public ArmStaticInst
Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const;
};
class DebugStep : public ArmStaticInst
{
public:
DebugStep(ExtMachInst _machInst);
Fault execute(ExecContext *xc, Trace::InstRecord *traceData) const;
};
#endif

View File

@@ -43,6 +43,8 @@
#include "arch/arm/faults.hh"
#include "arch/arm/isa.hh"
#include "arch/arm/self_debug.hh"
#include "arch/arm/utility.hh"
#include "base/condcodes.hh"
#include "base/cprintf.hh"
#include "base/loader/symtab.hh"
@@ -1106,10 +1108,7 @@ CPSR
ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
{
CPSR new_cpsr = 0;
// gem5 doesn't implement single-stepping, so force the SS bit to
// 0.
new_cpsr.ss = 0;
ExceptionLevel dest;
if (illegalExceptionReturn(tc, cpsr, spsr)) {
// If the SPSR specifies an illegal exception return,
@@ -1123,6 +1122,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
new_cpsr.el = cpsr.el;
new_cpsr.sp = cpsr.sp;
}
dest = currEL(tc);
} else {
new_cpsr.il = spsr.il;
if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) {
@@ -1133,6 +1133,7 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
new_cpsr.el = spsr.el;
new_cpsr.sp = spsr.sp;
}
dest = (ExceptionLevel)(uint8_t) spsr.el;
}
new_cpsr.nz = spsr.nz;
@@ -1154,6 +1155,10 @@ ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
new_cpsr.daif = spsr.daif;
}
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
SoftwareStep * ss = (isa->getSelfDebug())->getSstep();
new_cpsr.ss = ss->debugExceptionReturnSS(tc, spsr, dest, new_cpsr.width);
return new_cpsr;
}

View File

@@ -836,6 +836,7 @@ ISA::setMiscReg(int misc_reg, RegVal val)
pc.nextThumb(cpsr.t);
pc.nextJazelle(cpsr.j);
pc.illegalExec(cpsr.il == 1);
selfDebug->setDebugMask(cpsr.d == 1);
tc->getDecoderPtr()->setSveLen((getCurSveVecLenInBits() >> 7) - 1);

View File

@@ -46,6 +46,7 @@
// Opcode fields
def bitfield DECODERFAULT decoderFault;
def bitfield ILLEGALEXEC illegalExecution;
def bitfield DEBUGSTEP debugStep;
def bitfield ENCODING encoding;
def bitfield OPCODE opcode;

View File

@@ -38,17 +38,19 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
decode ILLEGALEXEC default IllegalExec::illegalExec() {
0: decode DECODERFAULT default DecoderFault::decoderFault() {
0: decode THUMB default Unknown::unknown() {
0: decode AARCH64 {
0:
##include "arm.isa"
decode DEBUGSTEP default DebugStep::debugStep() {
0: decode ILLEGALEXEC default IllegalExec::illegalExec() {
0: decode DECODERFAULT default DecoderFault::decoderFault() {
0: decode THUMB default Unknown::unknown() {
0: decode AARCH64 {
0:
##include "arm.isa"
1:
##include "aarch64.isa"
}
1:
##include "aarch64.isa"
##include "thumb.isa"
}
1:
##include "thumb.isa"
}
}
}

View File

@@ -59,6 +59,15 @@ def format IllegalExec() {{
decode_block = 'return new IllegalExecInst(machInst);\n'
}};
////////////////////////////////////////////////////////////////////
//
// Debug Step handling
//
def format DebugStep() {{
decode_block = 'return new DebugStep(machInst);\n'
}};
////////////////////////////////////////////////////////////////////
//
// Unknown instruction handling

View File

@@ -209,6 +209,13 @@ let {{
accCode = "IWDest = cSwap(Mem%s, ((CPSR)Cpsr).e);"
accCode = accCode % buildMemSuffix(self.sign, self.size)
if self.flavor in ('exclusive', 'acex'):
accCode += '''
auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
sd->getSstep()->setLdx();
'''
self.codeBlobs["memacc_code"] = accCode
# Push it out to the output files
@@ -284,6 +291,12 @@ let {{
FpDest_uw = (uint32_t)swappedMem;
FpDest2_uw = (uint32_t)(swappedMem >> 32);
'''
if self.flavor in ('exclusive', 'acex'):
accCode += '''
auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
sd->getSstep()->setLdx();
'''
self.codeBlobs["memacc_code"] = accCode

View File

@@ -236,7 +236,12 @@ let {{
accCode = "WDest = cSwap(Mem%s, isBigEndian64(xc->tcBase()));"
accCode = accCode % buildMemSuffix(self.sign, self.size)
if self.flavor in ('exclusive', 'acex'):
accCode += '''
auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
sd->getSstep()->setLdx();
'''
self.codeBlobs["memacc_code"] = accCode
if accEpilogCode:
self.codeBlobs["memacc_epilog_code"] = accEpilogCode
@@ -332,6 +337,12 @@ let {{
XDest2 = cSwap(Mem_tud[1],
isBigEndian64(xc->tcBase()));
'''
if self.flavor in ('exp', 'acexp'):
accCode += '''
auto *isa = static_cast<ArmISA::ISA *>(xc->tcBase()->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
sd->getSstep()->setLdx();
'''
self.codeBlobs["memacc_code"] = accCode
if accEpilogCode:
self.codeBlobs["memacc_epilog_code"] = accEpilogCode

View File

@@ -547,3 +547,74 @@ WatchPoint::compareAddress(ThreadContext *tc, Addr in_addr, uint8_t bas,
}
}
bool
SoftwareStep::debugExceptionReturnSS(ThreadContext *tc, CPSR spsr,
ExceptionLevel dest, bool aarch32)
{
bool SS_bit = false;
bool enabled_src = false;
if (bSS) {
enabled_src = conf->isDebugEnabled(tc);
bool enabled_dst = false;
bool secure = isSecureBelowEL3(tc) || dest == EL3;
CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
if (cpsr.width) {
enabled_dst = conf->isDebugEnabledForEL32(tc, dest, secure,
spsr.d == 1);
} else {
enabled_dst = conf->isDebugEnabledForEL64(tc, dest, secure,
spsr.d == 1);
}
ExceptionLevel ELd = debugTargetFrom(tc, secure);
if (!ELIs32(tc, ELd) && !enabled_src && enabled_dst) {
SS_bit = spsr.ss;
if (SS_bit == 0x0) {
stateSS = ACTIVE_PENDING_STATE;
} else {
stateSS = ACTIVE_NOT_PENDING_STATE;
}
}
}
return SS_bit;
}
bool
SoftwareStep::advanceSS(ThreadContext * tc)
{
PCState pc = tc->pcState();
bool res = false;
switch (stateSS){
case INACTIVE_STATE:
pc.debugStep(false);
break;
case ACTIVE_NOT_PENDING_STATE:
pc.debugStep(false);
if (cpsrD == 1 || !bSS) {
stateSS = INACTIVE_STATE;
} else {
pc.stepped(true);
stateSS = ACTIVE_PENDING_STATE;
tc->pcState(pc);
}
break;
case ACTIVE_PENDING_STATE:
if (!cpsrD && bSS) {
pc.debugStep(true);
res = true;
tc->pcState(pc);
}
stateSS = INACTIVE_STATE;
clearLdx();
break;
default:
break;
}
return res;
}

View File

@@ -48,11 +48,9 @@
class ThreadContext;
namespace ArmISA
{
class SelfDebug;
class BrkPoint
@@ -201,12 +199,70 @@ class WatchPoint
bool atomic, unsigned size);
};
class SoftwareStep
{
private:
static const uint8_t INACTIVE_STATE = 0;
static const uint8_t ACTIVE_PENDING_STATE = 1;
static const uint8_t ACTIVE_NOT_PENDING_STATE = 2;
bool bSS;
int stateSS;
SelfDebug * conf;
bool steppedLdx;
bool prevSteppedLdx;
bool cpsrD;
bool ctrStepped;
bool ctrActivate;
public:
SoftwareStep(SelfDebug* s): bSS(false), stateSS(INACTIVE_STATE),
conf(s), steppedLdx(false) { }
~SoftwareStep() { }
bool debugExceptionReturnSS(ThreadContext *tc, CPSR spsr,
ExceptionLevel dest, bool aarch32);
bool advanceSS(ThreadContext * tc);
inline void setCPSRD(bool val)
{
cpsrD = val;
}
inline void setEnableSS(bool val)
{
bSS = val;
}
void setLdx()
{
prevSteppedLdx = steppedLdx;
steppedLdx = true;
}
void clearLdx()
{
prevSteppedLdx = steppedLdx;
steppedLdx = false;
}
bool getLdx()
{
return prevSteppedLdx;
}
};
class SelfDebug
{
private:
std::vector<BrkPoint> arBrkPoints;
std::vector<WatchPoint> arWatchPoints;
SoftwareStep * softStep;
bool initialized;
bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
@@ -224,9 +280,14 @@ class SelfDebug
public:
SelfDebug(): initialized(false), enableTdeTge(false),
enableFlag(false), bSDD(false), bKDE(false), oslk(false)
{}
{
softStep = new SoftwareStep(this);
}
~SelfDebug(){}
~SelfDebug()
{
delete softStep;
}
Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
Fault testWatchPoints(ThreadContext *tc, Addr vaddr, bool write,
@@ -294,6 +355,7 @@ class SelfDebug
{
enableFlag = bits(val, 15);
bKDE = bits(val, 13);
softStep->setEnableSS((bool)bits(val, 0));
}
inline void setMDBGen(RegVal val)
@@ -321,6 +383,10 @@ class SelfDebug
arWatchPoints[index].updateControl(val);
}
inline void setDebugMask(bool mask)
{
softStep->setCPSRD(mask);
}
inline bool isAArch32()
{
return aarch32;
@@ -339,6 +405,11 @@ class SelfDebug
aarch32 = ELIs32(tc, fromEL);
return;
}
SoftwareStep * getSstep()
{
return softStep;
}
bool targetAArch32(ThreadContext * tc)
{
@@ -358,7 +429,7 @@ class SelfDebug
const AA64MMFR1 mm_fr1 = tc->readMiscReg(MISCREG_ID_AA64MMFR1_EL1);
const uint8_t nCtxtAwareBp = dfr.ctx_cmps;
const bool VMIDBits = mm_fr1.vmidbits;
for (int i=0; i<=dfr.brps; i++){
for (int i=0; i<=dfr.brps; i++) {
const bool isctxaw = i>=(dfr.brps-nCtxtAwareBp);
BrkPoint bkp = BrkPoint((MiscRegIndex)(MISCREG_DBGBCR0_EL1+i),
@@ -372,7 +443,7 @@ class SelfDebug
arBrkPoints.push_back(bkp);
}
for (int i=0; i<=dfr.wrps; i++){
for (int i=0; i<=dfr.wrps; i++) {
WatchPoint wtp = WatchPoint((MiscRegIndex)(MISCREG_DBGWCR0+i),
(MiscRegIndex)(MISCREG_DBGWVR0+i),
this, (bool)mm_fr2.varange, aarch32);

View File

@@ -1197,11 +1197,13 @@ TLB::translateFs(const RequestPtr &req, ThreadContext *tc, Mode mode,
auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
SelfDebug * sd = isa->getSelfDebug();
if (mode == Execute) {
fault = sd->testBreakPoints(tc, req->getVaddr());
const bool d_step = sd->getSstep()->advanceSS(tc);
if (!d_step) {
fault = sd->testBreakPoints(tc, req->getVaddr());
}
}
else if (!req->isCacheMaintenance() ||
(req->isCacheInvalidate() && !req->isCacheClean()))
{
(req->isCacheInvalidate() && !req->isCacheClean())) {
bool md = mode == Write ? true: false;
fault = sd->testWatchPoints(tc, req->getVaddr(), md,
req->isAtomic(),
@@ -1291,7 +1293,9 @@ TLB::translateComplete(const RequestPtr &req, ThreadContext *tc,
// stage 2 translation we prevent marking the translation as delayed twice,
// one when the translation starts and again when the stage 1 translation
// completes.
if (translation && (callFromS2 || !stage2Req || req->hasPaddr() || fault != NoFault)) {
if (translation && (callFromS2 || !stage2Req || req->hasPaddr() ||
fault != NoFault)) {
if (!delay)
translation->finish(fault, req, tc, mode);
else

View File

@@ -69,6 +69,7 @@ namespace ArmISA
// Decoder state
Bitfield<63, 62> decoderFault; // See DecoderFault
Bitfield<61> illegalExecution;
Bitfield<60> debugStep;
// SVE vector length, encoded in the same format as the ZCR_EL<x>.LEN
// bitfields
@@ -228,9 +229,15 @@ namespace ArmISA
uint8_t _nextItstate;
uint8_t _size;
bool _illegalExec;
// Software Step flags
bool _debugStep;
bool _stepped;
public:
PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0),
_size(0), _illegalExec(false)
_size(0), _illegalExec(false), _debugStep(false),
_stepped(false)
{}
void
@@ -241,7 +248,8 @@ namespace ArmISA
}
PCState(Addr val) : flags(0), nextFlags(0), _itstate(0),
_nextItstate(0), _size(0), _illegalExec(false)
_nextItstate(0), _size(0), _illegalExec(false),
_debugStep(false), _stepped(false)
{ set(val); }
bool
@@ -256,6 +264,30 @@ namespace ArmISA
_illegalExec = val;
}
bool
debugStep() const
{
return _debugStep;
}
void
debugStep(bool val)
{
_debugStep = val;
}
bool
stepped() const
{
return _stepped;
}
void
stepped(bool val)
{
_stepped = val;
}
bool
thumb() const
{
@@ -491,7 +523,9 @@ namespace ArmISA
flags == opc.flags && nextFlags == opc.nextFlags &&
_itstate == opc._itstate &&
_nextItstate == opc._nextItstate &&
_illegalExec == opc._illegalExec;
_illegalExec == opc._illegalExec &&
_debugStep == opc._debugStep &&
_stepped == opc._stepped;
}
bool
@@ -510,6 +544,8 @@ namespace ArmISA
SERIALIZE_SCALAR(_itstate);
SERIALIZE_SCALAR(_nextItstate);
SERIALIZE_SCALAR(_illegalExec);
SERIALIZE_SCALAR(_debugStep);
SERIALIZE_SCALAR(_stepped);
}
void
@@ -522,6 +558,8 @@ namespace ArmISA
UNSERIALIZE_SCALAR(_itstate);
UNSERIALIZE_SCALAR(_nextItstate);
UNSERIALIZE_SCALAR(_illegalExec);
UNSERIALIZE_SCALAR(_debugStep);
UNSERIALIZE_SCALAR(_stepped);
}
};
@@ -648,6 +686,9 @@ namespace ArmISA
EC_HW_BREAKPOINT = 0x30,
EC_HW_BREAKPOINT_LOWER_EL = 0x30,
EC_HW_BREAKPOINT_CURR_EL = 0x31,
EC_SOFTWARE_STEP = 0x32,
EC_SOFTWARE_STEP_LOWER_EL = 0x32,
EC_SOFTWARE_STEP_CURR_EL = 0x33,
EC_WATCHPOINT = 0x34,
EC_WATCHPOINT_LOWER_EL = 0x34,
EC_WATCHPOINT_CURR_EL = 0x35,