diff --git a/src/arch/alpha/utility.hh b/src/arch/alpha/utility.hh --- a/src/arch/alpha/utility.hh +++ b/src/arch/alpha/utility.hh @@ -116,6 +116,11 @@ return DTB_ASN_ASN(tc->readMiscRegNoEffect(IPR_DTB_ASN)); } +/* + * Returns true when single-stepping with remote gdb + */ +bool inSingleStepMode(ThreadContext *tc); + } // namespace AlphaISA #endif // __ARCH_ALPHA_UTILITY_HH__ # Node ID 54a9016bf08c3e82ed49fb21a44ad37a7329d8d7 # Parent 209b75a0b6f13f741d8d111092f6b72e58dbe9ed diff --git a/src/arch/alpha/utility.cc b/src/arch/alpha/utility.cc --- a/src/arch/alpha/utility.cc +++ b/src/arch/alpha/utility.cc @@ -104,6 +104,12 @@ tc->pcState(newPC); } +bool +inSingleStepMode(ThreadContext *tc) +{ + // not implemented + return false; +} } // namespace AlphaISA diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -323,6 +323,11 @@ */ uint8_t encodePhysAddrRange64(int pa_size); +/* + * Returns true when single-stepping with remote gdb + */ +bool inSingleStepMode(ThreadContext *tc); + } #endif diff --git a/src/arch/arm/utility.cc b/src/arch/arm/utility.cc --- a/src/arch/arm/utility.cc +++ b/src/arch/arm/utility.cc @@ -979,4 +979,11 @@ } } +bool +inSingleStepMode(ThreadContext *tc) +{ + // not implemented + return false; +} + } // namespace ArmISA diff --git a/src/arch/mips/utility.hh b/src/arch/mips/utility.hh --- a/src/arch/mips/utility.hh +++ b/src/arch/mips/utility.hh @@ -126,7 +126,11 @@ return 0; } +/* + * Returns true when single-stepping with remote gdb + */ +bool inSingleStepMode(ThreadContext *tc); + }; - #endif diff --git a/src/arch/mips/utility.cc b/src/arch/mips/utility.cc --- a/src/arch/mips/utility.cc +++ b/src/arch/mips/utility.cc @@ -273,5 +273,11 @@ tc->pcState(newPC); } +bool +inSingleStepMode(ThreadContext *tc) +{ + // not implemented + return false; +} } // namespace MipsISA diff --git a/src/arch/power/utility.hh b/src/arch/power/utility.hh --- a/src/arch/power/utility.hh +++ b/src/arch/power/utility.hh @@ -94,6 +94,11 @@ void initCPU(ThreadContext *, int cpuId); +/* + * Returns true when single-stepping with remote gdb + */ +bool inSingleStepMode(ThreadContext *tc); + } // namespace PowerISA diff --git a/src/arch/power/utility.cc b/src/arch/power/utility.cc --- a/src/arch/power/utility.cc +++ b/src/arch/power/utility.cc @@ -77,5 +77,11 @@ panic("initCPU not implemented for POWER.\n"); } +bool +inSingleStepMode(ThreadContext *tc) +{ + // not implemented + return false; +} } // namespace PowerISA diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -98,6 +98,11 @@ return tc->readMiscRegNoEffect(MISCREG_MMU_P_CONTEXT); } +/* + * Returns true if we're single-stepping with remote gdb + */ +bool inSingleStepMode(ThreadContext *tc); + } // namespace SparcISA #endif diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -261,4 +261,11 @@ por->invoke(tc); } +bool +inSingleStepMode(ThreadContext *tc) +{ + // not implemented + return false; +} + } // namespace SPARC_ISA diff --git a/src/arch/x86/remote_gdb.hh b/src/arch/x86/remote_gdb.hh --- a/src/arch/x86/remote_gdb.hh +++ b/src/arch/x86/remote_gdb.hh @@ -75,9 +75,7 @@ void clearSingleStep(); void setSingleStep(); - Addr nextBkpt; - Addr notTakenBkpt; - Addr takenBkpt; + void setTrapFlag(bool trap); }; } diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc --- a/src/arch/x86/remote_gdb.cc +++ b/src/arch/x86/remote_gdb.cc @@ -138,39 +138,25 @@ void RemoteGDB::clearSingleStep() { - DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n", - takenBkpt, notTakenBkpt); + DPRINTF(GDBMisc, "clearSingleStep bt_addr=%#x nt_addr=%#x\n"); - if (takenBkpt != 0) - clearTempBreakpoint(takenBkpt); - - if (notTakenBkpt != 0) - clearTempBreakpoint(notTakenBkpt); + setTrapFlag(false); + assert(!TheISA::inSingleStepMode(context)); } void RemoteGDB::setSingleStep() { - PCState pc = context->pcState(); - PCState bpc; - bool set_bt = false; + setTrapFlag(true); + assert(TheISA::inSingleStepMode(context)); - // User was stopped at pc, e.g. the instruction at pc was not - // executed. - ExtMachInst inst = read(pc.pc()); - StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc()); - if (si->hasBranchTarget(pc, context, bpc)) { - // Don't bother setting a breakpoint on the taken branch if it - // is the same as the next pc - if (bpc.pc() != pc.npc()) - set_bt = true; - } + DPRINTF(GDBMisc, "setSingleStep in remote gdb\n"); +} - DPRINTF(GDBMisc, "setSingleStep bt_addr=%#x nt_addr=%#x\n", - takenBkpt, notTakenBkpt); - - setTempBreakpoint(notTakenBkpt = pc.npc()); - - if (set_bt) - setTempBreakpoint(takenBkpt = bpc.pc()); +void +RemoteGDB::setTrapFlag(bool trap) +{ + RFLAGS rflagsReg = context->readMiscRegNoEffect(MISCREG_RFLAGS); + rflagsReg.tf = trap; + context->setMiscRegNoEffect(MISCREG_RFLAGS, rflagsReg); } diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh --- a/src/arch/x86/utility.hh +++ b/src/arch/x86/utility.hh @@ -203,6 +203,8 @@ * @param value Double precision float to store. */ void storeFloat80(void *mem, double value); + + bool inSingleStepMode(ThreadContext *tc); } #endif // __ARCH_X86_UTILITY_HH__ diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc --- a/src/arch/x86/utility.cc +++ b/src/arch/x86/utility.cc @@ -371,4 +371,11 @@ *fp80 = fp80_cvfd(value); } +bool +inSingleStepMode(ThreadContext *tc) { + + RFLAGS rflagsReg = tc->readMiscRegNoEffect(MISCREG_RFLAGS); + return (bool) rflagsReg.tf; +} + } // namespace X86_ISA diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -42,6 +42,7 @@ */ #include "arch/kernel_stats.hh" +#include "arch/remote_gdb.hh" #include "arch/stacktrace.hh" #include "arch/tlb.hh" #include "arch/utility.hh" @@ -552,6 +553,11 @@ delete traceData; traceData = NULL; } + + // check if the user requested a single-step in gdb + if(TheISA::inSingleStepMode(tc) && curStaticInst->isLastMicroop()) { + system->remoteGDB[0]->trap(SIGINT); + } } void