Line 45... |
Line 45... |
using sc_core::sc_fifo;
|
using sc_core::sc_fifo;
|
using sc_core::sc_module_name;
|
using sc_core::sc_module_name;
|
using sc_core::sc_stop;
|
using sc_core::sc_stop;
|
using sc_core::sc_time;
|
using sc_core::sc_time;
|
|
|
|
|
SC_HAS_PROCESS (GdbServerSC);
|
SC_HAS_PROCESS (GdbServerSC);
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Constructor for the GDB RSP server.
|
//! Constructor for the GDB RSP server.
|
|
|
Line 75... |
Line 74... |
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
GdbServerSC::GdbServerSC (sc_module_name name,
|
GdbServerSC::GdbServerSC (sc_module_name name,
|
uint32_t _flashStart,
|
uint32_t _flashStart,
|
uint32_t _flashEnd,
|
uint32_t _flashEnd,
|
int rspPort,
|
int rspPort,
|
sc_fifo<TapAction *> *tapActionQueue) :
|
sc_fifo <
|
sc_module (name),
|
TapAction * >*tapActionQueue):sc_module(name),
|
flashStart (_flashStart),
|
flashStart(_flashStart), flashEnd(_flashEnd)
|
flashEnd (_flashEnd)
|
|
{
|
{
|
pkt = new RspPacket (RSP_PKT_MAX);
|
pkt = new RspPacket (RSP_PKT_MAX);
|
rsp = new RspConnection (rspPort);
|
rsp = new RspConnection (rspPort);
|
debugUnit = new DebugUnitSC ("debug-unit", tapActionQueue);
|
debugUnit = new DebugUnitSC ("debug-unit", tapActionQueue);
|
mpHash = new MpHash ();
|
mpHash = new MpHash ();
|
Line 102... |
Line 100... |
|
|
SC_THREAD (rspServer);
|
SC_THREAD (rspServer);
|
|
|
} // GdbServerSC ()
|
} // GdbServerSC ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Destructor
|
//! Destructor
|
|
|
//! Free up data structures
|
//! Free up data structures
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Line 117... |
Line 114... |
delete rsp;
|
delete rsp;
|
delete pkt;
|
delete pkt;
|
|
|
} // ~GdbServerSC
|
} // ~GdbServerSC
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! SystemC thread to listen for RSP requests
|
//! SystemC thread to listen for RSP requests
|
|
|
//! JTAG actions will be queued as appropriate. Runs forever
|
//! JTAG actions will be queued as appropriate. Runs forever
|
|
|
Line 151... |
Line 147... |
*/
|
*/
|
debugUnit->stall ();
|
debugUnit->stall ();
|
targetStopped = true;
|
targetStopped = true;
|
|
|
// Make sure we are connected.
|
// Make sure we are connected.
|
while (!rsp->isConnected ())
|
while (!rsp->isConnected()) {
|
{
|
|
// Reconnect and stall the processor on a new connection
|
// Reconnect and stall the processor on a new connection
|
if (!rsp->rspConnect ())
|
if (!rsp->rspConnect()) {
|
{
|
|
// Serious failure. Must abort execution.
|
// Serious failure. Must abort execution.
|
cerr << "*** Unable to continue: ABORTING" << endl;
|
cerr << "*** Unable to continue: ABORTING" << endl;
|
sc_stop ();
|
sc_stop ();
|
}
|
}
|
|
|
// Stall the processor until we get a command to handle.
|
// Stall the processor until we get a command to handle.
|
if (!debugUnit->isStalled ())
|
if (!debugUnit->isStalled()) {
|
{
|
|
debugUnit->stall ();
|
debugUnit->stall ();
|
}
|
}
|
|
|
targetStopped = true; // Processor now not running
|
targetStopped = true; // Processor now not running
|
}
|
}
|
|
|
|
|
// Loop processing commands forever
|
// Loop processing commands forever
|
while (true)
|
while (true) {
|
{
|
if (!rsp->isConnected()) {
|
if (!rsp->isConnected())
|
|
{
|
|
sc_stop ();
|
sc_stop ();
|
return;
|
return;
|
}
|
}
|
// Wait until the target has stopped. In this simplified implementation,
|
// Wait until the target has stopped. In this simplified implementation,
|
// the only reasons for stopping are hitting a breakpoint (l.trap),
|
// the only reasons for stopping are hitting a breakpoint (l.trap),
|
// hardware single stepping or hitting a non-breakpoint l.trap. This
|
// hardware single stepping or hitting a non-breakpoint l.trap. This
|
// last is not cleanly handled at the moment (we ought to redirect the
|
// last is not cleanly handled at the moment (we ought to redirect the
|
// restart through the trap exception vector).
|
// restart through the trap exception vector).
|
while (!targetStopped)
|
while (!targetStopped) {
|
{
|
|
|
|
/* First check to see if the or1200 monitor module wants us to stall*/
|
/* First check to see if the or1200 monitor module wants us to stall*/
|
if (checkMonitorPipe())
|
if (checkMonitorPipe())
|
break;
|
break;
|
|
|
rspCheckForException();
|
rspCheckForException();
|
|
|
if (debugUnit->isStalled())
|
if (debugUnit->isStalled()) {
|
{
|
|
targetStopped = true;
|
targetStopped = true;
|
|
|
// If it's a breakpoint, then we need to back up one
|
// If it's a breakpoint, then we need to back up one
|
// instruction, so on restart we execute the actual
|
// instruction, so on restart we execute the actual
|
// instruction.
|
// instruction.
|
uint32_t ppc = debugUnit->readSpr (SPR_PPC);
|
uint32_t ppc = debugUnit->readSpr (SPR_PPC);
|
|
|
if (NULL != mpHash->lookup (BP_MEMORY, ppc) && rsp_sigval == TARGET_SIGNAL_TRAP)
|
if (NULL != mpHash->lookup(BP_MEMORY, ppc)
|
{
|
&& rsp_sigval == TARGET_SIGNAL_TRAP) {
|
writeNpc (ppc);
|
writeNpc (ppc);
|
}
|
}
|
|
|
// Tell the client we've stopped.
|
// Tell the client we've stopped.
|
rspReportException ();
|
rspReportException ();
|
}
|
} else if (rsp->rspSocketPeek() > 0) {
|
else if (rsp->rspSocketPeek() > 0)
|
|
{
|
|
if (rsp->rspSocketPeek() == 0x03) // ETX, end of text control char
|
if (rsp->rspSocketPeek() == 0x03) // ETX, end of text control char
|
{
|
{
|
// Got an interrupt command from GDB, this function should
|
// Got an interrupt command from GDB, this function should
|
// pull the packet off the socket and stall the processor.
|
// pull the packet off the socket and stall the processor.
|
// and then send a stop reply packet with signal
|
// and then send a stop reply packet with signal
|
Line 229... |
Line 213... |
// Get a RSP client request
|
// Get a RSP client request
|
rspClientRequest ();
|
rspClientRequest ();
|
}
|
}
|
} // rspServer ()
|
} // rspServer ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Deal with a request from the GDB client session
|
//! Deal with a request from the GDB client session
|
|
|
//! In general, apart from the simplest requests, this function replies on
|
//! In general, apart from the simplest requests, this function replies on
|
//! other functions to implement the functionality.
|
//! other functions to implement the functionality.
|
Line 246... |
Line 229... |
//! meaning? Or does it just mean that only vAttach will be recognized
|
//! meaning? Or does it just mean that only vAttach will be recognized
|
//! after this?
|
//! after this?
|
|
|
//! @param[in] pkt The received RSP packet
|
//! @param[in] pkt The received RSP packet
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspClientRequest()
|
GdbServerSC::rspClientRequest ()
|
|
{
|
|
if (!rsp->getPkt (pkt))
|
|
{
|
{
|
|
if (!rsp->getPkt(pkt)) {
|
rsp->rspClose (); // Comms failure
|
rsp->rspClose (); // Comms failure
|
return;
|
return;
|
}
|
}
|
//Uncomment the next line for the RSP client to print out every packet it gets from GDB
|
//Uncomment the next line for the RSP client to print out every packet it gets from GDB
|
//cerr << "rspClientRequest: " << pkt->data/*[0]*/ << endl;
|
//cerr << "rspClientRequest: " << pkt->data/*[0]*/ << endl;
|
switch (pkt->data[0])
|
switch (pkt->data[0]) {
|
{
|
|
case '!':
|
case '!':
|
// Request for extended remote mode
|
// Request for extended remote mode
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
Line 271... |
Line 251... |
rspReportException ();
|
rspReportException ();
|
return;
|
return;
|
|
|
case 'A':
|
case 'A':
|
// Initialization of argv not supported
|
// Initialization of argv not supported
|
cerr << "Warning: RSP 'A' packet not supported: ignored" << endl;
|
cerr << "Warning: RSP 'A' packet not supported: ignored" <<
|
|
endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
|
|
case 'b':
|
case 'b':
|
Line 440... |
Line 421... |
cerr << "Warning: Unknown RSP request" << pkt->data << endl;
|
cerr << "Warning: Unknown RSP request" << pkt->data << endl;
|
return;
|
return;
|
}
|
}
|
} // rspClientRequest ()
|
} // rspClientRequest ()
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Check if processor is stalled. If it is, read the DRR and return the
|
//! Check if processor is stalled. If it is, read the DRR and return the
|
//! target signal code.
|
//! target signal code.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspCheckForException()
|
GdbServerSC::rspCheckForException()
|
|
{
|
{
|
|
|
uint32_t drr;
|
uint32_t drr;
|
|
|
if (!debugUnit->isStalled())
|
if (!debugUnit->isStalled()) {
|
{
|
|
// Processor not stalled. Just return;
|
// Processor not stalled. Just return;
|
return;
|
return;
|
}
|
}
|
|
|
switch ((debugUnit->readSpr(SPR_DRR)&0xffffffff))
|
switch ((debugUnit->readSpr(SPR_DRR) & 0xffffffff)) {
|
{
|
case SPR_DRR_RSTE:
|
case SPR_DRR_RSTE: rsp_sigval = TARGET_SIGNAL_PWR; break;
|
rsp_sigval = TARGET_SIGNAL_PWR;
|
case SPR_DRR_BUSEE: rsp_sigval = TARGET_SIGNAL_BUS; break;
|
break;
|
case SPR_DRR_DPFE: rsp_sigval = TARGET_SIGNAL_SEGV; break;
|
case SPR_DRR_BUSEE:
|
case SPR_DRR_IPFE: rsp_sigval = TARGET_SIGNAL_SEGV; break;
|
rsp_sigval = TARGET_SIGNAL_BUS;
|
case SPR_DRR_TTE: rsp_sigval = TARGET_SIGNAL_ALRM; break;
|
break;
|
case SPR_DRR_AE: rsp_sigval = TARGET_SIGNAL_BUS; break;
|
case SPR_DRR_DPFE:
|
case SPR_DRR_IIE: rsp_sigval = TARGET_SIGNAL_ILL; break;
|
rsp_sigval = TARGET_SIGNAL_SEGV;
|
case SPR_DRR_IE: rsp_sigval = TARGET_SIGNAL_INT; break;
|
break;
|
case SPR_DRR_DME: rsp_sigval = TARGET_SIGNAL_SEGV; break;
|
case SPR_DRR_IPFE:
|
case SPR_DRR_IME: rsp_sigval = TARGET_SIGNAL_SEGV; break;
|
rsp_sigval = TARGET_SIGNAL_SEGV;
|
case SPR_DRR_RE: rsp_sigval = TARGET_SIGNAL_FPE; break;
|
break;
|
case SPR_DRR_SCE: rsp_sigval = TARGET_SIGNAL_USR2; break;
|
case SPR_DRR_TTE:
|
case SPR_DRR_FPE: rsp_sigval = TARGET_SIGNAL_FPE; break;
|
rsp_sigval = TARGET_SIGNAL_ALRM;
|
case SPR_DRR_TE: rsp_sigval = TARGET_SIGNAL_TRAP; break;
|
break;
|
|
case SPR_DRR_AE:
|
|
rsp_sigval = TARGET_SIGNAL_BUS;
|
|
break;
|
|
case SPR_DRR_IIE:
|
|
rsp_sigval = TARGET_SIGNAL_ILL;
|
|
break;
|
|
case SPR_DRR_IE:
|
|
rsp_sigval = TARGET_SIGNAL_INT;
|
|
break;
|
|
case SPR_DRR_DME:
|
|
rsp_sigval = TARGET_SIGNAL_SEGV;
|
|
break;
|
|
case SPR_DRR_IME:
|
|
rsp_sigval = TARGET_SIGNAL_SEGV;
|
|
break;
|
|
case SPR_DRR_RE:
|
|
rsp_sigval = TARGET_SIGNAL_FPE;
|
|
break;
|
|
case SPR_DRR_SCE:
|
|
rsp_sigval = TARGET_SIGNAL_USR2;
|
|
break;
|
|
case SPR_DRR_FPE:
|
|
rsp_sigval = TARGET_SIGNAL_FPE;
|
|
break;
|
|
case SPR_DRR_TE:
|
|
rsp_sigval = TARGET_SIGNAL_TRAP;
|
|
break;
|
|
|
default:
|
default:
|
// This must be the case of single step (which does not set DRR)
|
// This must be the case of single step (which does not set DRR)
|
rsp_sigval = TARGET_SIGNAL_TRAP; break;
|
rsp_sigval = TARGET_SIGNAL_TRAP;
|
|
break;
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Send a packet acknowledging an exception has occurred
|
//! Send a packet acknowledging an exception has occurred
|
|
|
//! The only signal we ever see in this implementation is TRAP.
|
//! The only signal we ever see in this implementation is TRAP.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspReportException()
|
GdbServerSC::rspReportException ()
|
|
{
|
{
|
// Construct a signal received packet
|
// Construct a signal received packet
|
pkt->data[0] = 'S';
|
pkt->data[0] = 'S';
|
pkt->data[1] = Utils::hex2Char (rsp_sigval >> 4);
|
pkt->data[1] = Utils::hex2Char (rsp_sigval >> 4);
|
pkt->data[2] = Utils::hex2Char (rsp_sigval % 16);
|
pkt->data[2] = Utils::hex2Char (rsp_sigval % 16);
|
Line 502... |
Line 506... |
|
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspReportException ()
|
} // rspReportException ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP continue request
|
//! Handle a RSP continue request
|
|
|
//! This version is typically used for the 'c' packet, to continue without
|
//! This version is typically used for the 'c' packet, to continue without
|
//! signal, in which case EXCEPT_NONE is passed in as the exception to use.
|
//! signal, in which case EXCEPT_NONE is passed in as the exception to use.
|
|
|
//! At present other exceptions are not supported
|
//! At present other exceptions are not supported
|
|
|
//! @param[in] except The OpenRISC 1000 exception to use
|
//! @param[in] except The OpenRISC 1000 exception to use
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspContinue(uint32_t except)
|
GdbServerSC::rspContinue (uint32_t except)
|
|
{
|
{
|
uint32_t addr; // Address to continue from, if any
|
uint32_t addr; // Address to continue from, if any
|
|
|
// Reject all except 'c' packets
|
// Reject all except 'c' packets
|
if ('c' != pkt->data[0])
|
if ('c' != pkt->data[0]) {
|
{
|
cerr <<
|
cerr << "Warning: Continue with signal not currently supported: "
|
"Warning: Continue with signal not currently supported: " <<
|
<< "ignored" << endl;
|
"ignored" << endl;
|
return;
|
return;
|
}
|
}
|
|
|
// Get an address if we have one
|
// Get an address if we have one
|
if (0 == strcmp ("c", pkt->data))
|
if (0 == strcmp("c", pkt->data)) {
|
{
|
|
addr = readNpc (); // Default uses current NPC
|
addr = readNpc (); // Default uses current NPC
|
}
|
} else if (1 != sscanf(pkt->data, "c%lx", &addr)) {
|
else if (1 != sscanf (pkt->data, "c%lx", &addr))
|
|
{
|
|
cerr << "Warning: RSP continue address " << pkt->data
|
cerr << "Warning: RSP continue address " << pkt->data
|
<< " not recognized: ignored" << endl;
|
<< " not recognized: ignored" << endl;
|
addr = readNpc (); // Default uses current NPC
|
addr = readNpc (); // Default uses current NPC
|
}
|
}
|
|
|
rspContinue (addr, EXCEPT_NONE);
|
rspContinue (addr, EXCEPT_NONE);
|
|
|
} // rspContinue ()
|
} // rspContinue ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP continue with signal request
|
//! Handle a RSP continue with signal request
|
|
|
//! @todo Currently does nothing. Will use the underlying generic continue
|
//! @todo Currently does nothing. Will use the underlying generic continue
|
//! function.
|
//! function.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspContinue()
|
GdbServerSC::rspContinue ()
|
|
{
|
{
|
cerr << "RSP continue with signal '" << pkt->data
|
cerr << "RSP continue with signal '" << pkt->data
|
<< "' received" << endl;
|
<< "' received" << endl;
|
|
|
} // rspContinue ()
|
} // rspContinue ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Generic processing of a continue request
|
//! Generic processing of a continue request
|
|
|
//! The signal may be EXCEPT_NONE if there is no exception to be
|
//! The signal may be EXCEPT_NONE if there is no exception to be
|
//! handled. Currently the exception is ignored.
|
//! handled. Currently the exception is ignored.
|
Line 570... |
Line 565... |
//! processor is unstalled.
|
//! processor is unstalled.
|
|
|
//! @param[in] addr Address from which to step
|
//! @param[in] addr Address from which to step
|
//! @param[in] except The exception to use (if any)
|
//! @param[in] except The exception to use (if any)
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspContinue(uint32_t addr, uint32_t except)
|
GdbServerSC::rspContinue (uint32_t addr,
|
|
uint32_t except)
|
|
{
|
{
|
// Set the address as the value of the next program counter
|
// Set the address as the value of the next program counter
|
writeNpc (addr);
|
writeNpc (addr);
|
|
|
/*
|
/*
|
Line 590... |
Line 583... |
*/
|
*/
|
|
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode
|
// Register 2 for watchpoints that we triggered to stop this time.
|
// Register 2 for watchpoints that we triggered to stop this time.
|
debugUnit->writeSpr (SPR_DRR, 0);
|
debugUnit->writeSpr (SPR_DRR, 0);
|
if (rsp_sigval == TARGET_SIGNAL_TRAP)
|
if (rsp_sigval == TARGET_SIGNAL_TRAP) {
|
{
|
|
/*
|
/*
|
Disable last trap generation on watchpoint if this is why we stopped
|
Disable last trap generation on watchpoint if this is why we stopped
|
last time.
|
last time.
|
*/
|
*/
|
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2);
|
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2);
|
if (temp_dmr2 & SPR_DMR2_WBS)
|
if (temp_dmr2 & SPR_DMR2_WBS) {
|
{
|
|
/*
|
/*
|
One of these breakpoints is responsible for our stopping, so
|
One of these breakpoints is responsible for our stopping, so
|
disable it this time we start. GDB will send a packet re-enabling
|
disable it this time we start. GDB will send a packet re-enabling
|
it next time we continue.
|
it next time we continue.
|
*/
|
*/
|
debugUnit->writeSpr (SPR_DMR2, temp_dmr2 & ~((temp_dmr2&SPR_DMR2_WBS)>>10));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
temp_dmr2 &
|
|
~((temp_dmr2 & SPR_DMR2_WBS) >>
|
|
10));
|
}
|
}
|
}
|
}
|
|
|
// Clear the single step trigger in Debug Mode Register 1 and set traps to
|
// Clear the single step trigger in Debug Mode Register 1 and set traps to
|
// be handled by the debug unit in the Debug Stop Register
|
// be handled by the debug unit in the Debug Stop Register
|
debugUnit->andSpr (SPR_DMR1, ~SPR_DMR1_ST);
|
debugUnit->andSpr (SPR_DMR1, ~SPR_DMR1_ST);
|
debugUnit->orSpr ( SPR_DSR, SPR_DSR_TE);
|
debugUnit->orSpr ( SPR_DSR, SPR_DSR_TE);
|
|
|
Line 620... |
Line 613... |
debugUnit->unstall ();
|
debugUnit->unstall ();
|
targetStopped = false;
|
targetStopped = false;
|
|
|
} // rspContinue ()
|
} // rspContinue ()
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
//!Handle an interrupt from GDB
|
//!Handle an interrupt from GDB
|
|
|
//! Detect an interrupt from GDB and stall the processor
|
//! Detect an interrupt from GDB and stall the processor
|
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspInterrupt()
|
GdbServerSC::rspInterrupt()
|
|
{
|
{
|
unsigned char c;
|
unsigned char c;
|
|
|
c = rsp->getRspChar();
|
c = rsp->getRspChar();
|
if (c < 0)
|
if (c < 0) {
|
{
|
|
// Had issues, just return
|
// Had issues, just return
|
return;
|
return;
|
}
|
}
|
|
|
// Ensure this is a ETX control char (0x3), currently, we only call this
|
// Ensure this is a ETX control char (0x3), currently, we only call this
|
// function when we've peeked and seen it, otherwise, ignore, return and pray
|
// function when we've peeked and seen it, otherwise, ignore, return and pray
|
// things go back to normal...
|
// things go back to normal...
|
if (c != 0x03)
|
if (c != 0x03) {
|
{
|
cerr <<
|
cerr << "* Warning: Interrupt character expected but not found on socket" << endl;
|
"* Warning: Interrupt character expected but not found on socket"
|
|
<< endl;
|
return;
|
return;
|
}
|
}
|
|
|
// Otherwise, it's an interrupt packet, stall the processor, and upon return
|
// Otherwise, it's an interrupt packet, stall the processor, and upon return
|
// to the main handle_rsp() loop, it will inform GDB.
|
// to the main handle_rsp() loop, it will inform GDB.
|
|
|
debugUnit->stall ();
|
debugUnit->stall ();
|
|
|
Line 670... |
Line 658... |
//! (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is
|
//! (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is
|
//! returned as a sequence of bytes in target endian order.
|
//! returned as a sequence of bytes in target endian order.
|
|
|
//! Each byte is packed as a pair of hex digits.
|
//! Each byte is packed as a pair of hex digits.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspReadAllRegs()
|
GdbServerSC::rspReadAllRegs ()
|
|
{
|
{
|
// The GPRs
|
// The GPRs
|
for (int r = 0; r < max_gprs; r++)
|
for (int r = 0; r < max_gprs; r++) {
|
{
|
|
Utils::reg2Hex (readGpr (r), &(pkt->data[r * 8]));
|
Utils::reg2Hex (readGpr (r), &(pkt->data[r * 8]));
|
}
|
}
|
|
|
// PPC, NPC and SR
|
// PPC, NPC and SR
|
Utils::reg2Hex (debugUnit->readSpr (SPR_PPC), &(pkt->data[PPC_REGNUM * 8]));
|
Utils::reg2Hex(debugUnit->readSpr(SPR_PPC),
|
|
&(pkt->data[PPC_REGNUM * 8]));
|
Utils::reg2Hex (readNpc (), &(pkt->data[NPC_REGNUM * 8]));
|
Utils::reg2Hex (readNpc (), &(pkt->data[NPC_REGNUM * 8]));
|
Utils::reg2Hex (debugUnit->readSpr (SPR_SR), &(pkt->data[SR_REGNUM * 8]));
|
Utils::reg2Hex (debugUnit->readSpr (SPR_SR), &(pkt->data[SR_REGNUM * 8]));
|
|
|
// Finalize the packet and send it
|
// Finalize the packet and send it
|
pkt->data[NUM_REGS * 8] = 0;
|
pkt->data[NUM_REGS * 8] = 0;
|
pkt->setLen (NUM_REGS * 8);
|
pkt->setLen (NUM_REGS * 8);
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspReadAllRegs ()
|
} // rspReadAllRegs ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP write all registers request
|
//! Handle a RSP write all registers request
|
|
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PPC
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PPC
|
//! (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is
|
//! (i.e. SPR PPC), NPC (i.e. SPR NPC) and SR (i.e. SPR SR). Each register is
|
Line 705... |
Line 691... |
|
|
//! @todo There is no error checking at present. Non-hex chars will generate a
|
//! @todo There is no error checking at present. Non-hex chars will generate a
|
//! warning message, but there is no other check that the right amount
|
//! warning message, but there is no other check that the right amount
|
//! of data is present. The result is always "OK".
|
//! of data is present. The result is always "OK".
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspWriteAllRegs()
|
GdbServerSC::rspWriteAllRegs ()
|
|
{
|
{
|
// The GPRs
|
// The GPRs
|
for (int r = 0; r < max_gprs; r++)
|
for (int r = 0; r < max_gprs; r++) {
|
{
|
|
writeGpr (r, Utils::hex2Reg (&(pkt->data[r * 8])));
|
writeGpr (r, Utils::hex2Reg (&(pkt->data[r * 8])));
|
}
|
}
|
|
|
// PPC, NPC and SR
|
// PPC, NPC and SR
|
debugUnit->writeSpr (SPR_PPC, Utils::hex2Reg (&(pkt->data[PPC_REGNUM * 8])));
|
debugUnit->writeSpr(SPR_PPC,
|
debugUnit->writeSpr (SPR_SR, Utils::hex2Reg (&(pkt->data[SR_REGNUM * 8])));
|
Utils::hex2Reg(&(pkt->data[PPC_REGNUM * 8])));
|
|
debugUnit->writeSpr(SPR_SR,
|
|
Utils::hex2Reg(&(pkt->data[SR_REGNUM * 8])));
|
writeNpc ( Utils::hex2Reg (&(pkt->data[NPC_REGNUM * 8])));
|
writeNpc ( Utils::hex2Reg (&(pkt->data[NPC_REGNUM * 8])));
|
|
|
// Acknowledge (always OK for now).
|
// Acknowledge (always OK for now).
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspWriteAllRegs ()
|
} // rspWriteAllRegs ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP read memory (symbolic) request
|
//! Handle a RSP read memory (symbolic) request
|
|
|
//! Syntax is:
|
//! Syntax is:
|
|
|
Line 738... |
Line 723... |
//! The response is the bytes, lowest address first, encoded as pairs of hex
|
//! The response is the bytes, lowest address first, encoded as pairs of hex
|
//! digits.
|
//! digits.
|
|
|
//! The length given is the number of bytes to be read.
|
//! The length given is the number of bytes to be read.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspReadMem()
|
GdbServerSC::rspReadMem ()
|
|
{
|
{
|
unsigned int addr; // Where to read the memory
|
unsigned int addr; // Where to read the memory
|
int len; // Number of bytes to read
|
int len; // Number of bytes to read
|
int off; // Offset into the memory
|
int off; // Offset into the memory
|
|
|
if (2 != sscanf (pkt->data, "m%x,%x:", &addr, &len))
|
if (2 != sscanf(pkt->data, "m%x,%x:", &addr, &len)) {
|
{
|
|
cerr << "Warning: Failed to recognize RSP read memory command: "
|
cerr << "Warning: Failed to recognize RSP read memory command: "
|
<< pkt->data << endl;
|
<< pkt->data << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Make sure we won't overflow the buffer (2 chars per byte)
|
// Make sure we won't overflow the buffer (2 chars per byte)
|
if ((len * 2) >= pkt->getBufSize())
|
if ((len * 2) >= pkt->getBufSize()) {
|
{
|
|
cerr << "Warning: Memory read " << pkt->data
|
cerr << "Warning: Memory read " << pkt->data
|
<< " too large for RSP packet: truncated" << endl;
|
<< " too large for RSP packet: truncated" << endl;
|
len = (pkt->getBufSize() - 1) / 2;
|
len = (pkt->getBufSize() - 1) / 2;
|
}
|
}
|
//cerr << "rspReadMem: " << len << " bytes@0x"<< hex << addr << endl;
|
//cerr << "rspReadMem: " << len << " bytes@0x"<< hex << addr << endl;
|
// Refill the buffer with the reply
|
// Refill the buffer with the reply
|
for (off = 0; off < len; off++)
|
for (off = 0; off < len; off++) {
|
{
|
|
unsigned char ch = debugUnit->readMem8 (addr + off);
|
unsigned char ch = debugUnit->readMem8 (addr + off);
|
|
|
pkt->data[off * 2] = Utils::hex2Char(ch >> 4);
|
pkt->data[off * 2] = Utils::hex2Char(ch >> 4);
|
pkt->data[off * 2 + 1] = Utils::hex2Char(ch & 0xf);
|
pkt->data[off * 2 + 1] = Utils::hex2Char(ch & 0xf);
|
}
|
}
|
Line 777... |
Line 757... |
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rsp_read_mem ()
|
} // rsp_read_mem ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP write memory (symbolic) request
|
//! Handle a RSP write memory (symbolic) request
|
|
|
//! Syntax is:
|
//! Syntax is:
|
|
|
Line 790... |
Line 769... |
//! The data is the bytes, lowest address first, encoded as pairs of hex
|
//! The data is the bytes, lowest address first, encoded as pairs of hex
|
//! digits.
|
//! digits.
|
|
|
//! The length given is the number of bytes to be written.
|
//! The length given is the number of bytes to be written.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspWriteMem()
|
GdbServerSC::rspWriteMem ()
|
|
{
|
{
|
uint32_t addr; // Where to write the memory
|
uint32_t addr; // Where to write the memory
|
int len; // Number of bytes to write
|
int len; // Number of bytes to write
|
|
|
if (2 != sscanf (pkt->data, "M%x,%x:", &addr, &len))
|
if (2 != sscanf(pkt->data, "M%x,%x:", &addr, &len)) {
|
{
|
|
cerr << "Warning: Failed to recognize RSP write memory "
|
cerr << "Warning: Failed to recognize RSP write memory "
|
<< pkt->data << endl;
|
<< pkt->data << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Find the start of the data and check there is the amount we expect.
|
// Find the start of the data and check there is the amount we expect.
|
char *symDat = (char *)(memchr (pkt->data, ':', pkt->getBufSize())) + 1;
|
char *symDat = (char *)(memchr (pkt->data, ':', pkt->getBufSize())) + 1;
|
int datLen = pkt->getLen() - (symDat - pkt->data);
|
int datLen = pkt->getLen() - (symDat - pkt->data);
|
|
|
// Sanity check
|
// Sanity check
|
if (len * 2 != datLen)
|
if (len * 2 != datLen) {
|
{
|
cerr << "Warning: Write of " << len *
|
cerr << "Warning: Write of " << len * 2 << "digits requested, but "
|
2 << "digits requested, but " << datLen <<
|
<< datLen << " digits supplied: packet ignored" << endl;
|
" digits supplied: packet ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Write the bytes to memory (no check the address is OK here)
|
// Write the bytes to memory (no check the address is OK here)
|
for (int off = 0; off < len; off++)
|
for (int off = 0; off < len; off++) {
|
{
|
|
uint8_t nyb1 = Utils::char2Hex (symDat[off * 2]);
|
uint8_t nyb1 = Utils::char2Hex (symDat[off * 2]);
|
uint8_t nyb2 = Utils::char2Hex (symDat[off * 2 + 1]);
|
uint8_t nyb2 = Utils::char2Hex (symDat[off * 2 + 1]);
|
|
|
if (!debugUnit->writeMem8 (addr + off, (nyb1 << 4) | nyb2))
|
if (!debugUnit->writeMem8(addr + off, (nyb1 << 4) | nyb2)) {
|
{
|
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
Line 838... |
Line 811... |
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspWriteMem ()
|
} // rspWriteMem ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Read a single register
|
//! Read a single register
|
|
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
|
//! (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a
|
//! (i.e. SPR NPC) and SR (i.e. SPR SR). The register is returned as a
|
//! sequence of bytes in target endian order.
|
//! sequence of bytes in target endian order.
|
|
|
//! Each byte is packed as a pair of hex digits.
|
//! Each byte is packed as a pair of hex digits.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspReadReg()
|
GdbServerSC::rspReadReg ()
|
|
{
|
{
|
unsigned int regNum;
|
unsigned int regNum;
|
|
|
// Break out the fields from the data
|
// Break out the fields from the data
|
if (1 != sscanf (pkt->data, "p%x", ®Num))
|
if (1 != sscanf(pkt->data, "p%x", ®Num)) {
|
{
|
cerr <<
|
cerr << "Warning: Failed to recognize RSP read register command: "
|
"Warning: Failed to recognize RSP read register command: "
|
<< pkt->data << endl;
|
<< pkt->data << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Get the relevant register
|
// Get the relevant register
|
if (regNum < max_gprs)
|
if (regNum < max_gprs) {
|
{
|
|
Utils::Utils::reg2Hex (readGpr (regNum), pkt->data);
|
Utils::Utils::reg2Hex (readGpr (regNum), pkt->data);
|
}
|
} else if (PPC_REGNUM == regNum) {
|
else if (PPC_REGNUM == regNum)
|
|
{
|
|
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_PPC), pkt->data);
|
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_PPC), pkt->data);
|
}
|
} else if (NPC_REGNUM == regNum) {
|
else if (NPC_REGNUM == regNum)
|
|
{
|
|
Utils::Utils::reg2Hex (readNpc (), pkt->data);
|
Utils::Utils::reg2Hex (readNpc (), pkt->data);
|
}
|
} else if (SR_REGNUM == regNum) {
|
else if (SR_REGNUM == regNum)
|
|
{
|
|
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_SR), pkt->data);
|
Utils::Utils::reg2Hex (debugUnit->readSpr (SPR_SR), pkt->data);
|
}
|
} else {
|
else
|
|
{
|
|
// Error response if we don't know the register
|
// Error response if we don't know the register
|
cerr << "Warning: Attempt to read unknown register" << regNum
|
cerr << "Warning: Attempt to read unknown register" << regNum
|
<< ": ignored" << endl;
|
<< ": ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
Line 895... |
Line 856... |
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspWriteReg ()
|
} // rspWriteReg ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Write a single register
|
//! Write a single register
|
|
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
|
//! The registers follow the GDB sequence for OR1K: GPR0 through GPR31, PC
|
//! (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a
|
//! (i.e. SPR NPC) and SR (i.e. SPR SR). The register is specified as a
|
//! sequence of bytes in target endian order.
|
//! sequence of bytes in target endian order.
|
|
|
//! Each byte is packed as a pair of hex digits.
|
//! Each byte is packed as a pair of hex digits.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspWriteReg()
|
GdbServerSC::rspWriteReg ()
|
|
{
|
{
|
unsigned int regNum;
|
unsigned int regNum;
|
char valstr[9]; // Allow for EOS on the string
|
char valstr[9]; // Allow for EOS on the string
|
|
|
// Break out the fields from the data
|
// Break out the fields from the data
|
if (2 != sscanf (pkt->data, "P%x=%8s", ®Num, valstr))
|
if (2 != sscanf(pkt->data, "P%x=%8s", ®Num, valstr)) {
|
{
|
cerr <<
|
cerr << "Warning: Failed to recognize RSP write register command "
|
"Warning: Failed to recognize RSP write register command "
|
<< pkt->data << endl;
|
<< pkt->data << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Set the relevant register
|
// Set the relevant register
|
if (regNum < max_gprs)
|
if (regNum < max_gprs) {
|
{
|
|
writeGpr (regNum, Utils::hex2Reg (valstr));
|
writeGpr (regNum, Utils::hex2Reg (valstr));
|
}
|
} else if (PPC_REGNUM == regNum) {
|
else if (PPC_REGNUM == regNum)
|
|
{
|
|
debugUnit->writeSpr (SPR_PPC, Utils::hex2Reg (valstr));
|
debugUnit->writeSpr (SPR_PPC, Utils::hex2Reg (valstr));
|
}
|
} else if (NPC_REGNUM == regNum) {
|
else if (NPC_REGNUM == regNum)
|
|
{
|
|
writeNpc (Utils::hex2Reg (valstr));
|
writeNpc (Utils::hex2Reg (valstr));
|
}
|
} else if (SR_REGNUM == regNum) {
|
else if (SR_REGNUM == regNum)
|
|
{
|
|
debugUnit->writeSpr (SPR_SR, Utils::hex2Reg (valstr));
|
debugUnit->writeSpr (SPR_SR, Utils::hex2Reg (valstr));
|
}
|
} else {
|
else
|
|
{
|
|
// Error response if we don't know the register
|
// Error response if we don't know the register
|
cerr << "Warning: Attempt to write unknown register " << regNum
|
cerr << "Warning: Attempt to write unknown register " << regNum
|
<< ": ignored" << endl;
|
<< ": ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
Line 953... |
Line 902... |
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspWriteReg ()
|
} // rspWriteReg ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP query request
|
//! Handle a RSP query request
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspQuery()
|
GdbServerSC::rspQuery ()
|
|
{
|
|
if (0 == strcmp ("qAttached", pkt->data))
|
|
{
|
{
|
|
if (0 == strcmp("qAttached", pkt->data)) {
|
// We are always attaching to an existing process with the bare metal
|
// We are always attaching to an existing process with the bare metal
|
// embedded system.
|
// embedded system.
|
pkt->packStr ("1");
|
pkt->packStr ("1");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strcmp("qC", pkt->data)) {
|
else if (0 == strcmp ("qC", pkt->data))
|
|
{
|
|
// Return the current thread ID (unsigned hex). A null response
|
// Return the current thread ID (unsigned hex). A null response
|
// indicates to use the previously selected thread. We use the constant
|
// indicates to use the previously selected thread. We use the constant
|
// OR1KSIM_TID to represent our single thread of control.
|
// OR1KSIM_TID to represent our single thread of control.
|
sprintf (pkt->data, "QC%x", OR1KSIM_TID);
|
sprintf (pkt->data, "QC%x", OR1KSIM_TID);
|
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qCRC", pkt->data, strlen("qCRC"))) {
|
else if (0 == strncmp ("qCRC", pkt->data, strlen ("qCRC")))
|
|
{
|
|
// Return CRC of memory area
|
// Return CRC of memory area
|
cerr << "Warning: RSP CRC query not supported" << endl;
|
cerr << "Warning: RSP CRC query not supported" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strcmp("qfThreadInfo", pkt->data)) {
|
else if (0 == strcmp ("qfThreadInfo", pkt->data))
|
|
{
|
|
// Return info about active threads. We return just the constant
|
// Return info about active threads. We return just the constant
|
// OR1KSIM_TID to represent our single thread of control.
|
// OR1KSIM_TID to represent our single thread of control.
|
sprintf (pkt->data, "m%x", OR1KSIM_TID);
|
sprintf (pkt->data, "m%x", OR1KSIM_TID);
|
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strcmp("qsThreadInfo", pkt->data)) {
|
else if (0 == strcmp ("qsThreadInfo", pkt->data))
|
|
{
|
|
// Return info about more active threads. We have no more, so return the
|
// Return info about more active threads. We have no more, so return the
|
// end of list marker, 'l'
|
// end of list marker, 'l'
|
pkt->packStr ("l");
|
pkt->packStr ("l");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 ==
|
else if (0 == strncmp ("qGetTLSAddr:", pkt->data, strlen ("qGetTLSAddr:")))
|
strncmp("qGetTLSAddr:", pkt->data, strlen("qGetTLSAddr:"))) {
|
{
|
|
// We don't support this feature
|
// We don't support this feature
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qL", pkt->data, strlen("qL"))) {
|
else if (0 == strncmp ("qL", pkt->data, strlen ("qL")))
|
|
{
|
|
// Deprecated and replaced by 'qfThreadInfo'
|
// Deprecated and replaced by 'qfThreadInfo'
|
cerr << "Warning: RSP qL deprecated: no info returned" << endl;
|
cerr << "Warning: RSP qL deprecated: no info returned" << endl;
|
pkt->packStr ("qM001");
|
pkt->packStr ("qM001");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strcmp("qOffsets", pkt->data)) {
|
else if (0 == strcmp ("qOffsets", pkt->data))
|
|
{
|
|
// Report any relocation
|
// Report any relocation
|
pkt->packStr ("Text=0;Data=0;Bss=0");
|
pkt->packStr ("Text=0;Data=0;Bss=0");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qP", pkt->data, strlen("qP"))) {
|
else if (0 == strncmp ("qP", pkt->data, strlen ("qP")))
|
|
{
|
|
// Deprecated and replaced by 'qThreadExtraInfo'
|
// Deprecated and replaced by 'qThreadExtraInfo'
|
cerr << "Warning: RSP qP deprecated: no info returned" << endl;
|
cerr << "Warning: RSP qP deprecated: no info returned" << endl;
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qRcmd,", pkt->data, strlen("qRcmd,"))) {
|
else if (0 == strncmp ("qRcmd,", pkt->data, strlen ("qRcmd,")))
|
|
{
|
|
// This is used to interface to commands to do "stuff"
|
// This is used to interface to commands to do "stuff"
|
rspCommand ();
|
rspCommand ();
|
}
|
} else if (0 == strncmp("qSupported", pkt->data, strlen("qSupported"))) {
|
else if (0 == strncmp ("qSupported", pkt->data, strlen ("qSupported")))
|
|
{
|
|
// Report a list of the features we support. For now we just ignore any
|
// Report a list of the features we support. For now we just ignore any
|
// supplied specific feature queries, but in the future these may be
|
// supplied specific feature queries, but in the future these may be
|
// supported as well. Note that the packet size allows for 'G' + all the
|
// supported as well. Note that the packet size allows for 'G' + all the
|
// registers sent to us, or a reply to 'g' with all the registers and an
|
// registers sent to us, or a reply to 'g' with all the registers and an
|
// EOS so the buffer is a well formed string.
|
// EOS so the buffer is a well formed string.
|
sprintf (pkt->data, "PacketSize=%x", pkt->getBufSize());
|
sprintf (pkt->data, "PacketSize=%x", pkt->getBufSize());
|
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qSymbol:", pkt->data, strlen("qSymbol:"))) {
|
else if (0 == strncmp ("qSymbol:", pkt->data, strlen ("qSymbol:")))
|
|
{
|
|
// Offer to look up symbols. Nothing we want (for now). TODO. This just
|
// Offer to look up symbols. Nothing we want (for now). TODO. This just
|
// ignores any replies to symbols we looked up, but we didn't want to
|
// ignores any replies to symbols we looked up, but we didn't want to
|
// do that anyway!
|
// do that anyway!
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qThreadExtraInfo,", pkt->data,
|
else if (0 == strncmp ("qThreadExtraInfo,", pkt->data,
|
strlen("qThreadExtraInfo,"))) {
|
strlen ("qThreadExtraInfo,")))
|
|
{
|
|
// Report that we are runnable, but the text must be hex ASCI
|
// Report that we are runnable, but the text must be hex ASCI
|
// digits. For now do this by steam, reusing the original packet
|
// digits. For now do this by steam, reusing the original packet
|
sprintf (pkt->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
sprintf (pkt->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
|
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
|
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qTStatus", pkt->data, strlen("qTstatus"))) {
|
else if (0 == strncmp ("qTStatus", pkt->data, strlen ("qTstatus")))
|
|
{
|
|
// We don't support tracing, return empty packet
|
// We don't support tracing, return empty packet
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("qXfer:", pkt->data, strlen("qXfer:"))) {
|
else if (0 == strncmp ("qXfer:", pkt->data, strlen ("qXfer:")))
|
|
{
|
|
// For now we support no 'qXfer' requests, but these should not be
|
// For now we support no 'qXfer' requests, but these should not be
|
// expected, since they were not reported by 'qSupported'
|
// expected, since they were not reported by 'qSupported'
|
cerr << "Warning: RSP 'qXfer' not supported: ignored" << endl;
|
cerr << "Warning: RSP 'qXfer' not supported: ignored" << endl;
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else {
|
else
|
|
{
|
|
cerr << "Unrecognized RSP query: ignored" << endl;
|
cerr << "Unrecognized RSP query: ignored" << endl;
|
}
|
}
|
} // rspQuery ()
|
} // rspQuery ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP qRcmd request
|
//! Handle a RSP qRcmd request
|
|
|
//! The actual command follows the "qRcmd," in ASCII encoded to hex
|
//! The actual command follows the "qRcmd," in ASCII encoded to hex
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspCommand()
|
GdbServerSC::rspCommand ()
|
|
{
|
{
|
char cmd[RSP_PKT_MAX];
|
char cmd[RSP_PKT_MAX];
|
|
|
Utils::hex2Ascii (cmd, &(pkt->data[strlen ("qRcmd,")]));
|
Utils::hex2Ascii (cmd, &(pkt->data[strlen ("qRcmd,")]));
|
|
|
// Work out which command it is
|
// Work out which command it is
|
if (0 == strncmp ("readspr ", cmd, strlen ("readspr")))
|
if (0 == strncmp("readspr ", cmd, strlen("readspr"))) {
|
{
|
|
unsigned int sprNum;
|
unsigned int sprNum;
|
|
|
// Parse and return error if we fail
|
// Parse and return error if we fail
|
if( 1 != sscanf (cmd, "readspr %4x", &sprNum))
|
if (1 != sscanf(cmd, "readspr %4x", &sprNum)) {
|
{
|
|
cerr << "Warning: qRcmd " << cmd
|
cerr << "Warning: qRcmd " << cmd
|
<< "not recognized: ignored" << endl;
|
<< "not recognized: ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// SPR out of range
|
// SPR out of range
|
if (sprNum > MAX_SPRS)
|
if (sprNum > MAX_SPRS) {
|
{
|
|
cerr << "Warning: qRcmd readspr " << hex << sprNum
|
cerr << "Warning: qRcmd readspr " << hex << sprNum
|
<< dec << " too large: ignored" << endl;
|
<< dec << " too large: ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Construct the reply
|
// Construct the reply
|
sprintf (cmd, "%8lx", debugUnit->readSpr (sprNum));
|
sprintf (cmd, "%8lx", debugUnit->readSpr (sprNum));
|
Utils::ascii2Hex (pkt->data, cmd);
|
Utils::ascii2Hex (pkt->data, cmd);
|
pkt->setLen (strlen (pkt->data));
|
pkt->setLen (strlen (pkt->data));
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if (0 == strncmp("writespr ", cmd, strlen("writespr"))) {
|
else if (0 == strncmp ("writespr ", cmd, strlen ("writespr")))
|
|
{
|
|
unsigned int sprNum;
|
unsigned int sprNum;
|
uint32_t val;
|
uint32_t val;
|
|
|
// Parse and return error if we fail
|
// Parse and return error if we fail
|
if( 2 != sscanf (cmd, "writespr %4x %8lx", &sprNum, &val))
|
if (2 != sscanf(cmd, "writespr %4x %8lx", &sprNum, &val)) {
|
{
|
cerr << "Warning: qRcmd " << cmd <<
|
cerr << "Warning: qRcmd " << cmd << " not recognized: ignored"
|
" not recognized: ignored" << endl;
|
<< endl;
|
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// SPR out of range
|
// SPR out of range
|
if (sprNum > MAX_SPRS)
|
if (sprNum > MAX_SPRS) {
|
{
|
|
cerr << "Warning: qRcmd writespr " << hex << sprNum
|
cerr << "Warning: qRcmd writespr " << hex << sprNum
|
<< dec << " too large: ignored" << endl;
|
<< dec << " too large: ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Update the SPR and reply "OK"
|
// Update the SPR and reply "OK"
|
debugUnit->writeSpr (sprNum, val);
|
debugUnit->writeSpr (sprNum, val);
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
}
|
|
|
} // rspCommand ()
|
} // rspCommand ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP set request
|
//! Handle a RSP set request
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspSet()
|
GdbServerSC::rspSet ()
|
|
{
|
|
if (0 == strncmp ("QPassSignals:", pkt->data, strlen ("QPassSignals:")))
|
|
{
|
{
|
|
if (0 == strncmp("QPassSignals:", pkt->data, strlen("QPassSignals:"))) {
|
// Passing signals not supported
|
// Passing signals not supported
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else if ((0 == strncmp("QTDP", pkt->data, strlen("QTDP"))) ||
|
else if ((0 == strncmp ("QTDP", pkt->data, strlen ("QTDP"))) ||
|
|
(0 == strncmp ("QFrame", pkt->data, strlen ("QFrame"))) ||
|
(0 == strncmp ("QFrame", pkt->data, strlen ("QFrame"))) ||
|
(0 == strcmp ("QTStart", pkt->data)) ||
|
(0 == strcmp ("QTStart", pkt->data)) ||
|
(0 == strcmp ("QTStop", pkt->data)) ||
|
(0 == strcmp ("QTStop", pkt->data)) ||
|
(0 == strcmp ("QTinit", pkt->data)) ||
|
(0 == strcmp ("QTinit", pkt->data)) ||
|
(0 == strncmp ("QTro", pkt->data, strlen ("QTro"))))
|
(0 == strncmp("QTro", pkt->data, strlen("QTro")))) {
|
{
|
|
// All tracepoint features are not supported. This reply is really only
|
// All tracepoint features are not supported. This reply is really only
|
// needed to 'QTDP', since with that the others should not be
|
// needed to 'QTDP', since with that the others should not be
|
// generated.
|
// generated.
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else {
|
else
|
|
{
|
|
cerr << "Unrecognized RSP set request: ignored" << endl;
|
cerr << "Unrecognized RSP set request: ignored" << endl;
|
delete pkt;
|
delete pkt;
|
}
|
}
|
} // rspSet ()
|
} // rspSet ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP restart request
|
//! Handle a RSP restart request
|
|
|
//! For now we just put the program counter back to the reset vector. If we
|
//! For now we just put the program counter back to the reset vector. If we
|
//! supported the vRun request, we should use the address specified
|
//! supported the vRun request, we should use the address specified
|
//! there. There is no point in unstalling the processor, since we'll never
|
//! there. There is no point in unstalling the processor, since we'll never
|
//! get control back.
|
//! get control back.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspRestart()
|
GdbServerSC::rspRestart ()
|
|
{
|
{
|
writeNpc (EXCEPT_RESET);
|
writeNpc (EXCEPT_RESET);
|
|
|
} // rspRestart ()
|
} // rspRestart ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP step request
|
//! Handle a RSP step request
|
|
|
//! This version is typically used for the 's' packet, to continue without
|
//! This version is typically used for the 's' packet, to continue without
|
//! signal, in which case EXCEPT_NONE is passed in as the exception to use.
|
//! signal, in which case EXCEPT_NONE is passed in as the exception to use.
|
|
|
//! @param[in] except The exception to use. Only EXCEPT_NONE should be set
|
//! @param[in] except The exception to use. Only EXCEPT_NONE should be set
|
//! this way.
|
//! this way.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspStep(uint32_t except)
|
GdbServerSC::rspStep (uint32_t except)
|
|
{
|
{
|
uint32_t addr; // The address to step from, if any
|
uint32_t addr; // The address to step from, if any
|
|
|
// Reject all except 's' packets
|
// Reject all except 's' packets
|
if ('s' != pkt->data[0])
|
if ('s' != pkt->data[0]) {
|
{
|
|
cerr << "Warning: Step with signal not currently supported: "
|
cerr << "Warning: Step with signal not currently supported: "
|
<< "ignored" << endl;
|
<< "ignored" << endl;
|
return;
|
return;
|
}
|
}
|
|
|
if (0 == strcmp ("s", pkt->data))
|
if (0 == strcmp("s", pkt->data)) {
|
{
|
|
addr = readNpc (); // Default uses current NPC
|
addr = readNpc (); // Default uses current NPC
|
}
|
} else if (1 != sscanf(pkt->data, "s%lx", &addr)) {
|
else if (1 != sscanf (pkt->data, "s%lx", &addr))
|
|
{
|
|
cerr << "Warning: RSP step address " << pkt->data
|
cerr << "Warning: RSP step address " << pkt->data
|
<< " not recognized: ignored" << endl;
|
<< " not recognized: ignored" << endl;
|
addr = readNpc (); // Default uses current NPC
|
addr = readNpc (); // Default uses current NPC
|
}
|
}
|
|
|
rspStep (addr, EXCEPT_NONE);
|
rspStep (addr, EXCEPT_NONE);
|
|
|
} // rspStep ()
|
} // rspStep ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP step with signal request
|
//! Handle a RSP step with signal request
|
|
|
//! @todo Currently null. Will use the underlying generic step function.
|
//! @todo Currently null. Will use the underlying generic step function.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspStep()
|
GdbServerSC::rspStep ()
|
|
{
|
{
|
cerr << "RSP step with signal '" << pkt->data << "' received" << endl;
|
cerr << "RSP step with signal '" << pkt->data << "' received" << endl;
|
|
|
} // rspStep ()
|
} // rspStep ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Generic processing of a step request
|
//! Generic processing of a step request
|
|
|
//! The signal may be EXCEPT_NONE if there is no exception to be
|
//! The signal may be EXCEPT_NONE if there is no exception to be
|
//! handled. Currently the exception is ignored.
|
//! handled. Currently the exception is ignored.
|
Line 1273... |
Line 1159... |
//! for continue) for any consecutive calls to step.
|
//! for continue) for any consecutive calls to step.
|
|
|
//! @param[in] addr Address from which to step
|
//! @param[in] addr Address from which to step
|
//! @param[in] except The exception to use (if any)
|
//! @param[in] except The exception to use (if any)
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspStep(uint32_t addr, uint32_t except)
|
GdbServerSC::rspStep (uint32_t addr,
|
|
uint32_t except)
|
|
{
|
{
|
// Set the address as the value of the next program counter
|
// Set the address as the value of the next program counter
|
writeNpc (addr);
|
writeNpc (addr);
|
|
|
/*
|
/*
|
Line 1293... |
Line 1177... |
*/
|
*/
|
|
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode
|
// Clear Debug Reason Register and watchpoint break generation in Debug Mode
|
// Register 2 for watchpoints that we triggered to stop this time.
|
// Register 2 for watchpoints that we triggered to stop this time.
|
debugUnit->writeSpr (SPR_DRR, 0);
|
debugUnit->writeSpr (SPR_DRR, 0);
|
if (rsp_sigval == TARGET_SIGNAL_TRAP)
|
if (rsp_sigval == TARGET_SIGNAL_TRAP) {
|
{
|
|
/*
|
/*
|
Disable last trap generation on watchpoint if this is why we stopped
|
Disable last trap generation on watchpoint if this is why we stopped
|
last time.
|
last time.
|
*/
|
*/
|
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2);
|
uint32_t temp_dmr2 = debugUnit->readSpr (SPR_DMR2);
|
if (temp_dmr2 & SPR_DMR2_WBS)
|
if (temp_dmr2 & SPR_DMR2_WBS) {
|
{
|
|
/*
|
/*
|
One of these breakpoints is responsible for our stopping, so
|
One of these breakpoints is responsible for our stopping, so
|
disable it this time we start. GDB will send a packet re-enabling
|
disable it this time we start. GDB will send a packet re-enabling
|
it next time we continue.
|
it next time we continue.
|
*/
|
*/
|
debugUnit->writeSpr (SPR_DMR2, temp_dmr2 & ~((temp_dmr2&SPR_DMR2_WBS)>>10));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
temp_dmr2 &
|
|
~((temp_dmr2 & SPR_DMR2_WBS) >>
|
|
10));
|
}
|
}
|
}
|
}
|
|
|
// Set the single step trigger in Debug Mode Register 1 and set traps to be
|
// Set the single step trigger in Debug Mode Register 1 and set traps to be
|
// handled by the debug unit in the Debug Stop Register
|
// handled by the debug unit in the Debug Stop Register
|
debugUnit->orSpr (SPR_DMR1, SPR_DMR1_ST);
|
debugUnit->orSpr (SPR_DMR1, SPR_DMR1_ST);
|
debugUnit->orSpr (SPR_DSR, SPR_DSR_TE);
|
debugUnit->orSpr (SPR_DSR, SPR_DSR_TE);
|
|
|
Line 1323... |
Line 1207... |
debugUnit->unstall ();
|
debugUnit->unstall ();
|
targetStopped = false;
|
targetStopped = false;
|
|
|
} // rspStep ()
|
} // rspStep ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP 'v' packet
|
//! Handle a RSP 'v' packet
|
|
|
//! These are commands associated with executing the code on the target
|
//! These are commands associated with executing the code on the target
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspVpkt()
|
GdbServerSC::rspVpkt ()
|
|
{
|
|
if (0 == strncmp ("vAttach;", pkt->data, strlen ("vAttach;")))
|
|
{
|
{
|
|
if (0 == strncmp("vAttach;", pkt->data, strlen("vAttach;"))) {
|
// Attaching is a null action, since we have no other process. We just
|
// Attaching is a null action, since we have no other process. We just
|
// return a stop packet (using TRAP) to indicate we are stopped.
|
// return a stop packet (using TRAP) to indicate we are stopped.
|
pkt->packStr ("S05");
|
pkt->packStr ("S05");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 == strcmp("vCont?", pkt->data)) {
|
else if (0 == strcmp ("vCont?", pkt->data))
|
|
{
|
|
// For now we don't support this.
|
// For now we don't support this.
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 == strncmp("vCont", pkt->data, strlen("vCont"))) {
|
else if (0 == strncmp ("vCont", pkt->data, strlen ("vCont")))
|
|
{
|
|
// This shouldn't happen, because we've reported non-support via vCont?
|
// This shouldn't happen, because we've reported non-support via vCont?
|
// above
|
// above
|
cerr << "Warning: RSP vCont not supported: ignored" << endl;
|
cerr << "Warning: RSP vCont not supported: ignored" << endl;
|
return;
|
return;
|
}
|
} else if (0 == strncmp("vFile:", pkt->data, strlen("vFile:"))) {
|
else if (0 == strncmp ("vFile:", pkt->data, strlen ("vFile:")))
|
|
{
|
|
// For now we don't support this.
|
// For now we don't support this.
|
cerr << "Warning: RSP vFile not supported: ignored" << endl;
|
cerr << "Warning: RSP vFile not supported: ignored" << endl;
|
pkt->packStr ("");
|
pkt->packStr ("");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 ==
|
else if (0 == strncmp ("vFlashErase:", pkt->data, strlen ("vFlashErase:")))
|
strncmp("vFlashErase:", pkt->data, strlen("vFlashErase:"))) {
|
{
|
|
// For now we don't support this.
|
// For now we don't support this.
|
cerr << "Warning: RSP vFlashErase not supported: ignored" << endl;
|
cerr << "Warning: RSP vFlashErase not supported: ignored" <<
|
|
endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 ==
|
else if (0 == strncmp ("vFlashWrite:", pkt->data, strlen ("vFlashWrite:")))
|
strncmp("vFlashWrite:", pkt->data, strlen("vFlashWrite:"))) {
|
{
|
|
// For now we don't support this.
|
// For now we don't support this.
|
cerr << "Warning: RSP vFlashWrite not supported: ignored" << endl;
|
cerr << "Warning: RSP vFlashWrite not supported: ignored" <<
|
|
endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 == strcmp("vFlashDone", pkt->data)) {
|
else if (0 == strcmp ("vFlashDone", pkt->data))
|
|
{
|
|
// For now we don't support this.
|
// For now we don't support this.
|
cerr << "Warning: RSP vFlashDone not supported: ignored" << endl;;
|
cerr << "Warning: RSP vFlashDone not supported: ignored" <<
|
|
endl;;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
} else if (0 == strncmp("vRun;", pkt->data, strlen("vRun;"))) {
|
else if (0 == strncmp ("vRun;", pkt->data, strlen ("vRun;")))
|
|
{
|
|
// We shouldn't be given any args, but check for this
|
// We shouldn't be given any args, but check for this
|
if (pkt->getLen () > strlen ("vRun;"))
|
if (pkt->getLen() > strlen("vRun;")) {
|
{
|
|
cerr << "Warning: Unexpected arguments to RSP vRun "
|
cerr << "Warning: Unexpected arguments to RSP vRun "
|
"command: ignored" << endl;
|
"command: ignored" << endl;
|
}
|
}
|
|
|
// Restart the current program. However unlike a "R" packet, "vRun"
|
// Restart the current program. However unlike a "R" packet, "vRun"
|
// should behave as though it has just stopped. We use signal 5 (TRAP).
|
// should behave as though it has just stopped. We use signal 5 (TRAP).
|
rspRestart ();
|
rspRestart ();
|
pkt->packStr ("S05");
|
pkt->packStr ("S05");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
}
|
} else {
|
else
|
|
{
|
|
cerr << "Warning: Unknown RSP 'v' packet type " << pkt->data
|
cerr << "Warning: Unknown RSP 'v' packet type " << pkt->data
|
<< ": ignored" << endl;
|
<< ": ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
} // rspVpkt ()
|
} // rspVpkt ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP write memory (binary) request
|
//! Handle a RSP write memory (binary) request
|
|
|
//! Syntax is:
|
//! Syntax is:
|
|
|
Line 1427... |
Line 1294... |
//! The length given is the number of bytes to be written. The data buffer has
|
//! The length given is the number of bytes to be written. The data buffer has
|
//! already been unescaped, so will hold this number of bytes.
|
//! already been unescaped, so will hold this number of bytes.
|
|
|
//! The data is in model-endian format, so no transformation is needed.
|
//! The data is in model-endian format, so no transformation is needed.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspWriteMemBin()
|
GdbServerSC::rspWriteMemBin ()
|
|
{
|
{
|
uint32_t addr; // Where to write the memory
|
uint32_t addr; // Where to write the memory
|
int len; // Number of bytes to write
|
int len; // Number of bytes to write
|
|
|
if (2 != sscanf (pkt->data, "X%x,%x:", &addr, &len))
|
if (2 != sscanf(pkt->data, "X%x,%x:", &addr, &len)) {
|
{
|
cerr <<
|
cerr << "Warning: Failed to recognize RSP write memory command: %s"
|
"Warning: Failed to recognize RSP write memory command: %s"
|
<< pkt->data << endl;
|
<< pkt->data << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Find the start of the data and "unescape" it. Bindat must be unsigned, or
|
// Find the start of the data and "unescape" it. Bindat must be unsigned, or
|
// all sorts of horrible sign extensions will happen when val is computed
|
// all sorts of horrible sign extensions will happen when val is computed
|
// below!
|
// below!
|
uint8_t *bindat = (uint8_t *)(memchr (pkt->data, ':',
|
uint8_t *bindat = (uint8_t *)(memchr (pkt->data, ':',
|
pkt->getBufSize ())) + 1;
|
pkt->getBufSize ())) + 1;
|
int off = (char *)bindat - pkt->data;
|
int off = (char *)bindat - pkt->data;
|
int newLen = Utils::rspUnescape ((char *)bindat, pkt->getLen () - off);
|
int newLen = Utils::rspUnescape ((char *)bindat, pkt->getLen () - off);
|
|
|
// Sanity check
|
// Sanity check
|
if (newLen != len)
|
if (newLen != len) {
|
{
|
|
int minLen = len < newLen ? len : newLen;
|
int minLen = len < newLen ? len : newLen;
|
|
|
cerr << "Warning: Write of " << len << " bytes requested, but "
|
cerr << "Warning: Write of " << len << " bytes requested, but "
|
<< newLen << " bytes supplied. " << minLen << " will be written"
|
<< newLen << " bytes supplied. " << minLen <<
|
<< endl;
|
" will be written" << endl;
|
len = minLen;
|
len = minLen;
|
}
|
}
|
|
|
// Write the bytes to memory. More efficent to do this in 32-bit chunks
|
// Write the bytes to memory. More efficent to do this in 32-bit chunks
|
int startBytes = addr & 0x3;
|
int startBytes = addr & 0x3;
|
int endBytes = (addr + len) & 0x3;
|
int endBytes = (addr + len) & 0x3;
|
|
|
// First partial word. Access bindat in an endian independent fashion.
|
// First partial word. Access bindat in an endian independent fashion.
|
for (off = 0 ; off < startBytes ; off++)
|
for (off = 0; off < startBytes; off++) {
|
{
|
if (!debugUnit->writeMem8(addr + off, bindat[off])) {
|
if (!debugUnit->writeMem8 (addr + off, bindat[off]))
|
|
{
|
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
// The bulk as words. Convert to model endian before writing.
|
// The bulk as words. Convert to model endian before writing.
|
for (off = startBytes; off < len; off += 4)
|
for (off = startBytes; off < len; off += 4) {
|
{
|
|
uint32_t val = *((uint32_t *)(&(bindat[off])));
|
uint32_t val = *((uint32_t *)(&(bindat[off])));
|
|
|
if (!debugUnit->writeMem32 (addr + off, Utils::htotl (val)))
|
if (!debugUnit->writeMem32(addr + off, Utils::htotl(val))) {
|
{
|
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
|
|
// Last partial word. Access bindat in an endian independent fashion.
|
// Last partial word. Access bindat in an endian independent fashion.
|
for (off = len - endBytes; off < len ; off++)
|
for (off = len - endBytes; off < len; off++) {
|
{
|
|
uint32_t base = (addr + len) & 0xfffffffc;
|
uint32_t base = (addr + len) & 0xfffffffc;
|
|
|
if (!debugUnit->writeMem8 (base + off, bindat[off]))
|
if (!debugUnit->writeMem8(base + off, bindat[off])) {
|
{
|
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
}
|
}
|
Line 1507... |
Line 1364... |
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
|
|
} // rspWriteMemBin ()
|
} // rspWriteMemBin ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Handle a RSP remove breakpoint or matchpoint request
|
//! Handle a RSP remove breakpoint or matchpoint request
|
|
|
//! For now only memory breakpoints are implemented, which are implemented by
|
//! For now only memory breakpoints are implemented, which are implemented by
|
//! substituting a breakpoint at the specified address. The implementation must
|
//! substituting a breakpoint at the specified address. The implementation must
|
//! cope with the possibility of duplicate packets.
|
//! cope with the possibility of duplicate packets.
|
|
|
//! @todo This doesn't work with icache/immu yet
|
//! @todo This doesn't work with icache/immu yet
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::rspRemoveMatchpoint()
|
GdbServerSC::rspRemoveMatchpoint ()
|
|
{
|
{
|
MpType type; // What sort of matchpoint
|
MpType type; // What sort of matchpoint
|
uint32_t addr; // Address specified
|
uint32_t addr; // Address specified
|
uint32_t instr; // Instruction value found
|
uint32_t instr; // Instruction value found
|
int len; // Matchpoint length (not used)
|
int len; // Matchpoint length (not used)
|
|
|
// Break out the instruction
|
// Break out the instruction
|
if (3 != sscanf (pkt->data, "z%1d,%lx,%1d", (int *)&type, &addr, &len))
|
if (3 != sscanf(pkt->data, "z%1d,%lx,%1d", (int *)&type, &addr, &len)) {
|
{
|
|
cerr << "Warning: RSP matchpoint deletion request not "
|
cerr << "Warning: RSP matchpoint deletion request not "
|
<< "recognized: ignored" << endl;
|
<< "recognized: ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Sanity check that the length is 4
|
// Sanity check that the length is 4
|
if (4 != len)
|
if (4 != len) {
|
{
|
|
cerr << "Warning: RSP matchpoint deletion length " << len
|
cerr << "Warning: RSP matchpoint deletion length " << len
|
<< "not valid: 4 assumed" << endl;
|
<< "not valid: 4 assumed" << endl;
|
len = 4;
|
len = 4;
|
}
|
}
|
|
|
// Sort out the type of matchpoint
|
// Sort out the type of matchpoint
|
switch (type)
|
switch (type) {
|
{
|
|
case BP_MEMORY:
|
case BP_MEMORY:
|
// Memory breakpoint - replace the original instruction.
|
// Memory breakpoint - replace the original instruction.
|
if (mpHash->remove (type, addr, &instr))
|
if (mpHash->remove(type, addr, &instr)) {
|
{
|
|
//cerr << "rspRemoveMatchpoint at 0x" << hex << addr << " restoring instruction: 0x" << hex << instr <<endl;
|
//cerr << "rspRemoveMatchpoint at 0x" << hex << addr << " restoring instruction: 0x" << hex << instr <<endl;
|
debugUnit->writeMem32 (addr, instr);
|
debugUnit->writeMem32 (addr, instr);
|
}
|
}
|
|
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
Line 1564... |
Line 1413... |
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off=0;off<8;off++)
|
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x23)) &&
|
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x23)) &&
|
(debugUnit->readSpr (SPR_DVR0+off) == addr))
|
(debugUnit->readSpr (SPR_DVR0+off) == addr))
|
break;
|
break;
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
// Clear DCR's CT and DVR, WGB bit
|
// Clear DCR's CT and DVR, WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) & ~((1 << off)
|
|
<<
|
|
SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
|
|
case WP_WRITE:
|
case WP_WRITE:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off = 0; off < 8; off++) {
|
{
|
if ((debugUnit->readSpr(SPR_DCR0 + off) ==
|
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x63)) &&
|
(0x63))
|
(debugUnit->readSpr (SPR_DVR0+off) == addr))
|
&& (debugUnit->readSpr(SPR_DVR0 + off) ==
|
|
addr))
|
break;
|
break;
|
}
|
}
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Clear DCR's CT and DVR, WGB bit
|
// Clear DCR's CT and DVR, WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) &
|
|
~((1 << off) <<
|
|
SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
case WP_READ:
|
case WP_READ:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off = 0; off < 8; off++) {
|
{
|
if ((debugUnit->readSpr(SPR_DCR0 + off) ==
|
if ((debugUnit->readSpr (SPR_DCR0+off) == (0x43)) &&
|
(0x43))
|
(debugUnit->readSpr (SPR_DVR0+off) == addr))
|
&& (debugUnit->readSpr(SPR_DVR0 + off) ==
|
|
addr))
|
break;
|
break;
|
}
|
}
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Clear DCR's CT and DVR, WGB bit
|
// Clear DCR's CT and DVR, WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) &
|
|
~((1 << off) <<
|
|
SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
case WP_ACCESS:
|
case WP_ACCESS:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off = 0; off < 8; off++) {
|
{
|
|
//printf("WP_ACCESS remove check off=%d DCR=0x%.8x DVR=0x%.8x\n",
|
//printf("WP_ACCESS remove check off=%d DCR=0x%.8x DVR=0x%.8x\n",
|
//off,debugUnit->readSpr (SPR_DCR0+off),debugUnit->readSpr (SPR_DVR0+off));
|
//off,debugUnit->readSpr (SPR_DCR0+off),debugUnit->readSpr (SPR_DVR0+off));
|
if ((debugUnit->readSpr (SPR_DCR0+off) == (0xc3)) &&
|
if ((debugUnit->readSpr(SPR_DCR0 + off) ==
|
(debugUnit->readSpr (SPR_DVR0+off) == addr))
|
(0xc3))
|
|
&& (debugUnit->readSpr(SPR_DVR0 + off) ==
|
|
addr))
|
break;
|
break;
|
}
|
}
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
//printf("rspRemoveWatchpoint: WP_ACCESS remove ERROR, regpair %d for 0x%.8x\n",off, addr);
|
//printf("rspRemoveWatchpoint: WP_ACCESS remove ERROR, regpair %d for 0x%.8x\n",off, addr);
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
pkt->packStr ("E02"); // Failed ot find breakpoint
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
//printf("rspRemoveWatchpoint: WP_ACCESS remove, regpair %d for 0x%.8x\n",off, addr);
|
//printf("rspRemoveWatchpoint: WP_ACCESS remove, regpair %d for 0x%.8x\n",off, addr);
|
|
|
// Clear DCR's CT and DVR, WGB bit
|
// Clear DCR's CT and DVR, WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DCR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DVR0+off,0);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2) & ~((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) &
|
|
~((1 << off) <<
|
|
SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
default:
|
default:
|
Line 1665... |
Line 1523... |
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
} // rspRemoveMatchpoint ()
|
} // rspRemoveMatchpoint ()
|
|
|
|
|
//---------------------------------------------------------------------------*/
|
//---------------------------------------------------------------------------*/
|
//! Handle a RSP insert breakpoint or matchpoint request
|
//! Handle a RSP insert breakpoint or matchpoint request
|
|
|
//! For now only memory breakpoints are implemented, which are implemented by
|
//! For now only memory breakpoints are implemented, which are implemented by
|
//! substituting a breakpoint at the specified address. The implementation must
|
//! substituting a breakpoint at the specified address. The implementation must
|
//! cope with the possibility of duplicate packets.
|
//! cope with the possibility of duplicate packets.
|
|
|
//! @todo This doesn't work with icache/immu yet
|
//! @todo This doesn't work with icache/immu yet
|
//---------------------------------------------------------------------------*/
|
//---------------------------------------------------------------------------*/
|
void
|
void GdbServerSC::rspInsertMatchpoint()
|
GdbServerSC::rspInsertMatchpoint ()
|
|
{
|
{
|
MpType type; // What sort of matchpoint
|
MpType type; // What sort of matchpoint
|
uint32_t addr; // Address specified
|
uint32_t addr; // Address specified
|
int len; // Matchpoint length (not used)
|
int len; // Matchpoint length (not used)
|
|
|
// Break out the instruction
|
// Break out the instruction
|
if (3 != sscanf (pkt->data, "Z%1d,%lx,%1d", (int *)&type, &addr, &len))
|
if (3 != sscanf(pkt->data, "Z%1d,%lx,%1d", (int *)&type, &addr, &len)) {
|
{
|
|
cerr << "Warning: RSP matchpoint insertion request not "
|
cerr << "Warning: RSP matchpoint insertion request not "
|
<< "recognized: ignored" << endl;
|
<< "recognized: ignored" << endl;
|
pkt->packStr ("E01");
|
pkt->packStr ("E01");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
// Sanity check that the length is 4
|
// Sanity check that the length is 4
|
if (4 != len)
|
if (4 != len) {
|
{
|
|
cerr << "Warning: RSP matchpoint insertion length " << len
|
cerr << "Warning: RSP matchpoint insertion length " << len
|
<< "not valid: 4 assumed" << endl;
|
<< "not valid: 4 assumed" << endl;
|
len = 4;
|
len = 4;
|
}
|
}
|
|
|
// Sort out the type of matchpoint
|
// Sort out the type of matchpoint
|
switch (type)
|
switch (type) {
|
{
|
|
case BP_MEMORY:
|
case BP_MEMORY:
|
// Memory breakpoint - substitute a TRAP instruction
|
// Memory breakpoint - substitute a TRAP instruction
|
mpHash->add (type, addr, debugUnit->readMem32 (addr));
|
mpHash->add (type, addr, debugUnit->readMem32 (addr));
|
debugUnit->writeMem32 (addr, OR1K_TRAP_INSTR);
|
debugUnit->writeMem32 (addr, OR1K_TRAP_INSTR);
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
Line 1715... |
Line 1566... |
|
|
case BP_HARDWARE:
|
case BP_HARDWARE:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off=0;off<8;off++)
|
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK))
|
if (!
|
|
(debugUnit->readSpr(SPR_DCR0 + off) &
|
|
SPR_DCR_CT_MASK))
|
break;
|
break;
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr (""); // No room
|
pkt->packStr (""); // No room
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
// CC = equal, CT = Instruction fetch EA, set WGB bit
|
// CC = equal, CT = Instruction fetch EA, set WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0x22);
|
debugUnit->writeSpr (SPR_DCR0+off,0x22);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) |
|
|
((1 << off) << SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
case WP_WRITE:
|
case WP_WRITE:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off=0;off<8;off++)
|
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK))
|
if (!
|
|
(debugUnit->readSpr(SPR_DCR0 + off) &
|
|
SPR_DCR_CT_MASK))
|
break;
|
break;
|
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr);
|
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr);
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr (""); // No room
|
pkt->packStr (""); // No room
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
// CC = equal, CT = Store EA, set WGB bit
|
// CC = equal, CT = Store EA, set WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0x62);
|
debugUnit->writeSpr (SPR_DCR0+off,0x62);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) |
|
|
((1 << off) << SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
case WP_READ:
|
case WP_READ:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off=0;off<8;off++)
|
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK))
|
if (!
|
|
(debugUnit->readSpr(SPR_DCR0 + off) &
|
|
SPR_DCR_CT_MASK))
|
break;
|
break;
|
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr);
|
//printf("rspInsertWatchpoint: WP_WRITE, regpair %d for 0x%.8x\n",off, addr);
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr (""); // No room
|
pkt->packStr (""); // No room
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
// CC = equal, CT = Load EA, set WGB bit
|
// CC = equal, CT = Load EA, set WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0x42);
|
debugUnit->writeSpr (SPR_DCR0+off,0x42);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) |
|
|
((1 << off) << SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
Line 1784... |
Line 1644... |
|
|
case WP_ACCESS:
|
case WP_ACCESS:
|
{
|
{
|
int off;
|
int off;
|
for (off=0;off<8;off++)
|
for (off=0;off<8;off++)
|
if (!(debugUnit->readSpr (SPR_DCR0+off) & SPR_DCR_CT_MASK))
|
if (!
|
|
(debugUnit->readSpr(SPR_DCR0 + off) &
|
|
SPR_DCR_CT_MASK))
|
break;
|
break;
|
//printf("rspInsertWatchpoint: WP_ACCESS, regpair %d for 0x%.8x\n",off, addr);
|
//printf("rspInsertWatchpoint: WP_ACCESS, regpair %d for 0x%.8x\n",off, addr);
|
if (off > 7)
|
if (off > 7) {
|
{
|
|
pkt->packStr (""); // No room
|
pkt->packStr (""); // No room
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
// CC = equal, CT = Load/Store EA, set WGB bit
|
// CC = equal, CT = Load/Store EA, set WGB bit
|
debugUnit->writeSpr (SPR_DCR0+off,0xc2);
|
debugUnit->writeSpr (SPR_DCR0+off,0xc2);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DVR0+off,addr);
|
debugUnit->writeSpr (SPR_DMR2,debugUnit->readSpr (SPR_DMR2)|((1<<off)<<SPR_DMR2_WGB_SHIFT));
|
debugUnit->writeSpr(SPR_DMR2,
|
|
debugUnit->readSpr(SPR_DMR2) |
|
|
((1 << off) << SPR_DMR2_WGB_SHIFT));
|
pkt->packStr ("OK");
|
pkt->packStr ("OK");
|
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
|
|
Line 1811... |
Line 1674... |
rsp->putPkt (pkt);
|
rsp->putPkt (pkt);
|
return;
|
return;
|
}
|
}
|
} // rspInsertMatchpoint ()
|
} // rspInsertMatchpoint ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Read the value of the Next Program Counter (a SPR)
|
//! Read the value of the Next Program Counter (a SPR)
|
|
|
//! A convenience routine.
|
//! A convenience routine.
|
|
|
Line 1828... |
Line 1690... |
//! refilled). Fortunately SPR cacheing in the debug unit silently solves this
|
//! refilled). Fortunately SPR cacheing in the debug unit silently solves this
|
//! for us.
|
//! for us.
|
|
|
//! @return The value of the NPC
|
//! @return The value of the NPC
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
uint32_t
|
uint32_t GdbServerSC::readNpc()
|
GdbServerSC::readNpc ()
|
|
{
|
{
|
return debugUnit->readSpr (SPR_NPC);
|
return debugUnit->readSpr (SPR_NPC);
|
|
|
} // readNpc ()
|
} // readNpc ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Write the value of the Next Program Counter (a SPR)
|
//! Write the value of the Next Program Counter (a SPR)
|
|
|
//! A convenience function.
|
//! A convenience function.
|
|
|
Line 1856... |
Line 1716... |
//! or not it is cached) if it has not changed. So unlike all other SPRs we
|
//! or not it is cached) if it has not changed. So unlike all other SPRs we
|
//! always read it first before writing.
|
//! always read it first before writing.
|
|
|
//! @param[in] The address to write into the NPC
|
//! @param[in] The address to write into the NPC
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::writeNpc(uint32_t addr)
|
GdbServerSC::writeNpc (uint32_t addr)
|
|
{
|
|
if (addr != readNpc())
|
|
{
|
{
|
|
if (addr != readNpc()) {
|
debugUnit->writeSpr (SPR_NPC, addr);
|
debugUnit->writeSpr (SPR_NPC, addr);
|
}
|
}
|
} // writeNpc ()
|
} // writeNpc ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Read the value of an OpenRISC 1000 General Purpose Register
|
//! Read the value of an OpenRISC 1000 General Purpose Register
|
|
|
//! A convenience function. This is just a wrapper for reading a SPR, since
|
//! A convenience function. This is just a wrapper for reading a SPR, since
|
//! the GPR's are mapped into SPR space
|
//! the GPR's are mapped into SPR space
|
|
|
//! @param[in] regNum The GPR to read
|
//! @param[in] regNum The GPR to read
|
|
|
//! @return The value of the GPR
|
//! @return The value of the GPR
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
uint32_t
|
uint32_t GdbServerSC::readGpr(int regNum)
|
GdbServerSC::readGpr (int regNum)
|
|
{
|
{
|
return debugUnit->readSpr (SPR_GPR0 + regNum);
|
return debugUnit->readSpr (SPR_GPR0 + regNum);
|
|
|
} // readGpr ()
|
} // readGpr ()
|
|
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//! Write the value of an OpenRISC 1000 General Purpose Register
|
//! Write the value of an OpenRISC 1000 General Purpose Register
|
|
|
//! A convenience function. This is just a wrapper for writing a SPR, since
|
//! A convenience function. This is just a wrapper for writing a SPR, since
|
//! the GPR's are mapped into SPR space
|
//! the GPR's are mapped into SPR space
|
|
|
//! @param[in] regNum The GPR to read
|
//! @param[in] regNum The GPR to read
|
|
|
//! @return The value of the GPR
|
//! @return The value of the GPR
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
void
|
void GdbServerSC::writeGpr(int regNum, uint32_t value)
|
GdbServerSC::writeGpr (int regNum,
|
|
uint32_t value)
|
|
{
|
{
|
debugUnit->writeSpr (SPR_GPR0 + regNum, value);
|
debugUnit->writeSpr (SPR_GPR0 + regNum, value);
|
|
|
} // writeGpr ()
|
} // writeGpr ()
|
|
|
Line 1912... |
Line 1765... |
//! more appropriately.
|
//! more appropriately.
|
//! Read from the pipe should be NON-blocking.
|
//! Read from the pipe should be NON-blocking.
|
|
|
//! @return false if nothing received, else true
|
//! @return false if nothing received, else true
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
bool
|
bool GdbServerSC::checkMonitorPipe()
|
GdbServerSC::checkMonitorPipe ()
|
|
{
|
{
|
char readChar;
|
char readChar;
|
int n = read(monitor_to_gdb_pipe[0][0], &readChar, sizeof(char));
|
int n = read(monitor_to_gdb_pipe[0][0], &readChar, sizeof(char));
|
if (!( ((n < 0) && (errno == EAGAIN)) || (n==0) ) && !targetStopped)
|
if (!(((n < 0) && (errno == EAGAIN)) || (n == 0)) && !targetStopped) {
|
{
|
|
debugUnit->stall ();
|
debugUnit->stall ();
|
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE
|
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE
|
rsp_sigval = TARGET_SIGNAL_NONE;
|
rsp_sigval = TARGET_SIGNAL_NONE;
|
rspReportException();
|
rspReportException();
|
targetStopped = true; // Processor now not running
|
targetStopped = true; // Processor now not running
|