OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/or_debug_proxy
    from Rev 431 to Rev 497
    Reverse comparison

Rev 431 → Rev 497

/includes/gdb.h
60,6 → 60,8
 
extern int err;
 
extern int kernel_debug;
 
/* All JTAG chains. */
enum jtag_chains
{
/ChangeLog
1,3 → 1,17
2011-03-07 Julius Baxter, ORSoC AB <julius@orsoc.se>
* src/or_debug_proxy.c: Ran indent on code to neaten.
Added -k option to enable kernel debugging option which remaps 0xc0
high address to 0x00.
* include/gdb.h:(kernel_debug): Declared as extern int.
* src/gdb.c: Ran indent on code to neaten.
(kernel_debug): Added, initialise to 0.
<gdb_write_byte>: Also check kernel_debug with IS_VM_ADDR.
<gdb_read_byte>: Ditto.
<gdb_write_reg>: Ditto.
<gdb_read_reg>: Ditto.
<gdb_read_block>: Ditto.
<gdb_write_block>: Ditto.
 
2010-11-23 Julius Baxter <julius@opencores.org>
* src/gdb.c <rsp_query>: qTStatus packet now returns empty packet.
/src/or_debug_proxy.c
61,7 → 61,7
#include "win_FTCJTAG_ptrs.h"
#else
#include <signal.h>
void catch_sigint(int sig_num); // First param must be "int"
void catch_sigint(int sig_num); // First param must be "int"
#endif
 
#include "gdb.h"
77,13 → 77,13
#define ENDPOINT_TARGET_USB 1
#define ENDPOINT_TARGET_OTHER 2
 
static int endpoint_target; // Value to hold targeted endpoint
static int endpoint_target; // Value to hold targeted endpoint
 
#define GDB_PROTOCOL_JTAG 1
#define GDB_PROTOCOL_RSP 2
#define GDB_PROTOCOL_NONE 3
 
int err; // Global error value
int err; // Global error value
 
/* Currently selected scan chain - just to prevent unnecessary transfers. */
int current_chain = -1;
91,253 → 91,285
/* The chain that should be currently selected. */
int dbg_chain = -1;
 
int main(int argc, char *argv[]) {
int main(int argc, char *argv[])
{
 
char *s;
int gdb_protocol = GDB_PROTOCOL_NONE;
endpoint_target = ENDPOINT_TARGET_NONE;
int inp_arg = 1;
char *s;
int gdb_protocol = GDB_PROTOCOL_NONE;
endpoint_target = ENDPOINT_TARGET_NONE;
int inp_arg = 1;
 
// Check we were compiled with at least one endpoint enabled
// Check we were compiled with at least one endpoint enabled
#ifndef USB_ENDPOINT_ENABLED
printf("No endpoints enabled.\nRecompile the proxy with at least one endpoint enabled\n");
exit(0);
printf
("No endpoints enabled.\nRecompile the proxy with at least one endpoint enabled\n");
exit(0);
#endif
 
// init our global error number
err = DBG_ERR_OK;
// init our global error number
err = DBG_ERR_OK;
 
// Parse input options
if (argc < 3)
{
print_usage();
exit(1);
}
// Parse input options
if (argc < 3) {
print_usage();
exit(1);
}
 
err = DBG_ERR_OK;
srand(getpid());
err = DBG_ERR_OK;
srand(getpid());
 
// Parse through the input, check what we've been given
// Parse through the input, check what we've been given
 
while ( argv[inp_arg] != NULL )
{
if(strcmp(argv[inp_arg], "-r") == 0)
{
gdb_protocol = GDB_PROTOCOL_RSP;
endpoint_target = ENDPOINT_TARGET_USB;
while (argv[inp_arg] != NULL) {
if (strcmp(argv[inp_arg], "-r") == 0) {
gdb_protocol = GDB_PROTOCOL_RSP;
endpoint_target = ENDPOINT_TARGET_USB;
} else if (strcmp(argv[inp_arg], "-o") == 0) {
gdb_protocol = GDB_PROTOCOL_RSP;
endpoint_target = ENDPOINT_TARGET_OTHER;
} else if (strcmp(argv[inp_arg], "-k") == 0) {
kernel_debug = 1;
} else {
serverPort = strtol(argv[2], &s, 10);
}
 
inp_arg++;
}
else if(strcmp(argv[inp_arg], "-o") == 0)
{
gdb_protocol = GDB_PROTOCOL_RSP;
endpoint_target = ENDPOINT_TARGET_OTHER;
 
if (endpoint_target == ENDPOINT_TARGET_NONE ||
gdb_protocol == GDB_PROTOCOL_NONE ||
serverPort > 65535 || *s != '\0') {
print_usage();
exit(1);
}
else
{
serverPort = strtol(argv[2],&s,10);
#ifdef CYGWIN_COMPILE
// Load the FTCJTAG DLL function pointers
if (getFTDIJTAGFunctions() < 0) {
exit(-1);
}
inp_arg++;
}
 
if(endpoint_target == ENDPOINT_TARGET_NONE || gdb_protocol == GDB_PROTOCOL_NONE || serverPort > 65535 || *s != '\0')
{
print_usage();
exit(1);
}
 
#ifdef CYGWIN_COMPILE
// Load the FTCJTAG DLL function pointers
if (getFTDIJTAGFunctions() < 0){
exit(-1);
}
#endif
 
#ifndef CYGWIN_COMPILE
// Install a signal handler to exit gracefully
// when we receive a sigint
signal(SIGINT, catch_sigint);
// Install a signal handler to exit gracefully
// when we receive a sigint
signal(SIGINT, catch_sigint);
#endif
/* Initialise connection to our OR1k system */
current_chain = -1;
 
/* Initialise connection to our OR1k system */
current_chain = -1;
#ifdef USB_ENDPOINT_ENABLED
/* USB Endpoint */
if (endpoint_target == ENDPOINT_TARGET_USB)
{
printf("\nConnecting to OR1k via USB debug cable\n\n");
if ((err = usb_dbg_reset())) goto JtagIfError;
dbg_test(); // Perform some tests
}
/* USB Endpoint */
if (endpoint_target == ENDPOINT_TARGET_USB) {
printf("\nConnecting to OR1k via USB debug cable\n\n");
if ((err = usb_dbg_reset()))
goto JtagIfError;
dbg_test(); // Perform some tests
}
#endif
/* We have a connection to the target system. Now establish server connection. */
if(gdb_protocol == GDB_PROTOCOL_RSP)
{ // Connect to RSP server
/* RSP always starts stalled as though we have just reset the processor. */
// rsp_exception (EXCEPT_TRAP);
handle_rsp ();
// if((server_fd = GetServerSocket("or1ksim","tcp", serverPort))) {
}else {
fprintf(stderr,"Cannot start RSP Proxy server on port %d\n", serverPort);
exit(-1);
}
 
/* We have a connection to the target system. Now establish server
connection. */
if (gdb_protocol == GDB_PROTOCOL_RSP) { // Connect to RSP server
/* RSP always starts stalled as though we have just reset the
processor. */
// rsp_exception (EXCEPT_TRAP);
handle_rsp();
} else {
fprintf(stderr, "Cannot start RSP Proxy server on port %d\n",
serverPort);
exit(-1);
}
 
JtagIfError:
fprintf(stderr,"Connection via USB debug cable failed (err = %d).\nPlease ensure the device is attached and correctly installed\n\n", err);
exit(-1);
return 0;
fprintf(stderr,
"Connection via USB debug cable failed (err = %d).\nPlease ensure the device is attached and correctly installed\n\n",
err);
exit(-1);
return 0;
}
 
 
int dbg_reset()
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_reset();
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_reset();
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
void dbg_test() {
void dbg_test()
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) usb_dbg_test();
if (endpoint_target == ENDPOINT_TARGET_USB)
usb_dbg_test();
#endif
}
 
/* Set TAP instruction register */
int dbg_set_tap_ir(uint32_t ir) {
int dbg_set_tap_ir(uint32_t ir)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) usb_set_tap_ir(ir);
if (endpoint_target == ENDPOINT_TARGET_USB)
usb_set_tap_ir(ir);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* Sets scan chain. */
int dbg_set_chain(uint32_t chain) {
int dbg_set_chain(uint32_t chain)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_set_chain(chain);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_set_chain(chain);
#endif
return DBG_ERR_INVALID_ENDPOINT;
}
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* sends out a command with 32bit address and 16bit length, if len >= 0 */
int dbg_command(uint32_t type, uint32_t adr, uint32_t len) {
// This is never called by any of the VPI functions, so only USB endpoint
int dbg_command(uint32_t type, uint32_t adr, uint32_t len)
{
// This is never called by any of the VPI functions, so only USB
// endpoint
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_command(type,adr,len);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_command(type, adr, len);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* writes a ctrl reg */
int dbg_ctrl(uint32_t reset, uint32_t stall) {
int dbg_ctrl(uint32_t reset, uint32_t stall)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_ctrl(reset, stall);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_ctrl(reset, stall);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* reads control register */
int dbg_ctrl_read(uint32_t *reset, uint32_t *stall) {
int dbg_ctrl_read(uint32_t * reset, uint32_t * stall)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_ctrl_read(reset, stall);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_ctrl_read(reset, stall);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* issues a burst read/write */
int dbg_go(unsigned char *data, uint16_t len, uint32_t read) {
// Only USB endpouint32_t option here
int dbg_go(unsigned char *data, uint16_t len, uint32_t read)
{
// Only USB endpouint32_t option here
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_go(data, len, read);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_go(data, len, read);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* read a byte from wishbone */
int dbg_wb_read8(uint32_t adr, uint8_t *data) {
int dbg_wb_read8(uint32_t adr, uint8_t * data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_read8(adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_read8(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
 
/* read a word from wishbone */
int dbg_wb_read32(uint32_t adr, uint32_t *data) {
int dbg_wb_read32(uint32_t adr, uint32_t * data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_read32(adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_read32(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* write a word to wishbone */
int dbg_wb_write8(uint32_t adr, uint8_t data) {
int dbg_wb_write8(uint32_t adr, uint8_t data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_write8( adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_write8(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* write a word to wishbone */
int dbg_wb_write32(uint32_t adr, uint32_t data) {
int dbg_wb_write32(uint32_t adr, uint32_t data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_write32( adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_write32(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* read a block from wishbone */
int dbg_wb_read_block32(uint32_t adr, uint32_t *data, uint32_t len) {
int dbg_wb_read_block32(uint32_t adr, uint32_t * data, uint32_t len)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_read_block32( adr, data, len);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_read_block32(adr, data, len);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* write a block to wishbone */
int dbg_wb_write_block32(uint32_t adr, uint32_t *data, uint32_t len) {
int dbg_wb_write_block32(uint32_t adr, uint32_t * data, uint32_t len)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_wb_write_block32( adr, data, len);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_wb_write_block32(adr, data, len);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* read a register from cpu */
int dbg_cpu0_read(uint32_t adr, uint32_t *data, uint32_t length) {
int dbg_cpu0_read(uint32_t adr, uint32_t * data, uint32_t length)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_cpu0_read( adr, data, length);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_cpu0_read(adr, data, length);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* write a cpu register */
int dbg_cpu0_write(uint32_t adr, uint32_t *data, uint32_t length) {
int dbg_cpu0_write(uint32_t adr, uint32_t * data, uint32_t length)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_cpu0_write( adr, data, length);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_cpu0_write(adr, data, length);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
/* write a cpu module register */
int dbg_cpu0_write_ctrl(uint32_t adr, unsigned char data) {
int dbg_cpu0_write_ctrl(uint32_t adr, unsigned char data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_cpu0_write_ctrl( adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_cpu0_write_ctrl(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
 
/* read a register from cpu module */
int dbg_cpu0_read_ctrl(uint32_t adr, unsigned char *data) {
int dbg_cpu0_read_ctrl(uint32_t adr, unsigned char *data)
{
#ifdef USB_ENDPOINT_ENABLED
if (endpoint_target == ENDPOINT_TARGET_USB) return usb_dbg_cpu0_read_ctrl( adr, data);
if (endpoint_target == ENDPOINT_TARGET_USB)
return usb_dbg_cpu0_read_ctrl(adr, data);
#endif
return DBG_ERR_INVALID_ENDPOINT;
return DBG_ERR_INVALID_ENDPOINT;
}
 
 
void test_sdram(void) {
void test_sdram(void)
{
return;
}
 
344,36 → 376,45
// Close down gracefully when we receive any kill signals
void catch_sigint(int sig_num)
{
// Close down any potentially open sockets and USB handles
if (server_fd) close(server_fd);
gdb_close();
// Close down any potentially open sockets and USB handles
if (server_fd)
close(server_fd);
gdb_close();
#ifdef USB_ENDPOINT_ENABLED
usb_close_device_handle();
usb_close_device_handle();
#endif
printf("\nInterrupt signal received. Closing down connections and exiting\n\n");
exit(0);
printf
("\nInterrupt signal received. Closing down connections and exiting\n\n");
exit(0);
}
 
void print_usage()
{
printf("Invalid or insufficient arguments\n");
printf("\n");
printf("OpenRISC GDB proxy server usage: or_debug_proxy -server_type port\n");
printf("\n");
printf("server_type:\n");
printf("\n");
printf("Usage: or_debug_proxy <SERVERTYPE> <PORT> <OPTIONS>\n");
printf("OpenRISC GDB Proxy Server\n");
printf("\n");
printf("\tServer Type:\n");
#ifdef USB_ENDPOINT_ENABLED
printf("\t-r Start a server using RSP, connection to hadware target via\n\t USB\n");
printf("\t-j Start a server using legacy OR remote JTAG protocol, to\n\t hardware target via USB\n");
printf
("\t-r\tStart a server using RSP, connection to hadware target via\n\t\tUSB\n");
printf
("\t-j\tStart a server using legacy OR remote JTAG protocol, to\n\t\thardware target via USB (DEPRECATED)\n");
printf("\n");
#endif
printf("\n");
printf("port:\n");
printf("\tAny free port within the usable range of 0 - 65535\n");
printf("\n");
printf("Example:\n");
printf("\tPort:\n");
printf("\t\tAny free port within the usable range of 0 - 65535\n");
printf("\n");
printf("\tOptions:\n");
printf
("\t-k\tAccesses to 0xC0000000 map to 0x0. Useful for kernel debugging.\n");
printf("\n");
printf("\tExample:\n");
#ifdef USB_ENDPOINT_ENABLED
printf("\tStart a GDB server on port 5555, using RSP, connecting to\n\thardware target via USB\n");
printf("\tor_debug_proxy -r 5555\n");
printf("\n");
printf
("\t\tStart a GDB server on port 50001, using RSP, connecting to\n\t\thardware target via USB:\n\n");
printf("\t\t./or_debug_proxy -r 50001\n");
printf("\n");
#endif
fflush (stdout);
fflush(stdout);
}
/src/gdb.c
43,7 → 43,6
// Implements GDB stub for OpenRISC debug proxy.
//
 
 
/*$$CHANGE HISTORY*/
/******************************************************************************/
/* */
51,9 → 50,9
/* */
/******************************************************************************/
 
// Date Version Description
// Date Version Description
//------------------------------------------------------------------------
// 081101 Imported code from "jp" project jb
// 081101 Imported code from "jp" project jb
// 090219 Adapted code from Jeremy Bennett's RSP server
// for the or1ksim project. rmb
// 090304 Finished RSP server code import, added extra
69,7 → 68,7
#ifdef CYGWIN_COMPILE
 
#else
// linux includes
// linux includes
#include <time.h>
#include <sched.h>
#endif
97,11 → 96,10
#include <errno.h>
#include <arpa/inet.h>
 
 
/*! Name of the Or1ksim RSP service */
#define OR1KSIM_RSP_SERVICE "or1ksim-rsp"
 
#include "gdb.h" /* partially copied from gdb/config/or1k */
#include "gdb.h" /* partially copied from gdb/config/or1k */
#include "or_debug_proxy.h"
 
#define MAX_GPRS (32)
113,9 → 111,9
#define NUM_REGS (MAX_GPRS + 3) /*!< Total GDB registers */
 
/* OR1k CPU registers address */
#define NPC_CPU_REG_ADD 0x10 /* Next PC */
#define SR_CPU_REG_ADD 0x11 /* Supervision Register */
#define PPC_CPU_REG_ADD 0x12 /* Previous PC */
#define NPC_CPU_REG_ADD 0x10 /* Next PC */
#define SR_CPU_REG_ADD 0x11 /* Supervision Register */
#define PPC_CPU_REG_ADD 0x12 /* Previous PC */
#define DMR1_CPU_REG_ADD ((6 << 11) + 16) /* Debug Mode Register 1 (DMR1) 0x3010 */
#define DMR2_CPU_REG_ADD ((6 << 11) + 17) /* Debug Mode Register 2 (DMR2) 0x3011 */
#define DSR_CPU_REG_ADD ((6 << 11) + 20) /* Debug Stop Register (DSR) 0x3014 */
141,9 → 139,9
/* Definition of special-purpose registers (SPRs). */
#define MAX_SPRS (0x10000)
 
#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/
#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */
#define SPR_DSR_TE 0x00002000 /* Trap exception */
#define SPR_DMR1_ST 0x00400000 /* Single-step trace */
#define SPR_DMR2_WGB 0x003ff000 /* Watchpoints generating breakpoint */
#define SPR_DSR_TE 0x00002000 /* Trap exception */
 
#define WORDSBIGENDIAN_N
 
166,22 → 164,21
 
// Changed to #defines from static const int's due to compile error
// DRR (Debug Reason Register) Bits
#define SPR_DRR_RSTE 0x00000001 //!< Reset
#define SPR_DRR_BUSEE 0x00000002 //!< Bus error
#define SPR_DRR_DPFE 0x00000004 //!< Data page fault
#define SPR_DRR_IPFE 0x00000008 //!< Insn page fault
#define SPR_DRR_TTE 0x00000010 //!< Tick timer
#define SPR_DRR_AE 0x00000020 //!< Alignment
#define SPR_DRR_IIE 0x00000040 //!< Illegal instruction
#define SPR_DRR_IE 0x00000080 //!< Interrupt
#define SPR_DRR_DME 0x00000100 //!< DTLB miss
#define SPR_DRR_IME 0x00000200 //!< ITLB miss
#define SPR_DRR_RE 0x00000400 //!< Range fault
#define SPR_DRR_SCE 0x00000800 //!< System call
#define SPR_DRR_FPE 0x00001000 //!< Floating point
#define SPR_DRR_TE 0x00002000 //!< Trap
#define SPR_DRR_RSTE 0x00000001 //!< Reset
#define SPR_DRR_BUSEE 0x00000002 //!< Bus error
#define SPR_DRR_DPFE 0x00000004 //!< Data page fault
#define SPR_DRR_IPFE 0x00000008 //!< Insn page fault
#define SPR_DRR_TTE 0x00000010 //!< Tick timer
#define SPR_DRR_AE 0x00000020 //!< Alignment
#define SPR_DRR_IIE 0x00000040 //!< Illegal instruction
#define SPR_DRR_IE 0x00000080 //!< Interrupt
#define SPR_DRR_DME 0x00000100 //!< DTLB miss
#define SPR_DRR_IME 0x00000200 //!< ITLB miss
#define SPR_DRR_RE 0x00000400 //!< Range fault
#define SPR_DRR_SCE 0x00000800 //!< System call
#define SPR_DRR_FPE 0x00001000 //!< Floating point
#define SPR_DRR_TE 0x00002000 //!< Trap
 
 
/*! Definition of GDB target signals. Data taken from the GDB 6.8
source. Only those we use defined here. The exact meaning of
signal number is defined by the header `include/gdb/signals.h'
188,22 → 185,21
in the GDB source code. For an explanation of what each signal
means, see target_signal_to_string.*/
enum target_signal {
TARGET_SIGNAL_NONE = 0,
TARGET_SIGNAL_INT = 2,
TARGET_SIGNAL_ILL = 4,
TARGET_SIGNAL_TRAP = 5,
TARGET_SIGNAL_FPE = 8,
TARGET_SIGNAL_BUS = 10,
TARGET_SIGNAL_SEGV = 11,
TARGET_SIGNAL_ALRM = 14,
TARGET_SIGNAL_USR2 = 31,
TARGET_SIGNAL_PWR = 32
TARGET_SIGNAL_NONE = 0,
TARGET_SIGNAL_INT = 2,
TARGET_SIGNAL_ILL = 4,
TARGET_SIGNAL_TRAP = 5,
TARGET_SIGNAL_FPE = 8,
TARGET_SIGNAL_BUS = 10,
TARGET_SIGNAL_SEGV = 11,
TARGET_SIGNAL_ALRM = 14,
TARGET_SIGNAL_USR2 = 31,
TARGET_SIGNAL_PWR = 32
};
 
/*! String to map hex digits to chars */
static const char hexchars[]="0123456789abcdef";
static const char hexchars[] = "0123456789abcdef";
 
 
//! Is the NPC cached?
 
//! Setting the NPC flushes the pipeline, so subsequent reads will return
213,15 → 209,16
//! cached value becomes invalid. So we must track the stall state, and if
//! appropriate cache the NPC.
enum stallStates {
STALLED,
UNSTALLED,
UNKNOWN
STALLED,
UNSTALLED,
UNKNOWN
} stallState;
 
int npcIsCached; //!< Is the NPC cached - should be bool
uint32_t npcCachedValue; //!< Cached value of the NPC
int npcIsCached; //!< Is the NPC cached - should be bool
uint32_t npcCachedValue; //!< Cached value of the NPC
 
/* OR32 Linux kernel debugging hacks */
int kernel_debug = 0; // Disabled by default. Enabled via command line.
/* If we're operating in virtual memory space, currently the standard VM base
is 0xc0000000, since the GDB we're currently using is bare-metal we will
do a translation of these VM addresses to their physical address - although
236,8 → 233,6
#define IS_VM_ADDR(adr) ((adr & OR32_LINUX_VM_MASK) == OR32_LINUX_VM_OFFSET)
 
 
 
 
/************************
JTAG Server Routines
************************/
254,116 → 249,114
 
/*! Data structure for RSP buffers. Can't be null terminated, since it may
include zero bytes */
struct rsp_buf
{
char data[GDB_BUF_MAX_TIMES_TWO];
int len;
struct rsp_buf {
char data[GDB_BUF_MAX_TIMES_TWO];
int len;
};
 
/*! Enumeration of different types of matchpoint. These have explicit values
matching the second digit of 'z' and 'Z' packets. */
enum mp_type {
BP_MEMORY = 0, // software-breakpoint Z0 break
BP_HARDWARE = 1, // hardware-breakpoint Z1 hbreak
WP_WRITE = 2, // write-watchpoint Z2 watch
WP_READ = 3, // read-watchpoint Z3 rwatch
WP_ACCESS = 4 // access-watchpoint Z4 awatch
};
BP_MEMORY = 0, // software-breakpoint Z0 break
BP_HARDWARE = 1, // hardware-breakpoint Z1 hbreak
WP_WRITE = 2, // write-watchpoint Z2 watch
WP_READ = 3, // read-watchpoint Z3 rwatch
WP_ACCESS = 4 // access-watchpoint Z4 awatch
};
 
/*! Data structure for a matchpoint hash table entry */
struct mp_entry
{
enum mp_type type; /*!< Type of matchpoint */
uint32_t addr; /*!< Address with the matchpoint */
uint32_t instr; /*!< Substituted instruction */
struct mp_entry *next; /*!< Next entry with this hash */
struct mp_entry {
enum mp_type type; /*!< Type of matchpoint */
uint32_t addr; /*!< Address with the matchpoint */
uint32_t instr; /*!< Substituted instruction */
struct mp_entry *next; /*!< Next entry with this hash */
};
 
/*! Central data for the RSP connection */
static struct
{
int client_waiting; /*!< Is client waiting a response? */
// Not used int proto_num; /*!< Number of the protocol used */
int client_fd; /*!< FD for talking to GDB */
int sigval; /*!< GDB signal for any exception */
uint32_t start_addr; /*!< Start of last run */
struct mp_entry *mp_hash[MP_HASH_SIZE]; /*!< Matchpoint hash table */
static struct {
int client_waiting; /*!< Is client waiting a response? */
// Not used int proto_num; /*!< Number of the protocol used */
int client_fd; /*!< FD for talking to GDB */
int sigval; /*!< GDB signal for any exception */
uint32_t start_addr; /*!< Start of last run */
struct mp_entry *mp_hash[MP_HASH_SIZE]; /*!< Matchpoint hash table */
} rsp;
 
/* Forward declarations of static functions */
static char *printTime(void);
static int gdb_read(void*, int);
static int gdb_write(void*, int);
static int gdb_read(void *, int);
static int gdb_write(void *, int);
static void rsp_interrupt();
static char rsp_peek();
static struct rsp_buf *get_packet (void);
static void rsp_init (void);
static void set_npc (uint32_t addr);
static struct rsp_buf *get_packet(void);
static void rsp_init(void);
static void set_npc(uint32_t addr);
static uint32_t get_npc();
static void rsp_check_for_exception();
static int check_for_exception_vector(uint32_t ppc);
static void rsp_exception (uint32_t except);
static int get_rsp_char (void);
static int hex (int c);
static void rsp_get_client (void);
static void rsp_client_request (void);
static void rsp_client_close (void);
static void client_close (char err);
static void put_str_packet (const char *str);
static void rsp_report_exception (void);
static void put_packet (struct rsp_buf *p_buf);
static void send_rsp_str (unsigned char *data, int len);
static void rsp_query (struct rsp_buf *p_buf);
static void rsp_vpkt (struct rsp_buf *p_buf);
static void rsp_step (struct rsp_buf *p_buf);
static void rsp_step_with_signal (struct rsp_buf *p_buf);
static void rsp_step_generic (uint32_t addr, uint32_t except);
static void rsp_continue (struct rsp_buf *p_buf);
static void rsp_continue_with_signal (struct rsp_buf *p_buf);
static void rsp_continue_generic (uint32_t addr, uint32_t except);
static void rsp_read_all_regs (void);
static void rsp_write_all_regs (struct rsp_buf *p_buf);
static void rsp_read_mem (struct rsp_buf *p_buf);
static void rsp_write_mem (struct rsp_buf *p_buf);
static void rsp_write_mem_bin (struct rsp_buf *p_buf);
static int rsp_unescape (char *data, int len);
static void rsp_read_reg (struct rsp_buf *p_buf);
static void rsp_write_reg (struct rsp_buf *p_buf);
static void mp_hash_init (void);
static void mp_hash_add (enum mp_type type, uint32_t addr, uint32_t instr);
static struct mp_entry * mp_hash_lookup (enum mp_type type, uint32_t addr);
static struct mp_entry * mp_hash_delete (enum mp_type type, uint32_t addr);
static void rsp_remove_matchpoint (struct rsp_buf *p_buf);
static void rsp_insert_matchpoint (struct rsp_buf *p_buf);
static void rsp_command (struct rsp_buf *p_buf);
static void rsp_set (struct rsp_buf *p_buf);
static void rsp_restart (void);
static void ascii2hex (char *dest,char *src);
static void hex2ascii (char *dest, char *src);
static uint32_t hex2reg (char *p_buf);
static void reg2hex (uint32_t val, char *p_buf);
static void swap_buf(char* p_buf, int len);
static void set_stall_state (int state);
static void reset_or1k (void);
static void rsp_exception(uint32_t except);
static int get_rsp_char(void);
static int hex(int c);
static void rsp_get_client(void);
static void rsp_client_request(void);
static void rsp_client_close(void);
static void client_close(char err);
static void put_str_packet(const char *str);
static void rsp_report_exception(void);
static void put_packet(struct rsp_buf *p_buf);
static void send_rsp_str(unsigned char *data, int len);
static void rsp_query(struct rsp_buf *p_buf);
static void rsp_vpkt(struct rsp_buf *p_buf);
static void rsp_step(struct rsp_buf *p_buf);
static void rsp_step_with_signal(struct rsp_buf *p_buf);
static void rsp_step_generic(uint32_t addr, uint32_t except);
static void rsp_continue(struct rsp_buf *p_buf);
static void rsp_continue_with_signal(struct rsp_buf *p_buf);
static void rsp_continue_generic(uint32_t addr, uint32_t except);
static void rsp_read_all_regs(void);
static void rsp_write_all_regs(struct rsp_buf *p_buf);
static void rsp_read_mem(struct rsp_buf *p_buf);
static void rsp_write_mem(struct rsp_buf *p_buf);
static void rsp_write_mem_bin(struct rsp_buf *p_buf);
static int rsp_unescape(char *data, int len);
static void rsp_read_reg(struct rsp_buf *p_buf);
static void rsp_write_reg(struct rsp_buf *p_buf);
static void mp_hash_init(void);
static void mp_hash_add(enum mp_type type, uint32_t addr, uint32_t instr);
static struct mp_entry *mp_hash_lookup(enum mp_type type, uint32_t addr);
static struct mp_entry *mp_hash_delete(enum mp_type type, uint32_t addr);
static void rsp_remove_matchpoint(struct rsp_buf *p_buf);
static void rsp_insert_matchpoint(struct rsp_buf *p_buf);
static void rsp_command(struct rsp_buf *p_buf);
static void rsp_set(struct rsp_buf *p_buf);
static void rsp_restart(void);
static void ascii2hex(char *dest, char *src);
static void hex2ascii(char *dest, char *src);
static uint32_t hex2reg(char *p_buf);
static void reg2hex(uint32_t val, char *p_buf);
static void swap_buf(char *p_buf, int len);
static void set_stall_state(int state);
static void reset_or1k(void);
static void gdb_ensure_or1k_stalled();
static int gdb_set_chain(int chain);
static int gdb_write_byte(uint32_t adr, uint8_t data);
static int gdb_write_reg(uint32_t adr, uint32_t data);
static int gdb_read_byte(uint32_t adr, uint8_t *data);
static int gdb_read_reg(uint32_t adr, uint32_t *data);
static int gdb_write_block(uint32_t adr, uint32_t *data, int len);
static int gdb_read_block(uint32_t adr, uint32_t *data, int len);
static int gdb_read_byte(uint32_t adr, uint8_t * data);
static int gdb_read_reg(uint32_t adr, uint32_t * data);
static int gdb_write_block(uint32_t adr, uint32_t * data, int len);
static int gdb_read_block(uint32_t adr, uint32_t * data, int len);
 
char *printTime(void)
{
time_t tid;
struct tm *strtm;
static char timeBuf[20];
time(&tid);
strtm = localtime(&tid);
sprintf(timeBuf,"[%.02d:%.02d:%.02d] ",strtm->tm_hour,strtm->tm_min,strtm->tm_sec);
return timeBuf;
time_t tid;
struct tm *strtm;
static char timeBuf[20];
 
time(&tid);
strtm = localtime(&tid);
sprintf(timeBuf, "[%.02d:%.02d:%.02d] ", strtm->tm_hour, strtm->tm_min,
strtm->tm_sec);
return timeBuf;
}
 
/*---------------------------------------------------------------------------*/
371,29 → 364,28
 
Set up the central data structures. */
/*---------------------------------------------------------------------------*/
void
rsp_init (void)
void rsp_init(void)
{
/* Clear out the central data structure */
rsp.client_waiting = 0; /* GDB client is not waiting for us */
rsp.client_fd = -1; /* i.e. invalid */
rsp.sigval = 0; /* No exception */
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
/* Clear out the central data structure */
rsp.client_waiting = 0; /* GDB client is not waiting for us */
rsp.client_fd = -1; /* i.e. invalid */
rsp.sigval = 0; /* No exception */
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
 
/* Set up the matchpoint hash table */
mp_hash_init ();
/* Set up the matchpoint hash table */
mp_hash_init();
 
/* RSP always starts stalled as though we have just reset the processor. */
rsp_exception (EXCEPT_TRAP);
/* RSP always starts stalled as though we have just reset the processor. */
rsp_exception(EXCEPT_TRAP);
 
/* Setup the NPC caching variables */
stallState = STALLED;
// Force a caching of the NPC
npcIsCached = 0;
get_npc();
} /* rsp_init () */
/* Setup the NPC caching variables */
stallState = STALLED;
// Force a caching of the NPC
npcIsCached = 0;
get_npc();
 
} /* rsp_init () */
 
/*---------------------------------------------------------------------------*/
/*!Look for action on RSP
 
409,107 → 401,99
 
The next client request is then processed. */
/*---------------------------------------------------------------------------*/
void
handle_rsp (void)
void handle_rsp(void)
{
uint32_t temp_uint32;
uint32_t temp_uint32;
 
rsp_init();
rsp_init();
 
while (1){
/* If we have no RSP client, wait until we get one. */
while (-1 == rsp.client_fd)
{
rsp_get_client ();
rsp.client_waiting = 0; /* No longer waiting */
}
/* If we have an unacknowledged exception tell the GDB client. If this
exception was a trap due to a memory breakpoint, then adjust the NPC. */
if (rsp.client_waiting)
{
// Check for exception
rsp_check_for_exception();
while (1) {
/* If we have no RSP client, wait until we get one. */
while (-1 == rsp.client_fd) {
rsp_get_client();
rsp.client_waiting = 0; /* No longer waiting */
}
 
if(stallState == STALLED)
// Get the PPC if we're stalled
gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
/* If we have an unacknowledged exception tell the GDB client. If this
exception was a trap due to a memory breakpoint, then adjust the NPC. */
if (rsp.client_waiting) {
 
if ((TARGET_SIGNAL_TRAP == rsp.sigval) && (NULL != mp_hash_lookup (BP_MEMORY, temp_uint32)))
{
if (stallState != STALLED)
// This is a quick fix for a strange situation seen in some of
// the simulators where the sw bp would be detected, but the
// stalled state variable wasn't updated correctly indicating
// that last time it checked, it wasn't set but the processor
// had hit the breakpoint. So run rsp_check_for_exception() to
// bring everything up to date.
rsp_check_for_exception();
if(DEBUG_GDB) printf("Software breakpoint hit at 0x%08x. Rolling back NPC to this instruction\n", temp_uint32);
set_npc (temp_uint32);
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
}
else if(stallState == STALLED) {
// If we're here, the thing has stalled, but not because of a breakpoint we set
// report back the exception
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
}
// Check for exception
rsp_check_for_exception();
 
if (stallState == STALLED)
// Get the PPC if we're stalled
gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
 
if ((TARGET_SIGNAL_TRAP == rsp.sigval)
&& (NULL !=
mp_hash_lookup(BP_MEMORY, temp_uint32))) {
if (stallState != STALLED)
// This is a quick fix for a strange situation seen in some of
// the simulators where the sw bp would be detected, but the
// stalled state variable wasn't updated correctly indicating
// that last time it checked, it wasn't set but the processor
// had hit the breakpoint. So run rsp_check_for_exception() to
// bring everything up to date.
rsp_check_for_exception();
 
if (DEBUG_GDB)
printf
("Software breakpoint hit at 0x%08x. Rolling back NPC to this instruction\n",
temp_uint32);
 
set_npc(temp_uint32);
 
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
} else if (stallState == STALLED) {
// If we're here, the thing has stalled, but not because of a breakpoint we set
// report back the exception
 
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
 
}
 
#ifdef CYGWIN_COMPILE
//if (rsp.client_waiting)
//sleep(1);
//if (rsp.client_waiting)
//sleep(1);
#else
if (rsp.client_waiting)
usleep(10000);
sched_yield();
if (rsp.client_waiting)
usleep(10000);
sched_yield();
#endif
}
// See if there's any incoming data from the client by peeking at the socket
if (rsp_peek() > 0)
{
if (rsp_peek() == 0x03 && (stallState != STALLED)) // ETX, end of text control char
{
// Got an interrupt command from GDB, this function should
// pull the packet off the socket and stall the processor.
// and then send a stop reply packet with signal TARGET_SIGNAL_NONE
rsp_interrupt();
rsp.client_waiting = 0;
}
else if (rsp.client_waiting == 0)
{
// Default handling of data from the client:
/* Get a RSP client request */
rsp_client_request ();
}
} /* end if (rsp_peek() > 0) */
else
 
}
// See if there's any incoming data from the client by peeking at the socket
if (rsp_peek() > 0) {
if (rsp_peek() == 0x03 && (stallState != STALLED)) // ETX, end of text control char
{
// Got an interrupt command from GDB, this function should
// pull the packet off the socket and stall the processor.
// and then send a stop reply packet with signal TARGET_SIGNAL_NONE
rsp_interrupt();
rsp.client_waiting = 0;
} else if (rsp.client_waiting == 0) {
// Default handling of data from the client:
/* Get a RSP client request */
rsp_client_request();
}
} /* end if (rsp_peek() > 0) */
else
#ifdef CYGWIN_COMPILE
sleep(1);
sleep(1);
#else
{
usleep(10000);
sched_yield();
}
{
usleep(10000);
sched_yield();
}
#endif
}
} /* handle_rsp () */
 
}
 
} /* handle_rsp () */
 
/*
Check if processor is stalled - if it is, read the DRR
and return the target signal code
517,54 → 501,85
static void rsp_check_for_exception()
{
 
unsigned char stalled;
uint32_t drr;
err = dbg_cpu0_read_ctrl(0, &stalled); /* check if we're stalled */
unsigned char stalled;
uint32_t drr;
err = dbg_cpu0_read_ctrl(0, &stalled); /* check if we're stalled */
 
if (!(stalled & 0x01))
{
// Processor not stalled. Just return;
return;
}
if (DEBUG_GDB) printf("rsp_check_for_exception() detected processor was stalled\nChecking DRR\n");
// We're stalled
stallState = STALLED;
npcIsCached = 0;
if (!(stalled & 0x01)) {
// Processor not stalled. Just return;
return;
}
 
gdb_set_chain(SC_RISC_DEBUG);
if (DEBUG_GDB)
printf
("rsp_check_for_exception() detected processor was stalled\nChecking DRR\n");
 
// Now read the DRR (Debug Reason Register)
gdb_read_reg(DRR_CPU_REG_ADD, &drr);
// We're stalled
stallState = STALLED;
npcIsCached = 0;
 
if (DEBUG_GDB) printf("DRR: 0x%08x\n", drr);
switch ((int)(drr&0xffffffff))
{
case SPR_DRR_RSTE: rsp.sigval = TARGET_SIGNAL_PWR; break;
case SPR_DRR_BUSEE: rsp.sigval = TARGET_SIGNAL_BUS; break;
case SPR_DRR_DPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
case SPR_DRR_IPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
case SPR_DRR_TTE: rsp.sigval = TARGET_SIGNAL_ALRM; 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:
// This must be the case of single step (which does not set DRR)
rsp.sigval = TARGET_SIGNAL_TRAP; break;
}
gdb_set_chain(SC_RISC_DEBUG);
 
if (DEBUG_GDB) printf("rsp.sigval: 0x%x\n", rsp.sigval);
return;
// Now read the DRR (Debug Reason Register)
gdb_read_reg(DRR_CPU_REG_ADD, &drr);
 
if (DEBUG_GDB)
printf("DRR: 0x%08x\n", drr);
 
switch ((int)(drr & 0xffffffff)) {
case SPR_DRR_RSTE:
rsp.sigval = TARGET_SIGNAL_PWR;
break;
case SPR_DRR_BUSEE:
rsp.sigval = TARGET_SIGNAL_BUS;
break;
case SPR_DRR_DPFE:
rsp.sigval = TARGET_SIGNAL_SEGV;
break;
case SPR_DRR_IPFE:
rsp.sigval = TARGET_SIGNAL_SEGV;
break;
case SPR_DRR_TTE:
rsp.sigval = TARGET_SIGNAL_ALRM;
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:
// This must be the case of single step (which does not set DRR)
rsp.sigval = TARGET_SIGNAL_TRAP;
break;
}
 
if (DEBUG_GDB)
printf("rsp.sigval: 0x%x\n", rsp.sigval);
 
return;
}
 
/*---------------------------------------------------------------------------*/
577,24 → 592,23
@param[in] ppc Value of current PPC, as read from debug unit
@return: 1 if we set a sigval and should return control to GDB, else 0 */
/*---------------------------------------------------------------------------*/
static int
check_for_exception_vector(uint32_t ppc)
static int check_for_exception_vector(uint32_t ppc)
{
switch(ppc)
{
// The following should return sigvals to GDB for processing
case EXCEPT_BUSERR:
case EXCEPT_ALIGN:
case EXCEPT_ILLEGAL:
case EXCEPT_TRAP: if(DEBUG_GDB)
printf("PPC at exception address\n");
rsp_exception(ppc);
return 1;
default:
return 0;
}
return 1;
switch (ppc) {
// The following should return sigvals to GDB for processing
case EXCEPT_BUSERR:
case EXCEPT_ALIGN:
case EXCEPT_ILLEGAL:
case EXCEPT_TRAP:
if (DEBUG_GDB)
printf("PPC at exception address\n");
rsp_exception(ppc);
return 1;
 
default:
return 0;
}
return 1;
}
 
/*---------------------------------------------------------------------------*/
609,44 → 623,70
 
@param[in] except The exception (Or1ksim form) */
/*---------------------------------------------------------------------------*/
void
rsp_exception (uint32_t except)
void rsp_exception(uint32_t except)
{
int sigval; /* GDB signal equivalent to exception */
int sigval; /* GDB signal equivalent to exception */
 
switch (except)
{
case EXCEPT_RESET: sigval = TARGET_SIGNAL_PWR; break;
case EXCEPT_BUSERR: sigval = TARGET_SIGNAL_BUS; break;
case EXCEPT_DPF: sigval = TARGET_SIGNAL_SEGV; break;
case EXCEPT_IPF: sigval = TARGET_SIGNAL_SEGV; break;
case EXCEPT_TICK: sigval = TARGET_SIGNAL_ALRM; break;
case EXCEPT_ALIGN: sigval = TARGET_SIGNAL_BUS; break;
case EXCEPT_ILLEGAL: sigval = TARGET_SIGNAL_ILL; break;
case EXCEPT_INT: sigval = TARGET_SIGNAL_INT; break;
case EXCEPT_DTLBMISS: sigval = TARGET_SIGNAL_SEGV; break;
case EXCEPT_ITLBMISS: sigval = TARGET_SIGNAL_SEGV; break;
case EXCEPT_RANGE: sigval = TARGET_SIGNAL_FPE; break;
case EXCEPT_SYSCALL: sigval = TARGET_SIGNAL_USR2; break;
case EXCEPT_FPE: sigval = TARGET_SIGNAL_FPE; break;
case EXCEPT_TRAP: sigval = TARGET_SIGNAL_TRAP; break;
switch (except) {
case EXCEPT_RESET:
sigval = TARGET_SIGNAL_PWR;
break;
case EXCEPT_BUSERR:
sigval = TARGET_SIGNAL_BUS;
break;
case EXCEPT_DPF:
sigval = TARGET_SIGNAL_SEGV;
break;
case EXCEPT_IPF:
sigval = TARGET_SIGNAL_SEGV;
break;
case EXCEPT_TICK:
sigval = TARGET_SIGNAL_ALRM;
break;
case EXCEPT_ALIGN:
sigval = TARGET_SIGNAL_BUS;
break;
case EXCEPT_ILLEGAL:
sigval = TARGET_SIGNAL_ILL;
break;
case EXCEPT_INT:
sigval = TARGET_SIGNAL_INT;
break;
case EXCEPT_DTLBMISS:
sigval = TARGET_SIGNAL_SEGV;
break;
case EXCEPT_ITLBMISS:
sigval = TARGET_SIGNAL_SEGV;
break;
case EXCEPT_RANGE:
sigval = TARGET_SIGNAL_FPE;
break;
case EXCEPT_SYSCALL:
sigval = TARGET_SIGNAL_USR2;
break;
case EXCEPT_FPE:
sigval = TARGET_SIGNAL_FPE;
break;
case EXCEPT_TRAP:
sigval = TARGET_SIGNAL_TRAP;
break;
 
default:
fprintf (stderr, "Warning: Unknown RSP exception %u: Ignored\n", except);
return;
}
default:
fprintf(stderr, "Warning: Unknown RSP exception %u: Ignored\n",
except);
return;
}
 
if ((0 != rsp.sigval) && (sigval != rsp.sigval))
{
fprintf (stderr, "Warning: RSP signal %d received while signal "
"%d pending: Pending exception replaced\n", sigval, rsp.sigval);
}
if ((0 != rsp.sigval) && (sigval != rsp.sigval)) {
fprintf(stderr, "Warning: RSP signal %d received while signal "
"%d pending: Pending exception replaced\n", sigval,
rsp.sigval);
}
 
rsp.sigval = sigval; /* Save the signal value */
rsp.sigval = sigval; /* Save the signal value */
 
} /* rsp_exception () */
} /* rsp_exception () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a new client connection.
 
664,136 → 704,129
 
The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
/*---------------------------------------------------------------------------*/
static void
rsp_get_client (void)
static void rsp_get_client(void)
{
int tmp_fd; /* Temporary descriptor for socket */
int optval; /* Socket options */
struct sockaddr_in sock_addr; /* Socket address */
socklen_t len; /* Size of the socket address */
int tmp_fd; /* Temporary descriptor for socket */
int optval; /* Socket options */
struct sockaddr_in sock_addr; /* Socket address */
socklen_t len; /* Size of the socket address */
 
/* 0 is used as the RSP port number to indicate that we should use the
service name instead. */
if (0 == serverPort)
{
struct servent *service = getservbyname (OR1KSIM_RSP_SERVICE, "tcp");
if (NULL == service)
{
fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n",
OR1KSIM_RSP_SERVICE, strerror (errno));
return;
/* 0 is used as the RSP port number to indicate that we should use the
service name instead. */
if (0 == serverPort) {
struct servent *service =
getservbyname(OR1KSIM_RSP_SERVICE, "tcp");
if (NULL == service) {
fprintf(stderr,
"Warning: RSP unable to find service \"%s\": %s\n",
OR1KSIM_RSP_SERVICE, strerror(errno));
return;
}
serverPort = ntohs(service->s_port);
}
serverPort = ntohs (service->s_port);
}
 
/* Open a socket on which we'll listen for clients */
tmp_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tmp_fd < 0)
{
fprintf (stderr, "ERROR: Cannot open RSP socket\n");
exit (0);
}
/* Open a socket on which we'll listen for clients */
tmp_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tmp_fd < 0) {
fprintf(stderr, "ERROR: Cannot open RSP socket\n");
exit(0);
}
 
/* Allow rapid reuse of the port on this socket */
optval = 1;
setsockopt (tmp_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval,
sizeof (optval));
/* Allow rapid reuse of the port on this socket */
optval = 1;
setsockopt(tmp_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval,
sizeof(optval));
 
/* Bind the port to the socket */
sock_addr.sin_family = PF_INET;
sock_addr.sin_port = htons (serverPort);
sock_addr.sin_addr.s_addr = INADDR_ANY;
if (bind (tmp_fd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)))
{
fprintf (stderr, "ERROR: Cannot bind to RSP socket\n");
exit (0);
}
/* Listen for (at most one) client */
if (0 != listen (tmp_fd, 1))
{
fprintf (stderr, "ERROR: Cannot listen on RSP socket\n");
exit (0);
}
/* Bind the port to the socket */
sock_addr.sin_family = PF_INET;
sock_addr.sin_port = htons(serverPort);
sock_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(tmp_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr))) {
fprintf(stderr, "ERROR: Cannot bind to RSP socket\n");
exit(0);
}
 
printf("Waiting for gdb connection on localhost:%d\n", serverPort);
fflush (stdout);
/* Listen for (at most one) client */
if (0 != listen(tmp_fd, 1)) {
fprintf(stderr, "ERROR: Cannot listen on RSP socket\n");
exit(0);
}
 
printf("Press CTRL+c to exit.\n");
fflush (stdout);
printf("Waiting for gdb connection on localhost:%d\n", serverPort);
fflush(stdout);
 
/* Accept a client which connects */
len = sizeof (sock_addr);
rsp.client_fd = accept (tmp_fd, (struct sockaddr *)&sock_addr, &len);
printf("Press CTRL+c to exit.\n");
fflush(stdout);
 
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Failed to accept RSP client\n");
return;
}
/* Accept a client which connects */
len = sizeof(sock_addr);
rsp.client_fd = accept(tmp_fd, (struct sockaddr *)&sock_addr, &len);
 
/* Enable TCP keep alive process */
optval = 1;
setsockopt (rsp.client_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval,
sizeof (optval));
if (-1 == rsp.client_fd) {
fprintf(stderr, "Warning: Failed to accept RSP client\n");
return;
}
 
int flags;
/* If they have O_NONBLOCK, use the Posix way to do it */
/* Enable TCP keep alive process */
optval = 1;
setsockopt(rsp.client_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval,
sizeof(optval));
 
int flags;
 
/* If they have O_NONBLOCK, use the Posix way to do it */
 
#if defined(O_NONBLOCK)
/* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
if (-1 == (flags = fcntl(rsp.client_fd, F_GETFL, 0)))
flags = 0;
fcntl(rsp.client_fd, F_SETFL, flags | O_NONBLOCK);
/* Fixme: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */
if (-1 == (flags = fcntl(rsp.client_fd, F_GETFL, 0)))
flags = 0;
 
fcntl(rsp.client_fd, F_SETFL, flags | O_NONBLOCK);
#else
/* Otherwise, use the old way of doing it */
flags = 1;
ioctl(rsp.client_fd, FIOBIO, &flags);
/* Otherwise, use the old way of doing it */
flags = 1;
ioctl(rsp.client_fd, FIOBIO, &flags);
#endif
 
/* Set socket to be non-blocking.
/* Set socket to be non-blocking.
 
We do this because when we're given a continue, or step
instruction,command we set the processor stall off, then instantly check
if it's stopped. If it hasn't then we drop through and wait for input
from GDB. Obviously this will cause problems when it will stop after we
do the check. So now, rsp_peek() been implemented to simply check if
there's an incoming command from GDB (although, mainly interested in
int. commands), otherwise it returns back to poll the processor's
stall bit. It can only do this if the socket is non-blocking.
We do this because when we're given a continue, or step
instruction,command we set the processor stall off, then instantly check
if it's stopped. If it hasn't then we drop through and wait for input
from GDB. Obviously this will cause problems when it will stop after we
do the check. So now, rsp_peek() been implemented to simply check if
there's an incoming command from GDB (although, mainly interested in
int. commands), otherwise it returns back to poll the processor's
stall bit. It can only do this if the socket is non-blocking.
 
At first test, simply adding this line appeared to give no problems with
the existing code. No "simulation" of blocking behaviour on the
non-blocking socket was required (in the event that a read/write throws
back a EWOULDBLOCK error, as was looked to be the case in the previous
GDB handling code) -- Julius
*/
At first test, simply adding this line appeared to give no problems with
the existing code. No "simulation" of blocking behaviour on the
non-blocking socket was required (in the event that a read/write throws
back a EWOULDBLOCK error, as was looked to be the case in the previous
GDB handling code) -- Julius
*/
 
if (ioctl(rsp.client_fd, FIONBIO, (char *)&optval) > 0 )
{
perror("ioctl() failed");
close(rsp.client_fd);
close(tmp_fd);
exit(0);
}
if (ioctl(rsp.client_fd, FIONBIO, (char *)&optval) > 0) {
perror("ioctl() failed");
close(rsp.client_fd);
close(tmp_fd);
exit(0);
}
 
/* Don't delay small packets, for better interactive response (disable
Nagel's algorithm) */
optval = 1;
setsockopt (rsp.client_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval,
sizeof (optval));
/* Don't delay small packets, for better interactive response (disable
Nagel's algorithm) */
optval = 1;
setsockopt(rsp.client_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval,
sizeof(optval));
 
/* Socket is no longer needed */
close (tmp_fd); /* No longer need this */
signal (SIGPIPE, SIG_IGN); /* So we don't exit if client dies */
/* Socket is no longer needed */
close(tmp_fd); /* No longer need this */
signal(SIGPIPE, SIG_IGN); /* So we don't exit if client dies */
 
printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr));
} /* rsp_get_client () */
printf("Remote debugging from host %s\n",
inet_ntoa(sock_addr.sin_addr));
} /* rsp_get_client () */
 
 
/*---------------------------------------------------------------------------*/
/*!Deal with a request from the GDB client session
 
800,226 → 833,232
In general, apart from the simplest requests, this function replies on
other functions to implement the functionality. */
/*---------------------------------------------------------------------------*/
static void rsp_client_request (void)
static void rsp_client_request(void)
{
struct rsp_buf *p_buf = get_packet (); /* Message sent to us */
struct rsp_buf *p_buf = get_packet(); /* Message sent to us */
 
// Null packet means we hit EOF or the link was closed for some other
// reason. Close the client and return
if (NULL == p_buf)
{
rsp_client_close ();
return;
}
// Null packet means we hit EOF or the link was closed for some other
// reason. Close the client and return
if (NULL == p_buf) {
rsp_client_close();
return;
}
 
if (DEBUG_GDB){
printf("%s-----------------------------------------------------\n", printTime());
printf ("Packet received %s: %d chars\n", p_buf->data, p_buf->len );
fflush (stdout);
}
if (DEBUG_GDB) {
printf
("%s-----------------------------------------------------\n",
printTime());
printf("Packet received %s: %d chars\n", p_buf->data,
p_buf->len);
fflush(stdout);
}
 
switch (p_buf->data[0])
{
case '!':
/* Request for extended remote mode */
put_str_packet ("OK"); // OK = supports and has enabled extended mode.
return;
switch (p_buf->data[0]) {
case '!':
/* Request for extended remote mode */
put_str_packet("OK"); // OK = supports and has enabled extended mode.
return;
 
case '?':
/* Return last signal ID */
rsp_report_exception();
return;
case '?':
/* Return last signal ID */
rsp_report_exception();
return;
 
case 'A':
/* Initialization of argv not supported */
fprintf (stderr, "Warning: RSP 'A' packet not supported: ignored\n");
put_str_packet ("E01");
return;
case 'A':
/* Initialization of argv not supported */
fprintf(stderr,
"Warning: RSP 'A' packet not supported: ignored\n");
put_str_packet("E01");
return;
 
case 'b':
/* Setting baud rate is deprecated */
fprintf (stderr, "Warning: RSP 'b' packet is deprecated and not "
"supported: ignored\n");
return;
case 'b':
/* Setting baud rate is deprecated */
fprintf(stderr, "Warning: RSP 'b' packet is deprecated and not "
"supported: ignored\n");
return;
 
case 'B':
/* Breakpoints should be set using Z packets */
fprintf (stderr, "Warning: RSP 'B' packet is deprecated (use 'Z'/'z' "
"packets instead): ignored\n");
return;
case 'B':
/* Breakpoints should be set using Z packets */
fprintf(stderr,
"Warning: RSP 'B' packet is deprecated (use 'Z'/'z' "
"packets instead): ignored\n");
return;
 
case 'c':
/* Continue */
rsp_continue (p_buf);
return;
case 'c':
/* Continue */
rsp_continue(p_buf);
return;
 
case 'C':
/* Continue with signal */
rsp_continue_with_signal (p_buf);
return;
case 'C':
/* Continue with signal */
rsp_continue_with_signal(p_buf);
return;
 
case 'd':
/* Disable debug using a general query */
fprintf (stderr, "Warning: RSP 'd' packet is deprecated (define a 'Q' "
"packet instead: ignored\n");
return;
case 'd':
/* Disable debug using a general query */
fprintf(stderr,
"Warning: RSP 'd' packet is deprecated (define a 'Q' "
"packet instead: ignored\n");
return;
 
case 'D':
/* Detach GDB. Do this by closing the client. The rules say that
execution should continue. TODO. Is this really then intended
meaning? Or does it just mean that only vAttach will be recognized
after this? */
put_str_packet ("OK");
rsp_client_close ();
reset_or1k ();
set_stall_state (0);
return;
case 'D':
/* Detach GDB. Do this by closing the client. The rules say that
execution should continue. TODO. Is this really then intended
meaning? Or does it just mean that only vAttach will be recognized
after this? */
put_str_packet("OK");
rsp_client_close();
reset_or1k();
set_stall_state(0);
return;
 
case 'F':
/* File I/O is not currently supported */
fprintf (stderr, "Warning: RSP file I/O not currently supported: 'F' "
"packet ignored\n");
return;
case 'F':
/* File I/O is not currently supported */
fprintf(stderr,
"Warning: RSP file I/O not currently supported: 'F' "
"packet ignored\n");
return;
 
case 'g':
rsp_read_all_regs ();
return;
case 'g':
rsp_read_all_regs();
return;
 
case 'G':
rsp_write_all_regs (p_buf);
return;
case 'H':
/* Set the thread number of subsequent operations. For now ignore
silently and just reply "OK" */
put_str_packet ("OK");
return;
case 'G':
rsp_write_all_regs(p_buf);
return;
 
case 'i':
/* Single instruction step */
fprintf (stderr, "Warning: RSP cycle stepping not supported: target "
"stopped immediately\n");
rsp.client_waiting = 1; /* Stop reply will be sent */
return;
case 'H':
/* Set the thread number of subsequent operations. For now ignore
silently and just reply "OK" */
put_str_packet("OK");
return;
 
case 'I':
/* Single instruction step with signal */
fprintf (stderr, "Warning: RSP cycle stepping not supported: target "
"stopped immediately\n");
rsp.client_waiting = 1; /* Stop reply will be sent */
return;
case 'i':
/* Single instruction step */
fprintf(stderr,
"Warning: RSP cycle stepping not supported: target "
"stopped immediately\n");
rsp.client_waiting = 1; /* Stop reply will be sent */
return;
 
case 'k':
/* Kill request. Do nothing for now. */
return;
case 'I':
/* Single instruction step with signal */
fprintf(stderr,
"Warning: RSP cycle stepping not supported: target "
"stopped immediately\n");
rsp.client_waiting = 1; /* Stop reply will be sent */
return;
 
case 'm':
/* Read memory (symbolic) */
rsp_read_mem (p_buf);
return;
case 'k':
/* Kill request. Do nothing for now. */
return;
 
case 'M':
/* Write memory (symbolic) */
rsp_write_mem (p_buf);
return;
case 'm':
/* Read memory (symbolic) */
rsp_read_mem(p_buf);
return;
 
case 'p':
/* Read a register */
rsp_read_reg (p_buf);
return;
case 'M':
/* Write memory (symbolic) */
rsp_write_mem(p_buf);
return;
 
case 'P':
/* Write a register */
rsp_write_reg (p_buf);
return;
case 'p':
/* Read a register */
rsp_read_reg(p_buf);
return;
 
case 'q':
/* Any one of a number of query packets */
rsp_query (p_buf);
return;
case 'P':
/* Write a register */
rsp_write_reg(p_buf);
return;
 
case 'Q':
/* Any one of a number of set packets */
rsp_set (p_buf);
return;
case 'q':
/* Any one of a number of query packets */
rsp_query(p_buf);
return;
 
case 'r':
/* Reset the system. Deprecated (use 'R' instead) */
fprintf (stderr, "Warning: RSP 'r' packet is deprecated (use 'R' "
"packet instead): ignored\n");
return;
case 'Q':
/* Any one of a number of set packets */
rsp_set(p_buf);
return;
 
case 'R':
/* Restart the program being debugged. */
rsp_restart ();
return;
case 'r':
/* Reset the system. Deprecated (use 'R' instead) */
fprintf(stderr,
"Warning: RSP 'r' packet is deprecated (use 'R' "
"packet instead): ignored\n");
return;
 
case 's':
/* Single step (one high level instruction). This could be hard without
DWARF2 info */
rsp_step (p_buf);
return;
case 'R':
/* Restart the program being debugged. */
rsp_restart();
return;
 
case 'S':
/* Single step (one high level instruction) with signal. This could be
hard without DWARF2 info */
rsp_step_with_signal (p_buf);
return;
case 's':
/* Single step (one high level instruction). This could be hard without
DWARF2 info */
rsp_step(p_buf);
return;
 
case 't':
/* Search. This is not well defined in the manual and for now we don't
support it. No response is defined. */
fprintf (stderr, "Warning: RSP 't' packet not supported: ignored\n");
return;
case 'S':
/* Single step (one high level instruction) with signal. This could be
hard without DWARF2 info */
rsp_step_with_signal(p_buf);
return;
 
case 'T':
/* Is the thread alive. We are bare metal, so don't have a thread
context. The answer is always "OK". */
put_str_packet ("OK");
return;
case 't':
/* Search. This is not well defined in the manual and for now we don't
support it. No response is defined. */
fprintf(stderr,
"Warning: RSP 't' packet not supported: ignored\n");
return;
 
case 'v':
/* Any one of a number of packets to control execution */
rsp_vpkt (p_buf);
return;
case 'T':
/* Is the thread alive. We are bare metal, so don't have a thread
context. The answer is always "OK". */
put_str_packet("OK");
return;
 
case 'X':
/* Write memory (binary) */
rsp_write_mem_bin (p_buf);
return;
case 'v':
/* Any one of a number of packets to control execution */
rsp_vpkt(p_buf);
return;
 
case 'z':
/* Remove a breakpoint/watchpoint. */
rsp_remove_matchpoint (p_buf);
return;
case 'X':
/* Write memory (binary) */
rsp_write_mem_bin(p_buf);
return;
 
case 'Z':
/* Insert a breakpoint/watchpoint. */
rsp_insert_matchpoint (p_buf);
return;
case 'z':
/* Remove a breakpoint/watchpoint. */
rsp_remove_matchpoint(p_buf);
return;
 
default:
/* Unknown commands are ignored */
fprintf (stderr, "Warning: Unknown RSP request %s\n", p_buf->data);
return;
}
} /* rsp_client_request () */
case 'Z':
/* Insert a breakpoint/watchpoint. */
rsp_insert_matchpoint(p_buf);
return;
 
default:
/* Unknown commands are ignored */
fprintf(stderr, "Warning: Unknown RSP request %s\n",
p_buf->data);
return;
}
} /* rsp_client_request () */
 
/*---------------------------------------------------------------------------*/
/*!Close the connection to the client if it is open */
/*---------------------------------------------------------------------------*/
static void
rsp_client_close (void)
static void rsp_client_close(void)
{
if (-1 != rsp.client_fd)
{
close (rsp.client_fd);
rsp.client_fd = -1;
}
} /* rsp_client_close () */
if (-1 != rsp.client_fd) {
close(rsp.client_fd);
rsp.client_fd = -1;
}
} /* rsp_client_close () */
 
 
/*---------------------------------------------------------------------------*/
/*!Send a packet to the GDB client
 
1030,64 → 1069,59
 
@param[in] p_buf The data to send */
/*---------------------------------------------------------------------------*/
static void
put_packet (struct rsp_buf *p_buf)
static void put_packet(struct rsp_buf *p_buf)
{
unsigned char data[GDB_BUF_MAX * 2];
int len;
int ch; /* Ack char */
unsigned char data[GDB_BUF_MAX * 2];
int len;
int ch; /* Ack char */
 
/* Construct $<packet info>#<checksum>. Repeat until the GDB client
acknowledges satisfactory receipt. */
do
{
unsigned char checksum = 0; /* Computed checksum */
int count = 0; /* Index into the buffer */
/* Construct $<packet info>#<checksum>. Repeat until the GDB client
acknowledges satisfactory receipt. */
do {
unsigned char checksum = 0; /* Computed checksum */
int count = 0; /* Index into the buffer */
 
if (DEBUG_GDB_DUMP_DATA){
printf ("Putting %s\n\n", p_buf->data);
fflush (stdout);
}
if (DEBUG_GDB_DUMP_DATA) {
printf("Putting %s\n\n", p_buf->data);
fflush(stdout);
}
 
len = 0;
data[len++] = '$'; /* Start char */
len = 0;
data[len++] = '$'; /* Start char */
 
/* Body of the packet */
for (count = 0; count < p_buf->len; count++)
{
unsigned char ch = p_buf->data[count];
/* Body of the packet */
for (count = 0; count < p_buf->len; count++) {
unsigned char ch = p_buf->data[count];
 
/* Check for escaped chars */
if (('$' == ch) || ('#' == ch) || ('*' == ch) || ('}' == ch))
{
ch ^= 0x20;
checksum += (unsigned char)'}';
data[len++] = '}';
}
/* Check for escaped chars */
if (('$' == ch) || ('#' == ch) || ('*' == ch)
|| ('}' == ch)) {
ch ^= 0x20;
checksum += (unsigned char)'}';
data[len++] = '}';
}
 
checksum += ch;
data[len++] = ch;
}
checksum += ch;
data[len++] = ch;
}
 
data[len++] = '#'; /* End char */
data[len++] = '#'; /* End char */
 
/* Computed checksum */
data[len++] = (hexchars[checksum >> 4]);
data[len++] = (hexchars[checksum % 16]);
/* Computed checksum */
data[len++] = (hexchars[checksum >> 4]);
data[len++] = (hexchars[checksum % 16]);
 
send_rsp_str ((unsigned char *) &data, len);
send_rsp_str((unsigned char *)&data, len);
 
/* Check for ack of connection failure */
ch = get_rsp_char ();
if (0 > ch)
{
return; /* Fail the put silently. */
/* Check for ack of connection failure */
ch = get_rsp_char();
if (0 > ch) {
return; /* Fail the put silently. */
}
}
}
while ('+' != ch);
} /* put_packet () */
while ('+' != ch);
 
} /* put_packet () */
 
/*---------------------------------------------------------------------------*/
/*!Convenience to put a constant string packet
1094,31 → 1128,28
 
param[in] str The text of the packet */
/*---------------------------------------------------------------------------*/
static void
put_str_packet (const char *str)
static void put_str_packet(const char *str)
{
struct rsp_buf buffer;
int len = strlen (str);
struct rsp_buf buffer;
int len = strlen(str);
 
/* Construct the packet to send, so long as string is not too big,
otherwise truncate. Add EOS at the end for convenient debug printout */
/* Construct the packet to send, so long as string is not too big,
otherwise truncate. Add EOS at the end for convenient debug printout */
 
if (len >= GDB_BUF_MAX)
{
fprintf (stderr, "Warning: String %s too large for RSP packet: "
"truncated\n", str);
len = GDB_BUF_MAX - 1;
}
if (len >= GDB_BUF_MAX) {
fprintf(stderr, "Warning: String %s too large for RSP packet: "
"truncated\n", str);
len = GDB_BUF_MAX - 1;
}
 
strncpy (buffer.data, str, len);
buffer.data[len] = 0;
buffer.len = len;
strncpy(buffer.data, str, len);
buffer.data[len] = 0;
buffer.len = len;
 
put_packet (&buffer);
put_packet(&buffer);
 
} /* put_str_packet () */
} /* put_str_packet () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a packet from the GDB client
1133,126 → 1164,109
 
@return A pointer to the static buffer containing the data */
/*---------------------------------------------------------------------------*/
static struct rsp_buf *
get_packet (void)
static struct rsp_buf *get_packet(void)
{
static struct rsp_buf buf; /* Survives the return */
static struct rsp_buf buf; /* Survives the return */
 
/* Keep getting packets, until one is found with a valid checksum */
while (1)
{
unsigned char checksum; /* The checksum we have computed */
int count; /* Index into the buffer */
int ch; /* Current character */
/* Keep getting packets, until one is found with a valid checksum */
while (1) {
unsigned char checksum; /* The checksum we have computed */
int count; /* Index into the buffer */
int ch; /* Current character */
 
/* Wait around for the start character ('$'). Ignore all other
characters */
ch = get_rsp_char ();
/* Wait around for the start character ('$'). Ignore all other
characters */
ch = get_rsp_char();
 
while (ch != '$')
{
if (-1 == ch)
{
return NULL; /* Connection failed */
}
while (ch != '$') {
if (-1 == ch) {
return NULL; /* Connection failed */
}
 
ch = get_rsp_char ();
ch = get_rsp_char();
 
// Potentially handle an interrupt character (0x03) here
}
// Potentially handle an interrupt character (0x03) here
}
 
/* Read until a '#' or end of buffer is found */
checksum = 0;
count = 0;
while (count < GDB_BUF_MAX - 1)
{
ch = get_rsp_char ();
if(rsp.client_waiting && DEBUG_GDB)
{
printf("%x\n",ch);
}
/* Read until a '#' or end of buffer is found */
checksum = 0;
count = 0;
while (count < GDB_BUF_MAX - 1) {
ch = get_rsp_char();
 
if (rsp.client_waiting && DEBUG_GDB) {
printf("%x\n", ch);
}
 
/* Check for connection failure */
if (0 > ch)
{
return NULL;
}
/* Check for connection failure */
if (0 > ch) {
return NULL;
}
 
/* If we hit a start of line char begin all over again */
if ('$' == ch)
{
checksum = 0;
count = 0;
/* If we hit a start of line char begin all over again */
if ('$' == ch) {
checksum = 0;
count = 0;
 
continue;
}
continue;
}
 
/* Break out if we get the end of line char */
if ('#' == ch)
{
break;
}
/* Break out if we get the end of line char */
if ('#' == ch) {
break;
}
 
/* Update the checksum and add the char to the buffer */
/* Update the checksum and add the char to the buffer */
 
checksum = checksum + (unsigned char)ch;
buf.data[count] = (char)ch;
count = count + 1;
}
checksum = checksum + (unsigned char)ch;
buf.data[count] = (char)ch;
count = count + 1;
}
 
/* Mark the end of the buffer with EOS - it's convenient for non-binary
data to be valid strings. */
buf.data[count] = 0;
buf.len = count;
/* Mark the end of the buffer with EOS - it's convenient for non-binary
data to be valid strings. */
buf.data[count] = 0;
buf.len = count;
 
/* If we have a valid end of packet char, validate the checksum */
if ('#' == ch)
{
unsigned char xmitcsum; /* The checksum in the packet */
/* If we have a valid end of packet char, validate the checksum */
if ('#' == ch) {
unsigned char xmitcsum; /* The checksum in the packet */
 
ch = get_rsp_char ();
if (0 > ch)
{
return NULL; /* Connection failed */
}
xmitcsum = hex (ch) << 4;
ch = get_rsp_char();
if (0 > ch) {
return NULL; /* Connection failed */
}
xmitcsum = hex(ch) << 4;
 
ch = get_rsp_char ();
if (0 > ch)
{
return NULL; /* Connection failed */
}
ch = get_rsp_char();
if (0 > ch) {
return NULL; /* Connection failed */
}
 
xmitcsum += hex (ch);
xmitcsum += hex(ch);
 
/* If the checksums don't match print a warning, and put the
negative ack back to the client. Otherwise put a positive ack. */
if (checksum != xmitcsum)
{
fprintf (stderr, "Warning: Bad RSP checksum: Computed "
"0x%02x, received 0x%02x\n", checksum, xmitcsum);
/* If the checksums don't match print a warning, and put the
negative ack back to the client. Otherwise put a positive ack. */
if (checksum != xmitcsum) {
fprintf(stderr,
"Warning: Bad RSP checksum: Computed "
"0x%02x, received 0x%02x\n", checksum,
xmitcsum);
 
ch = '-';
send_rsp_str ((unsigned char *) &ch, 1); /* Failed checksum */
}
else
{
ch = '+';
send_rsp_str ((unsigned char *) &ch, 1); /* successful transfer */
break;
}
ch = '-';
send_rsp_str((unsigned char *)&ch, 1); /* Failed checksum */
} else {
ch = '+';
send_rsp_str((unsigned char *)&ch, 1); /* successful transfer */
break;
}
} else {
fprintf(stderr, "Warning: RSP packet overran buffer\n");
}
}
else
{
fprintf (stderr, "Warning: RSP packet overran buffer\n");
}
}
return &buf; /* Success */
} /* get_packet () */
return &buf; /* Success */
} /* get_packet () */
 
 
/*---------------------------------------------------------------------------*/
/*!Put a single character out onto the client socket
 
1260,45 → 1274,41
 
@param[in] c The character to put out */
/*---------------------------------------------------------------------------*/
static void
send_rsp_str (unsigned char *data, int len)
static void send_rsp_str(unsigned char *data, int len)
{
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Attempt to write '%s' to unopened RSP "
"client: Ignored\n", data);
return;
}
if (-1 == rsp.client_fd) {
fprintf(stderr,
"Warning: Attempt to write '%s' to unopened RSP "
"client: Ignored\n", data);
return;
}
 
/* Write until successful (we retry after interrupts) or catastrophic
failure. */
while (1)
{
switch (write (rsp.client_fd, data, len))
{
case -1:
/* Error: only allow interrupts or would block */
if ((EAGAIN != errno) && (EINTR != errno))
{
fprintf (stderr, "Warning: Failed to write to RSP client: "
"Closing client connection: %s\n",
strerror (errno));
rsp_client_close ();
return;
}
break;
/* Write until successful (we retry after interrupts) or catastrophic
failure. */
while (1) {
switch (write(rsp.client_fd, data, len)) {
case -1:
/* Error: only allow interrupts or would block */
if ((EAGAIN != errno) && (EINTR != errno)) {
fprintf(stderr,
"Warning: Failed to write to RSP client: "
"Closing client connection: %s\n",
strerror(errno));
rsp_client_close();
return;
}
 
case 0:
break; /* Nothing written! Try again */
break;
 
default:
return; /* Success, we can return */
case 0:
break; /* Nothing written! Try again */
 
default:
return; /* Success, we can return */
}
}
}
} /* send_rsp_str () */
} /* send_rsp_str () */
 
 
/*---------------------------------------------------------------------------*/
/*!Get a single character from the client socket
 
1306,47 → 1316,43
 
@return The character read, or -1 on failure */
/*---------------------------------------------------------------------------*/
static int
get_rsp_char ()
static int get_rsp_char()
{
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
"client: Ignored\n");
return -1;
}
if (-1 == rsp.client_fd) {
fprintf(stderr, "Warning: Attempt to read from unopened RSP "
"client: Ignored\n");
return -1;
}
 
/* Non-blocking read until successful (we retry after interrupts) or
catastrophic failure. */
while (1)
{
unsigned char c;
/* Non-blocking read until successful (we retry after interrupts) or
catastrophic failure. */
while (1) {
unsigned char c;
 
switch (read (rsp.client_fd, &c, sizeof (c)))
{
case -1:
/* Error: only allow interrupts */
if ((EAGAIN != errno) && (EINTR != errno))
{
fprintf (stderr, "Warning: Failed to read from RSP client: "
"Closing client connection: %s\n",
strerror (errno));
rsp_client_close ();
return -1;
}
switch (read(rsp.client_fd, &c, sizeof(c))) {
case -1:
/* Error: only allow interrupts */
if ((EAGAIN != errno) && (EINTR != errno)) {
fprintf(stderr,
"Warning: Failed to read from RSP client: "
"Closing client connection: %s\n",
strerror(errno));
rsp_client_close();
return -1;
}
 
break;
break;
 
case 0:
// EOF
rsp_client_close ();
return -1;
case 0:
// EOF
rsp_client_close();
return -1;
 
default:
return c & 0xff; /* Success, we can return (no sign extend!) */
default:
return c & 0xff; /* Success, we can return (no sign extend!) */
}
}
}
} /* get_rsp_char () */
} /* get_rsp_char () */
 
/*---------------------------------------------------------------------------*/
/* !Peek at data coming into server from GDB
1356,36 → 1362,35
@return the char we peeked, 0 otherwise */
/*---------------------------------------------------------------------------*/
static char
rsp_peek()
static char rsp_peek()
{
/*
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
"client: Ignored\n");
return -1;
}
*/
char c;
int n;
// Using recv here instead of read becuase we can pass the MSG_PEEK
// flag, which lets us look at what's on the socket, without actually
// taking it off
/*
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
"client: Ignored\n");
return -1;
}
*/
char c;
int n;
// Using recv here instead of read becuase we can pass the MSG_PEEK
// flag, which lets us look at what's on the socket, without actually
// taking it off
 
//if (DEBUG_GDB)
// printf("peeking at GDB socket...\n");
n = recv (rsp.client_fd, &c, sizeof (c), MSG_PEEK);
//if (DEBUG_GDB)
// printf("peeked, got n=%d, c=0x%x\n",n, c);
if (n > 0)
return c;
else
return '\0';
//if (DEBUG_GDB)
// printf("peeking at GDB socket...\n");
 
n = recv(rsp.client_fd, &c, sizeof(c), MSG_PEEK);
 
//if (DEBUG_GDB)
// printf("peeked, got n=%d, c=0x%x\n",n, c);
 
if (n > 0)
return c;
else
return '\0';
 
}
 
/*---------------------------------------------------------------------------*/
1393,43 → 1398,39
 
Detect an interrupt from GDB and stall the processor */
/*---------------------------------------------------------------------------*/
static void
rsp_interrupt()
static void rsp_interrupt()
{
unsigned char c;
unsigned char c;
 
if (read (rsp.client_fd, &c, sizeof (c)) <= 0)
{
// Had issues, just return
return;
}
// 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
// things go back to normal...
if (c != 0x03)
{
printf("Warning: Interrupt character expected but not found on socket.\n");
return;
}
// Otherwise, it's an interrupt packet, stall the processor, and upon return
// to the main handle_rsp() loop, it will inform GDB.
if (read(rsp.client_fd, &c, sizeof(c)) <= 0) {
// Had issues, just return
return;
}
// 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
// things go back to normal...
if (c != 0x03) {
printf
("Warning: Interrupt character expected but not found on socket.\n");
return;
}
// Otherwise, it's an interrupt packet, stall the processor, and upon return
// to the main handle_rsp() loop, it will inform GDB.
 
if (DEBUG_GDB) printf("Interrupt received from GDB. Stalling processor.\n");
if (DEBUG_GDB)
printf("Interrupt received from GDB. Stalling processor.\n");
 
set_stall_state (1);
set_stall_state(1);
 
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE
rsp.sigval = TARGET_SIGNAL_NONE;
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
// Send a stop reply response, manually set rsp.sigval to TARGET_SIGNAL_NONE
rsp.sigval = TARGET_SIGNAL_NONE;
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
 
return;
return;
 
}
 
 
/*---------------------------------------------------------------------------*/
/*!"Unescape" RSP binary data
 
1442,35 → 1443,28
 
@return The number of bytes AFTER conversion */
/*---------------------------------------------------------------------------*/
static int
rsp_unescape (char *data,
int len)
static int rsp_unescape(char *data, int len)
{
int from_off = 0; /* Offset to source char */
int to_off = 0; /* Offset to dest char */
int from_off = 0; /* Offset to source char */
int to_off = 0; /* Offset to dest char */
 
while (from_off < len)
{
/* Is it escaped */
if ( '}' == data[from_off])
{
from_off++;
data[to_off] = data[from_off] ^ 0x20;
while (from_off < len) {
/* Is it escaped */
if ('}' == data[from_off]) {
from_off++;
data[to_off] = data[from_off] ^ 0x20;
} else {
data[to_off] = data[from_off];
}
 
from_off++;
to_off++;
}
else
{
data[to_off] = data[from_off];
}
 
from_off++;
to_off++;
}
return to_off;
 
return to_off;
} /* rsp_unescape () */
 
} /* rsp_unescape () */
 
 
/*---------------------------------------------------------------------------*/
/*!Initialize the matchpoint hash table
 
1477,18 → 1471,15
This is an open hash table, so this function clears all the links to
NULL. */
/*---------------------------------------------------------------------------*/
static void
mp_hash_init (void)
static void mp_hash_init(void)
{
int i;
int i;
 
for (i = 0; i < MP_HASH_SIZE; i++)
{
rsp.mp_hash[i] = NULL;
}
} /* mp_hash_init () */
for (i = 0; i < MP_HASH_SIZE; i++) {
rsp.mp_hash[i] = NULL;
}
} /* mp_hash_init () */
 
 
/*---------------------------------------------------------------------------*/
/*!Add an entry to the matchpoint hash table
 
1501,36 → 1492,30
@param[in] addr The address of the matchpoint
@para[in] instr The instruction to associate with the address */
/*---------------------------------------------------------------------------*/
static void
mp_hash_add (enum mp_type type,
uint32_t addr,
uint32_t instr)
static void mp_hash_add(enum mp_type type, uint32_t addr, uint32_t instr)
{
int hv = addr % MP_HASH_SIZE;
struct mp_entry *curr;
int hv = addr % MP_HASH_SIZE;
struct mp_entry *curr;
 
/* See if we already have the entry */
for(curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next)
{
if ((type == curr->type) && (addr == curr->addr))
{
return; /* We already have the entry */
/* See if we already have the entry */
for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) {
if ((type == curr->type) && (addr == curr->addr)) {
return; /* We already have the entry */
}
}
}
 
/* Insert the new entry at the head of the chain */
curr = (struct mp_entry*) malloc (sizeof (*curr));
/* Insert the new entry at the head of the chain */
curr = (struct mp_entry *)malloc(sizeof(*curr));
 
curr->type = type;
curr->addr = addr;
curr->instr = instr;
curr->next = rsp.mp_hash[hv];
curr->type = type;
curr->addr = addr;
curr->instr = instr;
curr->next = rsp.mp_hash[hv];
 
rsp.mp_hash[hv] = curr;
rsp.mp_hash[hv] = curr;
 
} /* mp_hash_add () */
} /* mp_hash_add () */
 
 
/*---------------------------------------------------------------------------*/
/*!Look up an entry in the matchpoint hash table
 
1541,25 → 1526,22
 
@return The entry deleted, or NULL if the entry was not found */
/*---------------------------------------------------------------------------*/
static struct mp_entry * mp_hash_lookup (enum mp_type type, uint32_t addr)
static struct mp_entry *mp_hash_lookup(enum mp_type type, uint32_t addr)
{
int hv = addr % MP_HASH_SIZE;
struct mp_entry *curr;
int hv = addr % MP_HASH_SIZE;
struct mp_entry *curr;
 
/* Search */
for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next)
{
if ((type == curr->type) && (addr == curr->addr))
{
return curr; /* The entry found */
/* Search */
for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) {
if ((type == curr->type) && (addr == curr->addr)) {
return curr; /* The entry found */
}
}
}
 
/* Not found */
return NULL;
} /* mp_hash_lookup () */
/* Not found */
return NULL;
 
} /* mp_hash_lookup () */
 
/*---------------------------------------------------------------------------*/
/*!Delete an entry from the matchpoint hash table
1579,42 → 1561,34
 
@return The entry deleted, or NULL if the entry was not found */
/*---------------------------------------------------------------------------*/
static struct mp_entry *
mp_hash_delete (enum mp_type type,
uint32_t addr)
static struct mp_entry *mp_hash_delete(enum mp_type type, uint32_t addr)
{
int hv = addr % MP_HASH_SIZE;
struct mp_entry *prev = NULL;
struct mp_entry *curr;
int hv = addr % MP_HASH_SIZE;
struct mp_entry *prev = NULL;
struct mp_entry *curr;
 
/* Search */
for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next)
{
if ((type == curr->type) && (addr == curr->addr))
{
/* Found - delete. Method depends on whether we are the head of
chain. */
if (NULL == prev)
{
rsp.mp_hash[hv] = curr->next;
}
else
{
prev->next = curr->next;
}
/* Search */
for (curr = rsp.mp_hash[hv]; NULL != curr; curr = curr->next) {
if ((type == curr->type) && (addr == curr->addr)) {
/* Found - delete. Method depends on whether we are the head of
chain. */
if (NULL == prev) {
rsp.mp_hash[hv] = curr->next;
} else {
prev->next = curr->next;
}
 
return curr; /* The entry deleted */
return curr; /* The entry deleted */
}
 
prev = curr;
}
 
prev = curr;
}
/* Not found */
return NULL;
 
/* Not found */
return NULL;
} /* mp_hash_delete () */
} /* mp_hash_delete () */
 
 
/*---------------------------------------------------------------------------*/
/*!Utility to give the value of a hex char
 
1625,15 → 1599,14
@return The value of the hex character, or -1 if the character is
invalid. */
/*---------------------------------------------------------------------------*/
static int hex (int c)
static int hex(int c)
{
return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 :
((c >= '0') && (c <= '9')) ? c - '0' :
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1;
return ((c >= 'a') && (c <= 'f')) ? c - 'a' + 10 :
((c >= '0') && (c <= '9')) ? c - '0' :
((c >= 'A') && (c <= 'F')) ? c - 'A' + 10 : -1;
 
} /* hex () */
} /* hex () */
 
 
/*---------------------------------------------------------------------------*/
/*!Convert a register to a hex digit string
 
1643,32 → 1616,28
@param[in] val The value to convert
@param[out] p_buf The buffer for the text string */
/*---------------------------------------------------------------------------*/
static void
reg2hex (uint32_t val, char *p_buf)
static void reg2hex(uint32_t val, char *p_buf)
{
int n; /* Counter for digits */
int nyb_shift;
int n; /* Counter for digits */
int nyb_shift;
 
for (n = 0; n < 8; n++)
{
for (n = 0; n < 8; n++) {
#ifdef WORDSBIGENDIAN
if(n%2==0){
nyb_shift = n * 4 + 4;
}
else{
nyb_shift = n * 4 - 4;
}
if (n % 2 == 0) {
nyb_shift = n * 4 + 4;
} else {
nyb_shift = n * 4 - 4;
}
#else
nyb_shift = 28 - (n * 4);
nyb_shift = 28 - (n * 4);
#endif
p_buf[n] = hexchars[(val >> nyb_shift) & 0xf];
}
p_buf[n] = hexchars[(val >> nyb_shift) & 0xf];
}
 
p_buf[8] = 0; /* Useful to terminate as string */
p_buf[8] = 0; /* Useful to terminate as string */
 
} /* reg2hex () */
} /* reg2hex () */
 
 
/*---------------------------------------------------------------------------*/
/*!Convert a hex digit string to a register value
 
1679,27 → 1648,24
 
@return The value to convert */
/*---------------------------------------------------------------------------*/
static uint32_t
hex2reg (char *p_buf)
static uint32_t hex2reg(char *p_buf)
{
int n; /* Counter for digits */
uint32_t val = 0; /* The result */
int n; /* Counter for digits */
uint32_t val = 0; /* The result */
 
for (n = 0; n < 8; n++)
{
for (n = 0; n < 8; n++) {
#ifdef WORDSBIGENDIAN
int nyb_shift = n * 4;
int nyb_shift = n * 4;
#else
int nyb_shift = 28 - (n * 4);
int nyb_shift = 28 - (n * 4);
#endif
val |= hex (p_buf[n]) << nyb_shift;
}
val |= hex(p_buf[n]) << nyb_shift;
}
 
return val;
return val;
 
} /* hex2reg () */
} /* hex2reg () */
 
 
/*---------------------------------------------------------------------------*/
/*!Convert an ASCII character string to pairs of hex digits
 
1708,24 → 1674,21
@param[out] dest Buffer to store the hex digit pairs (null terminated)
@param[in] src The ASCII string (null terminated) */
/*---------------------------------------------------------------------------*/
static void ascii2hex (char *dest,
char *src)
static void ascii2hex(char *dest, char *src)
{
int i;
int i;
 
/* Step through converting the source string */
for (i = 0; src[i] != '\0'; i++)
{
char ch = src[i];
/* Step through converting the source string */
for (i = 0; src[i] != '\0'; i++) {
char ch = src[i];
 
dest[i * 2] = hexchars[ch >> 4 & 0xf];
dest[i * 2 + 1] = hexchars[ch & 0xf];
}
dest[i * 2] = hexchars[ch >> 4 & 0xf];
dest[i * 2 + 1] = hexchars[ch & 0xf];
}
 
dest[i * 2] = '\0';
} /* ascii2hex () */
dest[i * 2] = '\0';
 
} /* ascii2hex () */
 
/*---------------------------------------------------------------------------*/
/*!Convert pairs of hex digits to an ASCII character string
1735,22 → 1698,21
@param[out] dest The ASCII string (null terminated)
@param[in] src Buffer holding the hex digit pairs (null terminated) */
/*---------------------------------------------------------------------------*/
static void hex2ascii (char *dest,
char *src)
static void hex2ascii(char *dest, char *src)
{
int i;
int i;
 
/* Step through convering the source hex digit pairs */
for (i = 0; src[i * 2] != '\0' && src[i * 2 + 1] != '\0'; i++)
{
dest[i] = ((hex (src[i * 2]) & 0xf) << 4) | (hex (src[i * 2 + 1]) & 0xf);
}
/* Step through convering the source hex digit pairs */
for (i = 0; src[i * 2] != '\0' && src[i * 2 + 1] != '\0'; i++) {
dest[i] =
((hex(src[i * 2]) & 0xf) << 4) | (hex(src[i * 2 + 1]) &
0xf);
}
 
dest[i] = '\0';
dest[i] = '\0';
 
} /* hex2ascii () */
} /* hex2ascii () */
 
 
/*---------------------------------------------------------------------------*/
/*!Set the program counter
 
1763,39 → 1725,35
 
@param[in] addr The address to use */
/*---------------------------------------------------------------------------*/
static void
set_npc (uint32_t addr)
static void set_npc(uint32_t addr)
{
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
if (addr != get_npc())
{
if (addr != get_npc()) {
 
gdb_write_reg(NPC_CPU_REG_ADD, addr);
if (STALLED == stallState)
{
if (DEBUG_GDB) printf("set_npc(): New NPC value (0x%08x) written and locally cached \n", addr);
npcCachedValue = addr;
npcIsCached = 1;
}
else
{
if (DEBUG_GDB) printf("set_npc(): New NPC value (0x%08x) written \n", addr);
npcIsCached = 0;
}
gdb_write_reg(NPC_CPU_REG_ADD, addr);
 
}
else
return;
if (STALLED == stallState) {
if (DEBUG_GDB)
printf
("set_npc(): New NPC value (0x%08x) written and locally cached \n",
addr);
npcCachedValue = addr;
npcIsCached = 1;
} else {
if (DEBUG_GDB)
printf
("set_npc(): New NPC value (0x%08x) written \n",
addr);
npcIsCached = 0;
}
 
} /* set_npc () */
} else
return;
 
} /* set_npc () */
 
//! Read the value of the Next Program Counter (a SPR)
 
1810,68 → 1768,62
//! it. Otherwise read the corresponding SPR.
 
//! @return The value of the NPC
static uint32_t get_npc ()
static uint32_t get_npc()
{
uint32_t current_npc;
uint32_t current_npc;
 
if (STALLED == stallState)
{
if (npcIsCached == 0)
{
err = gdb_set_chain(SC_RISC_DEBUG);
err = gdb_read_reg(NPC_CPU_REG_ADD, &npcCachedValue);
if(err > 0){
printf("Error %d reading NPC\n", err);
rsp_client_close ();
return 0;
}
if (DEBUG_GDB) printf("get_npc(): caching newly read NPC value (0x%08x)\n",npcCachedValue);
if (STALLED == stallState) {
if (npcIsCached == 0) {
err = gdb_set_chain(SC_RISC_DEBUG);
err = gdb_read_reg(NPC_CPU_REG_ADD, &npcCachedValue);
if (err > 0) {
printf("Error %d reading NPC\n", err);
rsp_client_close();
return 0;
}
if (DEBUG_GDB)
printf
("get_npc(): caching newly read NPC value (0x%08x)\n",
npcCachedValue);
 
npcIsCached = 1;
} else if (DEBUG_GDB)
printf("get_npc(): reading cached NPC value (0x%08x)\n",
npcCachedValue);
 
npcIsCached = 1;
return npcCachedValue;
} else {
err = gdb_read_reg(NPC_CPU_REG_ADD, &current_npc);
if (err > 0) {
printf("Error %d reading NPC\n", err);
rsp_client_close();
return 0;
}
return current_npc;
 
}
else
if (DEBUG_GDB) printf("get_npc(): reading cached NPC value (0x%08x)\n",npcCachedValue);
} // get_npc ()
 
return npcCachedValue;
}
else
{
err = gdb_read_reg(NPC_CPU_REG_ADD, &current_npc);
if(err > 0){
printf("Error %d reading NPC\n", err);
rsp_client_close ();
return 0;
}
return current_npc;
 
}
} // get_npc ()
 
 
 
/*---------------------------------------------------------------------------*/
/*!Send a packet acknowledging an exception has occurred
 
This is only called if there is a client FD to talk to */
/*---------------------------------------------------------------------------*/
static void
rsp_report_exception (void)
static void rsp_report_exception(void)
{
struct rsp_buf buffer;
struct rsp_buf buffer;
 
/* Construct a signal received packet */
buffer.data[0] = 'S';
buffer.data[1] = hexchars[rsp.sigval >> 4];
buffer.data[2] = hexchars[rsp.sigval % 16];
buffer.data[3] = 0;
buffer.len = strlen (buffer.data);
/* Construct a signal received packet */
buffer.data[0] = 'S';
buffer.data[1] = hexchars[rsp.sigval >> 4];
buffer.data[2] = hexchars[rsp.sigval % 16];
buffer.data[3] = 0;
buffer.len = strlen(buffer.data);
 
put_packet (&buffer);
put_packet(&buffer);
 
} /* rsp_report_exception () */
} /* rsp_report_exception () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP continue request
 
1880,46 → 1832,44
 
@param[in] p_buf The full continue packet */
/*---------------------------------------------------------------------------*/
static void
rsp_continue (struct rsp_buf *p_buf)
static void rsp_continue(struct rsp_buf *p_buf)
{
uint32_t addr; /* Address to continue from, if any */
uint32_t addr; /* Address to continue from, if any */
 
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
if(err > 0){
printf("Error %d to set RISC Debug Interface chain in the CONTINUE command 'c'\n", err);
rsp_client_close ();
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
if (0 == strcmp ("c", p_buf->data))
{
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
}
else if (1 != sscanf (p_buf->data, "c%x", &addr))
{
fprintf (stderr,
"Warning: RSP continue address %s not recognized: ignored\n",
p_buf->data);
if (err > 0) {
printf
("Error %d to set RISC Debug Interface chain in the CONTINUE command 'c'\n",
err);
rsp_client_close();
return;
}
 
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
}
if (0 == strcmp("c", p_buf->data)) {
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
} else if (1 != sscanf(p_buf->data, "c%x", &addr)) {
fprintf(stderr,
"Warning: RSP continue address %s not recognized: ignored\n",
p_buf->data);
 
if (DEBUG_GDB) printf("rsp_continue() --> Read NPC = 0x%08x\n", addr);
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
}
 
rsp_continue_generic (addr, EXCEPT_NONE);
if (DEBUG_GDB)
printf("rsp_continue() --> Read NPC = 0x%08x\n", addr);
 
} /* rsp_continue () */
rsp_continue_generic(addr, EXCEPT_NONE);
 
} /* rsp_continue () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP continue with signal request
1928,15 → 1878,14
 
@param[in] p_buf The full continue with signal packet */
/*---------------------------------------------------------------------------*/
static void
rsp_continue_with_signal (struct rsp_buf *p_buf)
static void rsp_continue_with_signal(struct rsp_buf *p_buf)
{
printf ("RSP continue with signal '%s' received, signal ignored\n", p_buf->data);
rsp_continue (p_buf);
printf("RSP continue with signal '%s' received, signal ignored\n",
p_buf->data);
rsp_continue(p_buf);
 
} /* rsp_continue_with_signal () */
} /* rsp_continue_with_signal () */
 
 
/*---------------------------------------------------------------------------*/
/*!Generic processing of a continue request
 
1949,46 → 1898,50
@param[in] addr Address from which to step
@param[in] except The exception to use (if any) */
/*---------------------------------------------------------------------------*/
static void
rsp_continue_generic (uint32_t addr,
uint32_t except)
static void rsp_continue_generic(uint32_t addr, uint32_t except)
{
uint32_t temp_uint32;
/* Set the address as the value of the next program counter */
set_npc (addr);
/* Clear Debug Reason Register (DRR) 0x3015 */
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n");
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB;
if(gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR2 register\n");
temp_uint32 &= ~SPR_DMR2_WGB;
if(gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR2 register\n");
/* Clear the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */
// Arc sim --> cpu_state.sprs[SPR_DMR1] &= ~SPR_DMR1_ST;
if(gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR1 register\n");
temp_uint32 &= ~SPR_DMR1_ST;
if(gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR1 register\n");
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
if(gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32)) printf("Error read from DSR register\n");
temp_uint32 |= SPR_DSR_TE;
if(gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32)) printf("Error write to DSR register\n");
uint32_t temp_uint32;
 
/* Unstall the processor */
set_stall_state (0);
/* Set the address as the value of the next program counter */
set_npc(addr);
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
/* Clear Debug Reason Register (DRR) 0x3015 */
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
if (gdb_write_reg(DRR_CPU_REG_ADD, 0))
printf("Error write to DRR register\n");
 
} /* rsp_continue_generic () */
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB;
if (gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32))
printf("Error read from DMR2 register\n");
temp_uint32 &= ~SPR_DMR2_WGB;
if (gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32))
printf("Error write to DMR2 register\n");
 
/* Clear the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */
// Arc sim --> cpu_state.sprs[SPR_DMR1] &= ~SPR_DMR1_ST;
if (gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32))
printf("Error read from DMR1 register\n");
temp_uint32 &= ~SPR_DMR1_ST;
if (gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32))
printf("Error write to DMR1 register\n");
 
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
if (gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32))
printf("Error read from DSR register\n");
temp_uint32 |= SPR_DSR_TE;
if (gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32))
printf("Error write to DSR register\n");
 
/* Unstall the processor */
set_stall_state(0);
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
 
} /* rsp_continue_generic () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP read all registers request
 
1998,90 → 1951,93
 
Each byte is packed as a pair of hex digits. */
/*---------------------------------------------------------------------------*/
static void
rsp_read_all_regs (void)
static void rsp_read_all_regs(void)
{
struct rsp_buf buffer; /* Buffer for the reply */
int r; /* Register index */
uint32_t temp_uint32;
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
// Read all GPRs
for (r = 0; r < MAX_GPRS; r++){
err = gdb_read_reg(0x400 + r, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_read_reg at reg. %d\n", err, r);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, &(buffer.data[r * 8]));
if (DEBUG_GDB_DUMP_DATA){
switch(r % 4)
{
case 0:
printf("gpr%02d 0x%08x ", r, temp_uint32);
break;
case 1:
case 2:
printf("0x%08x ", temp_uint32);
break;
case 3:
printf("0x%08x\n", temp_uint32);
break;
default:
break;
struct rsp_buf buffer; /* Buffer for the reply */
int r; /* Register index */
uint32_t temp_uint32;
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
// Read all GPRs
for (r = 0; r < MAX_GPRS; r++) {
 
err = gdb_read_reg(0x400 + r, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_read_reg at reg. %d\n",
err, r);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, &(buffer.data[r * 8]));
 
if (DEBUG_GDB_DUMP_DATA) {
switch (r % 4) {
case 0:
printf("gpr%02d 0x%08x ", r, temp_uint32);
break;
case 1:
case 2:
printf("0x%08x ", temp_uint32);
break;
case 3:
printf("0x%08x\n", temp_uint32);
break;
default:
break;
}
}
 
}
}
}
/* ---------- PPC ---------- */
err = gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> PPC\n", err);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, &(buffer.data[PPC_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA) printf("PPC 0x%08x\n", temp_uint32);
/* ---------- NPC ---------- */
temp_uint32 = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> NPC\n", err);
put_str_packet ("E01");
return;
}
*/
reg2hex (temp_uint32, &(buffer.data[NPC_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA) printf("NPC 0x%08x\n", temp_uint32);
/* ---------- SR ---------- */
err = gdb_read_reg(SR_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> SP\n", err);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, &(buffer.data[SR_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA) printf("SR 0x%08x\n", temp_uint32);
/* ---------- PPC ---------- */
err = gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_read_reg read --> PPC\n", err);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, &(buffer.data[PPC_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA)
printf("PPC 0x%08x\n", temp_uint32);
/* ---------- NPC ---------- */
temp_uint32 = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_read_reg read --> NPC\n", err);
put_str_packet ("E01");
return;
}
*/
reg2hex(temp_uint32, &(buffer.data[NPC_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA)
printf("NPC 0x%08x\n", temp_uint32);
/* ---------- SR ---------- */
err = gdb_read_reg(SR_CPU_REG_ADD, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_read_reg read --> SP\n", err);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, &(buffer.data[SR_REGNUM * 8]));
if (DEBUG_GDB_DUMP_DATA)
printf("SR 0x%08x\n", temp_uint32);
 
/* Finalize the packet and send it */
buffer.data[NUM_REGS * 8] = 0;
buffer.len = NUM_REGS * 8;
/* Finalize the packet and send it */
buffer.data[NUM_REGS * 8] = 0;
buffer.len = NUM_REGS * 8;
 
put_packet (&buffer);
return;
} /* rsp_read_all_regs () */
put_packet(&buffer);
return;
} /* rsp_read_all_regs () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP write all registers request
 
2097,73 → 2053,83
 
@param[in] p_buf The original packet request. */
/*---------------------------------------------------------------------------*/
static void
rsp_write_all_regs (struct rsp_buf *p_buf)
static void rsp_write_all_regs(struct rsp_buf *p_buf)
{
uint32_t regnum; /* Register index */
// char valstr[9]; /* Allow for EOS on the string */
uint32_t regnum; /* Register index */
// char valstr[9]; /* Allow for EOS on the string */
 
// /* Check for valid data */
// if (0 != (strcmp ("G", p_buf->data)) && (GDB_BUF_MAX != strlen(p_buf->data)))
// {
// fprintf (stderr, "Warning: Failed to recognize RSP write register "
// "command: %s\n", p_buf->data);
// // put_str_packet ("E01");
// return;
// }
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// /* Check for valid data */
// if (0 != (strcmp ("G", p_buf->data)) && (GDB_BUF_MAX != strlen(p_buf->data)))
// {
// fprintf (stderr, "Warning: Failed to recognize RSP write register "
// "command: %s\n", p_buf->data);
// // put_str_packet ("E01");
// return;
// }
 
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
put_str_packet ("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
/* ---------- GPRS ---------- */
for (regnum = 0; regnum < MAX_GPRS; regnum++)
{
err = gdb_write_reg(0x400 + regnum, hex2reg (&p_buf->data[regnum * 8 + 1]));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> GPRS\n", err);
put_str_packet ("E01");
return;
}
}
/* ---------- PPC ---------- */
err = gdb_write_reg(PPC_CPU_REG_ADD, hex2reg (&p_buf->data[PPC_REGNUM * 8 + 1]));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> PPC\n", err);
put_str_packet ("E01");
return;
}
/* ---------- SR ---------- */
err = gdb_write_reg(SR_CPU_REG_ADD, hex2reg (&p_buf->data[SR_REGNUM * 8 + 1]));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> SR\n", err);
put_str_packet ("E01");
return;
}
/* ---------- NPC ---------- */
set_npc(hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1]));
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1]));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> NPC\n", err);
put_str_packet ("E01");
return;
}
*/
/* Acknowledge. TODO: We always succeed at present, even if the data was
defective. */
put_str_packet ("OK");
} /* rsp_write_all_regs () */
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
put_str_packet("E01");
return;
}
 
/* ---------- GPRS ---------- */
for (regnum = 0; regnum < MAX_GPRS; regnum++) {
err =
gdb_write_reg(0x400 + regnum,
hex2reg(&p_buf->data[regnum * 8 + 1]));
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_write_reg write --> GPRS\n",
err);
put_str_packet("E01");
return;
}
}
 
/* ---------- PPC ---------- */
err =
gdb_write_reg(PPC_CPU_REG_ADD,
hex2reg(&p_buf->data[PPC_REGNUM * 8 + 1]));
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in rsp_write_reg write --> PPC\n",
err);
put_str_packet("E01");
return;
}
/* ---------- SR ---------- */
err =
gdb_write_reg(SR_CPU_REG_ADD,
hex2reg(&p_buf->data[SR_REGNUM * 8 + 1]));
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in rsp_write_reg write --> SR\n", err);
put_str_packet("E01");
return;
}
/* ---------- NPC ---------- */
set_npc(hex2reg(&p_buf->data[NPC_REGNUM * 8 + 1]));
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1]));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> NPC\n", err);
put_str_packet ("E01");
return;
}
*/
/* Acknowledge. TODO: We always succeed at present, even if the data was
defective. */
put_str_packet("OK");
} /* rsp_write_all_regs () */
 
/*---------------------------------------------------------------------------*/
/* Handle a RSP read memory (symbolic) request
 
2180,134 → 2146,131
 
@param[in] p_buf The command received */
/*---------------------------------------------------------------------------*/
static void rsp_read_mem (struct rsp_buf *p_buf)
static void rsp_read_mem(struct rsp_buf *p_buf)
{
unsigned int addr; /* Where to read the memory */
int len; /* Number of bytes to read */
int off; /* Offset into the memory */
uint32_t temp_uint32 = 0;
char *rec_buf, *rec_buf_ptr;
int bytes_per_word = 4; /* Current OR implementation is 4-byte words */
int i;
int len_cpy;
/* Couple of temps we might need when doing aligning/leftover accesses */
uint32_t tmp_word;
uint8_t tmp_byte;
char *tmp_word_ptr = (char*) &tmp_word;
unsigned int addr; /* Where to read the memory */
int len; /* Number of bytes to read */
int off; /* Offset into the memory */
uint32_t temp_uint32 = 0;
char *rec_buf, *rec_buf_ptr;
int bytes_per_word = 4; /* Current OR implementation is 4-byte words */
int i;
int len_cpy;
/* Couple of temps we might need when doing aligning/leftover accesses */
uint32_t tmp_word;
uint8_t tmp_byte;
char *tmp_word_ptr = (char *)&tmp_word;
 
if (2 != sscanf(p_buf->data, "m%x,%x:", &addr, &len)) {
fprintf(stderr, "Warning: Failed to recognize RSP read memory "
"command: %s\n", p_buf->data);
put_str_packet("E01");
return;
}
 
if (2 != sscanf (p_buf->data, "m%x,%x:", &addr, &len))
{
fprintf (stderr, "Warning: Failed to recognize RSP read memory "
"command: %s\n", p_buf->data);
put_str_packet ("E01");
return;
}
/* Make sure we won't overflow the buffer (2 chars per byte) */
if ((len * 2) >= GDB_BUF_MAX_TIMES_TWO) {
fprintf(stderr,
"Warning: Memory read %s too large for RSP packet: "
"truncated\n", p_buf->data);
len = (GDB_BUF_MAX - 1) / 2;
}
 
/* Make sure we won't overflow the buffer (2 chars per byte) */
if ((len * 2) >= GDB_BUF_MAX_TIMES_TWO)
{
fprintf (stderr, "Warning: Memory read %s too large for RSP packet: "
"truncated\n", p_buf->data);
len = (GDB_BUF_MAX - 1) / 2;
}
if (!(rec_buf = (char *)malloc(len))) {
put_str_packet("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
if(!(rec_buf = (char*)malloc(len))) {
put_str_packet ("E01");
return;
}
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if (err) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
put_str_packet("E01");
return;
}
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
len_cpy = len;
rec_buf_ptr = rec_buf; // Need to save a copy of pointer
 
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if(err){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
put_str_packet ("E01");
return;
}
len_cpy = len;
rec_buf_ptr = rec_buf; // Need to save a copy of pointer
if (addr & 0x3) // address not word-aligned, do byte accesses first
{
if (addr & 0x3) // address not word-aligned, do byte accesses first
{
 
int num_bytes_to_align = bytes_per_word - (addr & 0x3);
int num_bytes_to_align = bytes_per_word - (addr & 0x3);
 
int bytes_to_read = (num_bytes_to_align >= len_cpy) ?
len_cpy : num_bytes_to_align;
for (i=0;i<bytes_to_read;i++)
int bytes_to_read = (num_bytes_to_align >= len_cpy) ?
len_cpy : num_bytes_to_align;
 
for (i = 0; i < bytes_to_read; i++) {
err = gdb_read_byte(addr++, (uint8_t *) & rec_buf[i]);
if (err) {
put_str_packet("E01");
return;
}
}
 
// Adjust our status
len_cpy -= bytes_to_read;
rec_buf_ptr += num_bytes_to_align;
}
 
if (len_cpy / bytes_per_word) // Now perform all full word accesses
{
err = gdb_read_byte(addr++, (uint8_t*) &rec_buf[i]);
if(err){
put_str_packet ("E01");
return;
}
}
// Adjust our status
len_cpy -= bytes_to_read;
rec_buf_ptr += num_bytes_to_align;
}
if (len_cpy/bytes_per_word) // Now perform all full word accesses
{
int words_to_read = len_cpy/bytes_per_word; // Full words to read
if (DEBUG_GDB) printf("rsp_read_mem: reading %d words from 0x%.8x\n",
words_to_read, addr);
// Read full data words from Wishbone Memory chain
err = gdb_read_block(addr, (uint32_t*)rec_buf_ptr,
words_to_read*bytes_per_word);
if(err){
put_str_packet ("E01");
return;
}
int words_to_read = len_cpy / bytes_per_word; // Full words to read
if (DEBUG_GDB)
printf("rsp_read_mem: reading %d words from 0x%.8x\n",
words_to_read, addr);
// Read full data words from Wishbone Memory chain
err = gdb_read_block(addr, (uint32_t *) rec_buf_ptr,
words_to_read * bytes_per_word);
 
// Adjust our status
len_cpy -= (words_to_read*bytes_per_word);
addr += (words_to_read*bytes_per_word);
rec_buf_ptr += (words_to_read*bytes_per_word);
}
if (len_cpy) // Leftover bytes
{
for (i=0;i<len_cpy;i++)
if (err) {
put_str_packet("E01");
return;
}
// Adjust our status
len_cpy -= (words_to_read * bytes_per_word);
addr += (words_to_read * bytes_per_word);
rec_buf_ptr += (words_to_read * bytes_per_word);
}
if (len_cpy) // Leftover bytes
{
err = gdb_read_byte(addr++, (uint8_t*) &rec_buf_ptr[i]);
if(err){
put_str_packet ("E01");
return;
}
}
}
for (i = 0; i < len_cpy; i++) {
err =
gdb_read_byte(addr++, (uint8_t *) & rec_buf_ptr[i]);
if (err) {
put_str_packet("E01");
return;
}
}
 
/* Refill the buffer with the reply */
for( off = 0 ; off < len ; off ++ ) {
;
p_buf->data[(2*off)] = hexchars[((rec_buf[off]&0xf0)>>4)];
p_buf->data[(2*off)+1] = hexchars[(rec_buf[off]&0x0f)];
}
}
 
if (DEBUG_GDB && (err > 0)) printf("\nError %x\n", err);fflush (stdout);
free(rec_buf);
p_buf->data[off * 2] = 0; /* End of string */
p_buf->len = strlen (p_buf->data);
if (DEBUG_GDB_BLOCK_DATA){
printf("rsp_read_mem: adr 0x%.8x data: ", addr);
for(i=0;i<len*2;i++)
printf("%c",p_buf->data[i]);
printf("\n");
}
/* Refill the buffer with the reply */
for (off = 0; off < len; off++) {
;
p_buf->data[(2 * off)] = hexchars[((rec_buf[off] & 0xf0) >> 4)];
p_buf->data[(2 * off) + 1] = hexchars[(rec_buf[off] & 0x0f)];
}
 
put_packet (p_buf);
if (DEBUG_GDB && (err > 0))
printf("\nError %x\n", err);
fflush(stdout);
free(rec_buf);
p_buf->data[off * 2] = 0; /* End of string */
p_buf->len = strlen(p_buf->data);
if (DEBUG_GDB_BLOCK_DATA) {
printf("rsp_read_mem: adr 0x%.8x data: ", addr);
for (i = 0; i < len * 2; i++)
printf("%c", p_buf->data[i]);
printf("\n");
}
 
} /* rsp_read_mem () */
put_packet(p_buf);
 
} /* rsp_read_mem () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP write memory (symbolic) request ("M")
2331,71 → 2294,68
 
@param[in] p_buf The command received */
/*---------------------------------------------------------------------------*/
static void
rsp_write_mem (struct rsp_buf *p_buf)
static void rsp_write_mem(struct rsp_buf *p_buf)
{
unsigned int addr; /* Where to write the memory */
int len; /* Number of bytes to write */
char *symdat; /* Pointer to the symboli data */
int datlen; /* Number of digits in symbolic data */
int off; /* Offset into the memory */
int nibc; /* Nibbel counter */
uint32_t val;
if (2 != sscanf (p_buf->data, "M%x,%x:", &addr, &len))
{
fprintf (stderr, "Warning: Failed to recognize RSP write memory "
"command: %s\n", p_buf->data);
put_str_packet ("E01");
return;
}
unsigned int addr; /* Where to write the memory */
int len; /* Number of bytes to write */
char *symdat; /* Pointer to the symboli data */
int datlen; /* Number of digits in symbolic data */
int off; /* Offset into the memory */
int nibc; /* Nibbel counter */
uint32_t val;
 
/* Find the start of the data and check there is the amount we expect. */
symdat = (char*) memchr ((const void *)p_buf->data, ':', GDB_BUF_MAX) + 1;
datlen = p_buf->len - (symdat - p_buf->data);
if (2 != sscanf(p_buf->data, "M%x,%x:", &addr, &len)) {
fprintf(stderr, "Warning: Failed to recognize RSP write memory "
"command: %s\n", p_buf->data);
put_str_packet("E01");
return;
}
 
/* Sanity check */
if (len * 2 != datlen)
{
fprintf (stderr, "Warning: Write of %d digits requested, but %d digits "
"supplied: packet ignored\n", len * 2, datlen );
put_str_packet ("E01");
return;
}
/* Find the start of the data and check there is the amount we expect. */
symdat =
(char *)memchr((const void *)p_buf->data, ':', GDB_BUF_MAX) + 1;
datlen = p_buf->len - (symdat - p_buf->data);
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
/* Sanity check */
if (len * 2 != datlen) {
fprintf(stderr,
"Warning: Write of %d digits requested, but %d digits "
"supplied: packet ignored\n", len * 2, datlen);
put_str_packet("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if (err) {
put_str_packet("E01");
return;
}
 
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if(err){
put_str_packet ("E01");
return;
}
val = 0;
off = 0;
/* Write the bytes to memory */
for (nibc = 0; nibc < datlen; nibc++)
{
val |= 0x0000000f & hex (symdat[nibc]);
if(nibc % 8 == 7){
err = gdb_write_block(addr + off, &val, 4);
if (DEBUG_GDB) printf("Error %x\n", err);fflush (stdout);
if(err){
put_str_packet ("E01");
return;
val = 0;
off = 0;
/* Write the bytes to memory */
for (nibc = 0; nibc < datlen; nibc++) {
val |= 0x0000000f & hex(symdat[nibc]);
if (nibc % 8 == 7) {
err = gdb_write_block(addr + off, &val, 4);
if (DEBUG_GDB)
printf("Error %x\n", err);
fflush(stdout);
if (err) {
put_str_packet("E01");
return;
}
val = 0;
off += 4;
}
val <<= 4;
}
val = 0;
off += 4;
}
val <<= 4;
}
put_str_packet ("OK");
} /* rsp_write_mem () */
put_str_packet("OK");
} /* rsp_write_mem () */
 
 
/*---------------------------------------------------------------------------*/
/*!Read a single register
 
2407,91 → 2367,89
 
@param[in] p_buf The original packet request. Reused for the reply. */
/*---------------------------------------------------------------------------*/
static void
rsp_read_reg (struct rsp_buf *p_buf)
static void rsp_read_reg(struct rsp_buf *p_buf)
{
unsigned int regnum;
uint32_t temp_uint32;
unsigned int regnum;
uint32_t temp_uint32;
 
/* Break out the fields from the data */
if (1 != sscanf (p_buf->data, "p%x", &regnum))
{
fprintf (stderr, "Warning: Failed to recognize RSP read register "
"command: %s\n", p_buf->data);
put_str_packet ("E01");
return;
}
/* Break out the fields from the data */
if (1 != sscanf(p_buf->data, "p%x", &regnum)) {
fprintf(stderr,
"Warning: Failed to recognize RSP read register "
"command: %s\n", p_buf->data);
put_str_packet("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
put_str_packet("E01");
return;
}
 
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
put_str_packet ("E01");
return;
}
/* Get the relevant register */
if (regnum < MAX_GPRS)
{
err = gdb_read_reg(0x400 + regnum, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_read_reg at reg. %d \n", err, regnum);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, p_buf->data);
}
else if (PPC_REGNUM == regnum) /* ---------- PPC ---------- */
{
err = gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_read_reg read --> PPC\n", err);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, p_buf->data);
}
else if (NPC_REGNUM == regnum) /* ---------- NPC ---------- */
{
temp_uint32 = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_read_reg read --> PPC\n", err);
put_str_packet ("E01");
return;
/* Get the relevant register */
if (regnum < MAX_GPRS) {
err = gdb_read_reg(0x400 + regnum, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in rsp_read_reg at reg. %d \n",
err, regnum);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, p_buf->data);
} else if (PPC_REGNUM == regnum) { /* ---------- PPC ---------- */
err = gdb_read_reg(PPC_CPU_REG_ADD, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_read_reg read --> PPC\n",
err);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, p_buf->data);
} else if (NPC_REGNUM == regnum) { /* ---------- NPC ---------- */
temp_uint32 = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_read_reg read --> PPC\n", err);
put_str_packet ("E01");
return;
}
*/
reg2hex(temp_uint32, p_buf->data);
} else if (SR_REGNUM == regnum) { /* ---------- SR ---------- */
err = gdb_read_reg(SR_CPU_REG_ADD, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_read_reg read --> PPC\n",
err);
put_str_packet("E01");
return;
}
reg2hex(temp_uint32, p_buf->data);
} else {
/* Error response if we don't know the register */
fprintf(stderr,
"Warning: Attempt to read unknown register 0x%x: "
"ignored\n", regnum);
put_str_packet("E01");
return;
}
*/
reg2hex (temp_uint32, p_buf->data);
}
else if (SR_REGNUM == regnum) /* ---------- SR ---------- */
{
err = gdb_read_reg(SR_CPU_REG_ADD, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_read_reg read --> PPC\n", err);
put_str_packet ("E01");
return;
}
reg2hex (temp_uint32, p_buf->data);
}
else
{
/* Error response if we don't know the register */
fprintf (stderr, "Warning: Attempt to read unknown register 0x%x: "
"ignored\n", regnum);
put_str_packet ("E01");
return;
}
 
p_buf->len = strlen (p_buf->data);
put_packet (p_buf);
p_buf->len = strlen(p_buf->data);
put_packet(p_buf);
 
} /* rsp_read_reg () */
} /* rsp_read_reg () */
 
/*---------------------------------------------------------------------------*/
/*!Write a single register
 
2503,231 → 2461,200
 
@param[in] p_buf The original packet request. */
/*---------------------------------------------------------------------------*/
static void
rsp_write_reg (struct rsp_buf *p_buf)
static void rsp_write_reg(struct rsp_buf *p_buf)
{
unsigned int regnum;
char valstr[9]; /* Allow for EOS on the string */
// int err = 0;
unsigned int regnum;
char valstr[9]; /* Allow for EOS on the string */
// int err = 0;
 
/* Break out the fields from the data */
if (2 != sscanf (p_buf->data, "P%x=%8s", &regnum, valstr))
{
fprintf (stderr, "Warning: Failed to recognize RSP write register "
"command: %s\n", p_buf->data);
put_str_packet ("E01");
return;
}
/* Break out the fields from the data */
if (2 != sscanf(p_buf->data, "P%x=%8s", &regnum, valstr)) {
fprintf(stderr,
"Warning: Failed to recognize RSP write register "
"command: %s\n", p_buf->data);
put_str_packet("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
put_str_packet ("E01");
return;
}
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
put_str_packet("E01");
return;
}
 
/* Set the relevant register */
if (regnum < MAX_GPRS) /* ---------- GPRS ---------- */
{
err = gdb_write_reg(0x400 + regnum, hex2reg (valstr));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> GPRS\n", err);
put_str_packet ("E01");
return;
}
}
else if (PPC_REGNUM == regnum) /* ---------- PPC ---------- */
{
err = gdb_write_reg(PPC_CPU_REG_ADD, hex2reg (valstr));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> PPC\n", err);
put_str_packet ("E01");
return;
}
}
else if (NPC_REGNUM == regnum) /* ---------- NPC ---------- */
{
set_npc(hex2reg (valstr));
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, hex2reg (valstr));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> NPC\n", err);
put_str_packet ("E01");
return;
/* Set the relevant register */
if (regnum < MAX_GPRS) { /* ---------- GPRS ---------- */
err = gdb_write_reg(0x400 + regnum, hex2reg(valstr));
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_write_reg write --> GPRS\n",
err);
put_str_packet("E01");
return;
}
} else if (PPC_REGNUM == regnum) { /* ---------- PPC ---------- */
err = gdb_write_reg(PPC_CPU_REG_ADD, hex2reg(valstr));
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_write_reg write --> PPC\n",
err);
put_str_packet("E01");
return;
}
} else if (NPC_REGNUM == regnum) { /* ---------- NPC ---------- */
set_npc(hex2reg(valstr));
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, hex2reg (valstr));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> NPC\n", err);
put_str_packet ("E01");
return;
}
*/
} else if (SR_REGNUM == regnum) { /* ---------- SR ---------- */
err = gdb_write_reg(SR_CPU_REG_ADD, hex2reg(valstr));
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_write_reg write --> SR\n",
err);
put_str_packet("E01");
return;
}
} else {
/* Error response if we don't know the register */
fprintf(stderr,
"Warning: Attempt to write unknown register 0x%x: "
"ignored\n", regnum);
put_str_packet("E01");
return;
}
*/
}
else if (SR_REGNUM == regnum) /* ---------- SR ---------- */
{
err = gdb_write_reg(SR_CPU_REG_ADD, hex2reg (valstr));
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> SR\n", err);
put_str_packet ("E01");
return;
}
}
else
{
/* Error response if we don't know the register */
fprintf (stderr, "Warning: Attempt to write unknown register 0x%x: "
"ignored\n", regnum);
put_str_packet ("E01");
return;
}
put_str_packet ("OK");
} /* rsp_write_reg () */
 
put_str_packet("OK");
 
} /* rsp_write_reg () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP query request
 
@param[in] p_buf The request */
/*---------------------------------------------------------------------------*/
static void
rsp_query (struct rsp_buf *p_buf)
static void rsp_query(struct rsp_buf *p_buf)
{
if (0 == strcmp ("qC", p_buf->data))
{
/* Return the current thread ID (unsigned hex). A null response
indicates to use the previously selected thread. Since we do not
support a thread concept, this is the appropriate response. */
put_str_packet ("");
}
if (0 == strncmp ("qAttached", p_buf->data, strlen ("qAttached")))
{
/* Return an indication of whether the remote server attached to an
existing process or created a new process.
Reply: '1' - The remote server attached to an existing process.
'0' - The remote server created a new process. */
put_str_packet ("1");
}
else if (0 == strncmp ("qCRC", p_buf->data, strlen ("qCRC")))
{
/* Return CRC of memory area */
fprintf (stderr, "Warning: RSP CRC query not supported\n");
put_str_packet ("E01");
}
else if (0 == strcmp ("qfThreadInfo", p_buf->data))
{
/* Return info about active threads. We return just '-1' */
put_str_packet ("m-1");
}
else if (0 == strcmp ("qsThreadInfo", p_buf->data))
{
/* Return info about more active threads. We have no more, so return the
end of list marker, 'l' */
put_str_packet ("l");
}
else if (0 == strncmp ("qGetTLSAddr:", p_buf->data, strlen ("qGetTLSAddr:")))
{
/* We don't support this feature */
put_str_packet ("");
}
else if (0 == strncmp ("qL", p_buf->data, strlen ("qL")))
{
/* Deprecated and replaced by 'qfThreadInfo' */
fprintf (stderr, "Warning: RSP qL deprecated: no info returned\n");
put_str_packet ("qM001");
}
else if (0 == strcmp ("qOffsets", p_buf->data))
{
/* Report any relocation */
put_str_packet ("Text=0;Data=0;Bss=0");
}
else if (0 == strncmp ("qP", p_buf->data, strlen ("qP")))
{
/* Deprecated and replaced by 'qThreadExtraInfo' */
fprintf (stderr, "Warning: RSP qP deprecated: no info returned\n");
put_str_packet ("");
}
else if (0 == strncmp ("qRcmd,", p_buf->data, strlen ("qRcmd,")))
{
/* This is used to interface to commands to do "stuff" */
rsp_command (p_buf);
}
else if (0 == strncmp ("qSupported", p_buf->data, strlen ("qSupported")))
{
/* 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
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
EOS so the buffer is a well formed string. */
setup_or32(); // setup cpu
char reply[GDB_BUF_MAX];
sprintf (reply, "PacketSize=%x", GDB_BUF_MAX);
put_str_packet (reply);
}
else if (0 == strncmp ("qSymbol:", p_buf->data, strlen ("qSymbol:")))
{
/* 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
do that anyway! */
put_str_packet ("OK");
}
else if (0 == strncmp ("qThreadExtraInfo,", p_buf->data,
strlen ("qThreadExtraInfo,")))
{
/* Report that we are runnable, but the text must be hex ASCI
digits. For now do this by steam, reusing the original packet */
sprintf (p_buf->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
p_buf->len = strlen (p_buf->data);
put_packet (p_buf);
}
else if (0 == strncmp ("qXfer:", p_buf->data, strlen ("qXfer:")))
{
/* For now we support no 'qXfer' requests, but these should not be
expected, since they were not reported by 'qSupported' */
fprintf (stderr, "Warning: RSP 'qXfer' not supported: ignored\n");
put_str_packet ("");
}
else if (0 == strncmp ("qTStatus", p_buf->data, strlen ("qTStatus")))
{
/* Ask the stub if there is a trace experiment running right now.
The reply has the form:
`Trunning[;field]...'
running is a single digit 1 if the trace is presently running, or 0
if not. It is followed by semicolon-separated optional fields that an
agent may use to report additional status.
*/
/* Not supported. Return empty packet */
put_str_packet ("");
}
else if ((0 == strncmp ("qTfV", p_buf->data, strlen ("qTfV"))) ||
(0 == strncmp ("qTsV", p_buf->data, strlen ("qTsV"))))
{
/*
These packets request data about trace state variables that are on the
target. gdb sends qTfV to get the first vari of data, and multiple qTsV
to get additional variables. Replies to these packets follow the syntax
of the QTDV packets that define trace state variables.
*/
put_str_packet ("");
}
else if (0 == strncmp ("qTfP", p_buf->data, strlen ("qTfP")))
{
/*
These packets request data about tracepoints that are being used by the
target. gdb sends qTfP to get the first piece of data, and multiple
qTsP to get additional pieces. Replies to these packets generally take
the form of the QTDP packets that define tracepoints. (FIXME add
detailed syntax)
*/
put_str_packet ("");
}
else
{
fprintf (stderr, "Unrecognized RSP query: ignored\n");
}
} /* rsp_query () */
if (0 == strcmp("qC", p_buf->data)) {
/* Return the current thread ID (unsigned hex). A null response
indicates to use the previously selected thread. Since we do not
support a thread concept, this is the appropriate response. */
put_str_packet("");
}
if (0 == strncmp("qAttached", p_buf->data, strlen("qAttached"))) {
/* Return an indication of whether the remote server attached to an
existing process or created a new process.
Reply: '1' - The remote server attached to an existing process.
'0' - The remote server created a new process. */
put_str_packet("1");
} else if (0 == strncmp("qCRC", p_buf->data, strlen("qCRC"))) {
/* Return CRC of memory area */
fprintf(stderr, "Warning: RSP CRC query not supported\n");
put_str_packet("E01");
} else if (0 == strcmp("qfThreadInfo", p_buf->data)) {
/* Return info about active threads. We return just '-1' */
put_str_packet("m-1");
} else if (0 == strcmp("qsThreadInfo", p_buf->data)) {
/* Return info about more active threads. We have no more, so return the
end of list marker, 'l' */
put_str_packet("l");
} else if (0 ==
strncmp("qGetTLSAddr:", p_buf->data,
strlen("qGetTLSAddr:"))) {
/* We don't support this feature */
put_str_packet("");
} else if (0 == strncmp("qL", p_buf->data, strlen("qL"))) {
/* Deprecated and replaced by 'qfThreadInfo' */
fprintf(stderr,
"Warning: RSP qL deprecated: no info returned\n");
put_str_packet("qM001");
} else if (0 == strcmp("qOffsets", p_buf->data)) {
/* Report any relocation */
put_str_packet("Text=0;Data=0;Bss=0");
} else if (0 == strncmp("qP", p_buf->data, strlen("qP"))) {
/* Deprecated and replaced by 'qThreadExtraInfo' */
fprintf(stderr,
"Warning: RSP qP deprecated: no info returned\n");
put_str_packet("");
} else if (0 == strncmp("qRcmd,", p_buf->data, strlen("qRcmd,"))) {
/* This is used to interface to commands to do "stuff" */
rsp_command(p_buf);
} else if (0 ==
strncmp("qSupported", p_buf->data, strlen("qSupported"))) {
/* 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
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
EOS so the buffer is a well formed string. */
setup_or32(); // setup cpu
char reply[GDB_BUF_MAX];
sprintf(reply, "PacketSize=%x", GDB_BUF_MAX);
put_str_packet(reply);
} else if (0 == strncmp("qSymbol:", p_buf->data, strlen("qSymbol:"))) {
/* 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
do that anyway! */
put_str_packet("OK");
} else if (0 == strncmp("qThreadExtraInfo,", p_buf->data,
strlen("qThreadExtraInfo,"))) {
/* Report that we are runnable, but the text must be hex ASCI
digits. For now do this by steam, reusing the original packet */
sprintf(p_buf->data, "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
p_buf->len = strlen(p_buf->data);
put_packet(p_buf);
} else if (0 == strncmp("qXfer:", p_buf->data, strlen("qXfer:"))) {
/* For now we support no 'qXfer' requests, but these should not be
expected, since they were not reported by 'qSupported' */
fprintf(stderr,
"Warning: RSP 'qXfer' not supported: ignored\n");
put_str_packet("");
} else if (0 == strncmp("qTStatus", p_buf->data, strlen("qTStatus"))) {
/* Ask the stub if there is a trace experiment running right now.
The reply has the form:
`Trunning[;field]...'
running is a single digit 1 if the trace is presently running, or 0
if not. It is followed by semicolon-separated optional fields that an
agent may use to report additional status.
*/
/* Not supported. Return empty packet */
put_str_packet("");
} else if ((0 == strncmp("qTfV", p_buf->data, strlen("qTfV"))) ||
(0 == strncmp("qTsV", p_buf->data, strlen("qTsV")))) {
/*
These packets request data about trace state variables that are on the
target. gdb sends qTfV to get the first vari of data, and multiple qTsV
to get additional variables. Replies to these packets follow the syntax
of the QTDV packets that define trace state variables.
*/
put_str_packet("");
} else if (0 == strncmp("qTfP", p_buf->data, strlen("qTfP"))) {
/*
These packets request data about tracepoints that are being used by the
target. gdb sends qTfP to get the first piece of data, and multiple
qTsP to get additional pieces. Replies to these packets generally take
the form of the QTDP packets that define tracepoints. (FIXME add
detailed syntax)
*/
put_str_packet("");
} else {
fprintf(stderr, "Unrecognized RSP query: ignored\n");
}
} /* rsp_query () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP qRcmd request
 
2735,147 → 2662,143
 
@param[in] p_buf The request in full */
/*---------------------------------------------------------------------------*/
static void
rsp_command (struct rsp_buf *p_buf)
static void rsp_command(struct rsp_buf *p_buf)
{
char cmd[GDB_BUF_MAX];
unsigned int regno;
uint32_t temp_uint32;
char cmd[GDB_BUF_MAX];
unsigned int regno;
uint32_t temp_uint32;
 
hex2ascii (cmd, &(p_buf->data[strlen ("qRcmd,")]));
hex2ascii(cmd, &(p_buf->data[strlen("qRcmd,")]));
 
/* Work out which command it is */
if (0 == strncmp ("readspr ", cmd, strlen ("readspr")))
{
/* Parse and return error if we fail */
if( 1 != sscanf (cmd, "readspr %4x", &regno))
{
fprintf (stderr, "Warning: qRcmd %s not recognized: ignored\n", cmd);
put_str_packet ("E01");
return;
}
/* SPR out of range */
if (regno > MAX_SPRS)
{
fprintf (stderr, "Warning: qRcmd readspr %x too large: ignored\n",
regno);
put_str_packet ("E01");
return;
}
/* Construct the reply */
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
/* Work out which command it is */
if (0 == strncmp("readspr ", cmd, strlen("readspr"))) {
/* Parse and return error if we fail */
if (1 != sscanf(cmd, "readspr %4x", &regno)) {
fprintf(stderr,
"Warning: qRcmd %s not recognized: ignored\n",
cmd);
put_str_packet("E01");
return;
}
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
// special case for NPC
if(regno == NPC_CPU_REG_ADD)
temp_uint32 = get_npc();
else
{
err = gdb_read_reg(regno, &temp_uint32);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_command at reg. %x \n", err, regno);
}
else{
reg2hex (temp_uint32, cmd);
if (DEBUG_GDB) printf("Error %d Command readspr Read reg. %x = 0x%08x\n", err, regno, temp_uint32);
}
}
// pack the result into the buffer to send back
sprintf (cmd, "%8x", (unsigned int)temp_uint32);
ascii2hex (p_buf->data, cmd);
p_buf->len = strlen (p_buf->data);
put_packet (p_buf);
}
else if (0 == strncmp ("writespr ", cmd, strlen ("writespr")))
{
unsigned int regno;
uint32_t val;
/* Parse and return error if we fail */
if( 2 != sscanf (cmd, "writespr %4x %8x", &regno, &val))
{
fprintf (stderr, "Warning: qRcmd %s not recognized: ignored\n",
cmd);
put_str_packet ("E01");
return;
}
/* SPR out of range */
if (regno > MAX_SPRS)
{
fprintf (stderr, "Warning: qRcmd writespr %x too large: ignored\n",
regno);
put_str_packet ("E01");
return;
}
/* SPR out of range */
if (regno > MAX_SPRS) {
fprintf(stderr,
"Warning: qRcmd readspr %x too large: ignored\n",
regno);
put_str_packet("E01");
return;
}
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
/* Construct the reply */
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
/* set the relevant register */
// special case for NPC
if(regno == NPC_CPU_REG_ADD)
set_npc(val);
else
{
err = gdb_write_reg(regno, val);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_command write Reg. %x = 0x%08x\n", err, regno, val);
put_str_packet ("E01");
return;
}
else{
if (DEBUG_GDB) printf("Error %d Command writespr Write reg. %x = 0x%08x\n", err, regno, val);
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
// special case for NPC
if (regno == NPC_CPU_REG_ADD)
temp_uint32 = get_npc();
else {
err = gdb_read_reg(regno, &temp_uint32);
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_command at reg. %x \n",
err, regno);
} else {
reg2hex(temp_uint32, cmd);
if (DEBUG_GDB)
printf
("Error %d Command readspr Read reg. %x = 0x%08x\n",
err, regno, temp_uint32);
}
}
 
// pack the result into the buffer to send back
sprintf(cmd, "%8x", (unsigned int)temp_uint32);
ascii2hex(p_buf->data, cmd);
p_buf->len = strlen(p_buf->data);
put_packet(p_buf);
} else if (0 == strncmp("writespr ", cmd, strlen("writespr"))) {
unsigned int regno;
uint32_t val;
 
/* Parse and return error if we fail */
if (2 != sscanf(cmd, "writespr %4x %8x", &regno, &val)) {
fprintf(stderr,
"Warning: qRcmd %s not recognized: ignored\n",
cmd);
put_str_packet("E01");
return;
}
 
/* SPR out of range */
if (regno > MAX_SPRS) {
fprintf(stderr,
"Warning: qRcmd writespr %x too large: ignored\n",
regno);
put_str_packet("E01");
return;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// First set the chain
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
 
/* set the relevant register */
// special case for NPC
if (regno == NPC_CPU_REG_ADD)
set_npc(val);
else {
 
err = gdb_write_reg(regno, val);
if (err > 0) {
if (DEBUG_GDB)
printf
("Error %d in rsp_command write Reg. %x = 0x%08x\n",
err, regno, val);
put_str_packet("E01");
return;
} else {
if (DEBUG_GDB)
printf
("Error %d Command writespr Write reg. %x = 0x%08x\n",
err, regno, val);
}
}
put_str_packet("OK");
}
put_str_packet ("OK");
}
} /* rsp_command () */
} /* rsp_command () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP set request
 
@param[in] p_buf The request */
/*---------------------------------------------------------------------------*/
static void
rsp_set (struct rsp_buf *p_buf)
static void rsp_set(struct rsp_buf *p_buf)
{
if (0 == strncmp ("QPassSignals:", p_buf->data, strlen ("QPassSignals:")))
{
/* Passing signals not supported */
put_str_packet ("");
}
else if ((0 == strncmp ("QTDP", p_buf->data, strlen ("QTDP"))) ||
(0 == strncmp ("QFrame", p_buf->data, strlen ("QFrame"))) ||
(0 == strcmp ("QTStart", p_buf->data)) ||
(0 == strcmp ("QTStop", p_buf->data)) ||
(0 == strcmp ("QTinit", p_buf->data)) ||
(0 == strncmp ("QTro", p_buf->data, strlen ("QTro"))))
{
/* All tracepoint features are not supported. This reply is really only
needed to 'QTDP', since with that the others should not be
generated. */
put_str_packet ("");
}
else
{
fprintf (stderr, "Unrecognized RSP set request: ignored\n");
}
} /* rsp_set () */
if (0 == strncmp("QPassSignals:", p_buf->data, strlen("QPassSignals:"))) {
/* Passing signals not supported */
put_str_packet("");
} else if ((0 == strncmp("QTDP", p_buf->data, strlen("QTDP"))) ||
(0 == strncmp("QFrame", p_buf->data, strlen("QFrame"))) ||
(0 == strcmp("QTStart", p_buf->data)) ||
(0 == strcmp("QTStop", p_buf->data)) ||
(0 == strcmp("QTinit", p_buf->data)) ||
(0 == strncmp("QTro", p_buf->data, strlen("QTro")))) {
/* All tracepoint features are not supported. This reply is really only
needed to 'QTDP', since with that the others should not be
generated. */
put_str_packet("");
} else {
fprintf(stderr, "Unrecognized RSP set request: ignored\n");
}
} /* rsp_set () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP restart request
 
2883,36 → 2806,35
vRun request. There is no point in unstalling the processor, since we'll
never get control back. */
/*---------------------------------------------------------------------------*/
static void
rsp_restart (void)
static void rsp_restart(void)
{
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
put_str_packet ("E01");
return;
}
// OR32 Arc sim equivalent --> set_npc (rsp.start_addr);
/* Set NPC to reset vector 0x100 */
set_npc(rsp.start_addr);
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, rsp.start_addr);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_restart write Reg. %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr);
put_str_packet ("E01");
return;
}
else{
if (DEBUG_GDB) printf("Error %d Command Reset. Set NPC to Start vector %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr);
}
*/
} /* rsp_restart () */
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
put_str_packet("E01");
return;
}
// OR32 Arc sim equivalent --> set_npc (rsp.start_addr);
/* Set NPC to reset vector 0x100 */
set_npc(rsp.start_addr);
/*
err = gdb_write_reg(NPC_CPU_REG_ADD, rsp.start_addr);
if(err > 0){
if (DEBUG_GDB) printf("Error %d in rsp_restart write Reg. %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr);
put_str_packet ("E01");
return;
}
 
else{
if (DEBUG_GDB) printf("Error %d Command Reset. Set NPC to Start vector %x = 0x%08x\n", err, NPC_CPU_REG_ADD, rsp.start_addr);
}
*/
} /* rsp_restart () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP step request
2922,61 → 2844,57
 
@param[in] p_buf The full step packet */
/*---------------------------------------------------------------------------*/
static void
rsp_step (struct rsp_buf *p_buf)
static void rsp_step(struct rsp_buf *p_buf)
{
uint32_t addr; /* The address to step from, if any */
uint32_t addr; /* The address to step from, if any */
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if(err > 0){
printf("Error %d to set RISC Debug Interface chain in the STEP command 's'\n", err);
rsp_client_close ();
return;
}
 
if (0 == strcmp ("s", p_buf->data))
{
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- Npc ---------- */
addr = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr);
if(err > 0){
printf("Error %d to read NPC in the STEP command 's'\n", err);
rsp_client_close ();
return;
// First set the chain
err = gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
if (err > 0) {
printf
("Error %d to set RISC Debug Interface chain in the STEP command 's'\n",
err);
rsp_client_close();
return;
}
*/
}
else if (1 != sscanf (p_buf->data, "s%x", &addr))
{
fprintf (stderr,
"Warning: RSP step address %s not recognized: ignored\n",
p_buf->data);
 
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr);
if(err > 0){
printf("Error %d to read NPC in the STEP command 's'\n", err);
rsp_client_close ();
return;
if (0 == strcmp("s", p_buf->data)) {
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- Npc ---------- */
addr = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr);
if(err > 0){
printf("Error %d to read NPC in the STEP command 's'\n", err);
rsp_client_close ();
return;
}
*/
} else if (1 != sscanf(p_buf->data, "s%x", &addr)) {
fprintf(stderr,
"Warning: RSP step address %s not recognized: ignored\n",
p_buf->data);
 
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
/* ---------- NPC ---------- */
addr = get_npc();
/*
err = gdb_read_reg(NPC_CPU_REG_ADD, &addr);
if(err > 0){
printf("Error %d to read NPC in the STEP command 's'\n", err);
rsp_client_close ();
return;
}
*/
}
*/
}
//if (DEBUG_GDB) printf("rsp_step() --> Read NPC = 0x%08x\n", addr);
rsp_step_generic(addr, EXCEPT_NONE);
 
//if (DEBUG_GDB) printf("rsp_step() --> Read NPC = 0x%08x\n", addr);
rsp_step_generic (addr, EXCEPT_NONE);
} /* rsp_step () */
 
} /* rsp_step () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP step with signal request
 
2984,14 → 2902,12
 
@param[in] p_buf The full step with signal packet */
/*---------------------------------------------------------------------------*/
static void
rsp_step_with_signal (struct rsp_buf *p_buf)
static void rsp_step_with_signal(struct rsp_buf *p_buf)
{
printf ("RSP step with signal '%s' received\n", p_buf->data);
printf("RSP step with signal '%s' received\n", p_buf->data);
 
} /* rsp_step_with_signal () */
} /* rsp_step_with_signal () */
 
 
/*---------------------------------------------------------------------------*/
/*!Generic processing of a step request
 
3004,47 → 2920,51
@param[in] addr Address from which to step
@param[in] except The exception to use (if any) */
/*---------------------------------------------------------------------------*/
static void
rsp_step_generic (uint32_t addr,
uint32_t except)
static void rsp_step_generic(uint32_t addr, uint32_t except)
{
uint32_t temp_uint32;
/* Set the address as the value of the next program counter */
set_npc (addr);
/* Clear Debug Reason Register (DRR) 0x3015 */
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n");
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB;
if(gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR2 register\n");
temp_uint32 &= ~SPR_DMR2_WGB;
if(gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR2 register\n");
/* Set the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */
// Arc sim --> cpu_state.sprs[SPR_DMR1] |= SPR_DMR1_ST;
if(gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR1 register\n");
temp_uint32 |= SPR_DMR1_ST;
if(gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR1 register\n");
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
if(gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32)) printf("Error read from DSR register\n");
temp_uint32 |= SPR_DSR_TE;
if(gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32)) printf("Error write to DSR register\n");
uint32_t temp_uint32;
 
/* Unstall the processor */
set_stall_state (0);
/* Set the address as the value of the next program counter */
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
set_npc(addr);
 
} /* rsp_step_generic () */
/* Clear Debug Reason Register (DRR) 0x3015 */
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
if (gdb_write_reg(DRR_CPU_REG_ADD, 0))
printf("Error write to DRR register\n");
 
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB;
if (gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32))
printf("Error read from DMR2 register\n");
temp_uint32 &= ~SPR_DMR2_WGB;
if (gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32))
printf("Error write to DMR2 register\n");
 
/* Set the single step trigger in Debug Mode Register 1 (DMR1) Register 0x3010 */
// Arc sim --> cpu_state.sprs[SPR_DMR1] |= SPR_DMR1_ST;
if (gdb_read_reg(DMR1_CPU_REG_ADD, &temp_uint32))
printf("Error read from DMR1 register\n");
temp_uint32 |= SPR_DMR1_ST;
if (gdb_write_reg(DMR1_CPU_REG_ADD, temp_uint32))
printf("Error write to DMR1 register\n");
 
/* Set traps to be handled by the debug unit in the Debug Stop Register (DSR) Register 0x3014 */
// Arc sim --> cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
if (gdb_read_reg(DSR_CPU_REG_ADD, &temp_uint32))
printf("Error read from DSR register\n");
temp_uint32 |= SPR_DSR_TE;
if (gdb_write_reg(DSR_CPU_REG_ADD, temp_uint32))
printf("Error write to DSR register\n");
 
/* Unstall the processor */
set_stall_state(0);
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
 
} /* rsp_step_generic () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP 'v' packet
 
3052,82 → 2972,71
 
@param[in] p_buf The request */
/*---------------------------------------------------------------------------*/
static void
rsp_vpkt (struct rsp_buf *p_buf)
static void rsp_vpkt(struct rsp_buf *p_buf)
{
if (0 == strncmp ("vAttach;", p_buf->data, strlen ("vAttach;")))
{
/* Attaching is a null action, since we have no other process. We just
return a stop packet (using TRAP) to indicate we are stopped. */
put_str_packet ("S05");
return;
}
else if (0 == strcmp ("vCont?", p_buf->data))
{
/* For now we don't support this. */
put_str_packet ("");
return;
}
else if (0 == strncmp ("vCont", p_buf->data, strlen ("vCont")))
{
/* This shouldn't happen, because we've reported non-support via vCont?
above */
fprintf (stderr, "Warning: RSP vCont not supported: ignored\n" );
return;
}
else if (0 == strncmp ("vFile:", p_buf->data, strlen ("vFile:")))
{
/* For now we don't support this. */
fprintf (stderr, "Warning: RSP vFile not supported: ignored\n" );
put_str_packet ("");
return;
}
else if (0 == strncmp ("vFlashErase:", p_buf->data, strlen ("vFlashErase:")))
{
/* For now we don't support this. */
fprintf (stderr, "Warning: RSP vFlashErase not supported: ignored\n" );
put_str_packet ("E01");
return;
}
else if (0 == strncmp ("vFlashWrite:", p_buf->data, strlen ("vFlashWrite:")))
{
/* For now we don't support this. */
fprintf (stderr, "Warning: RSP vFlashWrite not supported: ignored\n" );
put_str_packet ("E01");
return;
}
else if (0 == strcmp ("vFlashDone", p_buf->data))
{
/* For now we don't support this. */
fprintf (stderr, "Warning: RSP vFlashDone not supported: ignored\n" );
put_str_packet ("E01");
return;
}
else if (0 == strncmp ("vRun;", p_buf->data, strlen ("vRun;")))
{
/* We shouldn't be given any args, but check for this */
if (p_buf->len > (int) strlen ("vRun;"))
{
fprintf (stderr, "Warning: Unexpected arguments to RSP vRun "
"command: ignored\n");
if (0 == strncmp("vAttach;", p_buf->data, strlen("vAttach;"))) {
/* Attaching is a null action, since we have no other process. We just
return a stop packet (using TRAP) to indicate we are stopped. */
put_str_packet("S05");
return;
} else if (0 == strcmp("vCont?", p_buf->data)) {
/* For now we don't support this. */
put_str_packet("");
return;
} else if (0 == strncmp("vCont", p_buf->data, strlen("vCont"))) {
/* This shouldn't happen, because we've reported non-support via vCont?
above */
fprintf(stderr, "Warning: RSP vCont not supported: ignored\n");
return;
} else if (0 == strncmp("vFile:", p_buf->data, strlen("vFile:"))) {
/* For now we don't support this. */
fprintf(stderr, "Warning: RSP vFile not supported: ignored\n");
put_str_packet("");
return;
} else if (0 ==
strncmp("vFlashErase:", p_buf->data,
strlen("vFlashErase:"))) {
/* For now we don't support this. */
fprintf(stderr,
"Warning: RSP vFlashErase not supported: ignored\n");
put_str_packet("E01");
return;
} else if (0 ==
strncmp("vFlashWrite:", p_buf->data,
strlen("vFlashWrite:"))) {
/* For now we don't support this. */
fprintf(stderr,
"Warning: RSP vFlashWrite not supported: ignored\n");
put_str_packet("E01");
return;
} else if (0 == strcmp("vFlashDone", p_buf->data)) {
/* For now we don't support this. */
fprintf(stderr,
"Warning: RSP vFlashDone not supported: ignored\n");
put_str_packet("E01");
return;
} else if (0 == strncmp("vRun;", p_buf->data, strlen("vRun;"))) {
/* We shouldn't be given any args, but check for this */
if (p_buf->len > (int)strlen("vRun;")) {
fprintf(stderr,
"Warning: Unexpected arguments to RSP vRun "
"command: ignored\n");
}
 
/* Restart the current program. However unlike a "R" packet, "vRun"
should behave as though it has just stopped. We use signal
5 (TRAP). */
rsp_restart();
put_str_packet("S05");
} else {
fprintf(stderr,
"Warning: Unknown RSP 'v' packet type %s: ignored\n",
p_buf->data);
put_str_packet("E01");
return;
}
} /* rsp_vpkt () */
 
/* Restart the current program. However unlike a "R" packet, "vRun"
should behave as though it has just stopped. We use signal
5 (TRAP). */
rsp_restart ();
put_str_packet ("S05");
}
else
{
fprintf (stderr, "Warning: Unknown RSP 'v' packet type %s: ignored\n",
p_buf->data);
put_str_packet ("E01");
return;
}
} /* rsp_vpkt () */
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP write memory (binary) request
 
3144,153 → 3053,170
 
@param[in] p_buf The command received */
/*---------------------------------------------------------------------------*/
static void
rsp_write_mem_bin (struct rsp_buf *p_buf)
static void rsp_write_mem_bin(struct rsp_buf *p_buf)
{
unsigned int addr; /* Where to write the memory */
int len; /* Number of bytes to write */
char *bindat, *bindat_ptr; /* Pointer to the binary data */
int off = 0; /* Offset to start of binary data */
int newlen; /* Number of bytes in bin data */
int i;
int bytes_per_word = 4; /* Current OR implementation is 4-byte words */
unsigned int addr; /* Where to write the memory */
int len; /* Number of bytes to write */
char *bindat, *bindat_ptr; /* Pointer to the binary data */
int off = 0; /* Offset to start of binary data */
int newlen; /* Number of bytes in bin data */
int i;
int bytes_per_word = 4; /* Current OR implementation is 4-byte words */
 
if (2 != sscanf (p_buf->data, "X%x,%x:", &addr, &len))
{
fprintf (stderr, "Warning: Failed to recognize RSP write memory "
"command: %s\n", p_buf->data);
put_str_packet ("E01");
return;
}
if (2 != sscanf(p_buf->data, "X%x,%x:", &addr, &len)) {
fprintf(stderr, "Warning: Failed to recognize RSP write memory "
"command: %s\n", p_buf->data);
put_str_packet("E01");
return;
}
 
/* Find the start of the data and "unescape" it */
bindat = p_buf->data;
while(off < GDB_BUF_MAX){
if(bindat[off] == ':'){
bindat = bindat + off + 1;
off++;
break;
}
off++;
}
if(off >= GDB_BUF_MAX){
put_str_packet ("E01");
return;
}
newlen = rsp_unescape (bindat, p_buf->len - off);
/* Find the start of the data and "unescape" it */
bindat = p_buf->data;
while (off < GDB_BUF_MAX) {
if (bindat[off] == ':') {
bindat = bindat + off + 1;
off++;
break;
}
off++;
}
if (off >= GDB_BUF_MAX) {
put_str_packet("E01");
return;
}
 
/* Sanity check */
if (newlen != len)
{
int minlen = len < newlen ? len : newlen;
newlen = rsp_unescape(bindat, p_buf->len - off);
 
fprintf (stderr, "Warning: Write of %d bytes requested, but %d bytes "
"supplied. %d will be written\n", len, newlen, minlen);
len = minlen;
}
/* Sanity check */
if (newlen != len) {
int minlen = len < newlen ? len : newlen;
 
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
fprintf(stderr,
"Warning: Write of %d bytes requested, but %d bytes "
"supplied. %d will be written\n", len, newlen, minlen);
len = minlen;
}
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if(err){
put_str_packet ("E01");
return;
}
/* Write the bytes to memory */
if (len)
{
//swap_buf(bindat, len);
if (DEBUG_GDB_BLOCK_DATA){
uint32_t temp_uint32;
for (off = 0; off < len; off++){
temp_uint32 = (temp_uint32 << 8) | (0x000000ff & bindat[off]);
if((off %4 ) == 3){
//temp_uint32 = htonl(temp_uint32);
}
switch(off % 16)
{
case 3:
printf("Add 0x%08x Data 0x%08x ", addr + off - 3, temp_uint32);
break;
case 7:
case 11:
printf("0x%08x ", temp_uint32);
break;
case 15:
printf("0x%08x\n", temp_uint32);
break;
default:
break;
}
if ((len - off == 1) && (off % 16) < 15) printf("\n");
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if (err) {
put_str_packet("E01");
return;
}
}
bindat_ptr = bindat; // Copy pointer so we don't trash the original.
if (addr & 0x3) // not perfectly aligned at beginning - fix
{
if (DEBUG_GDB) {
printf("rsp_write_mem_bin: address not word aligned: 0x%.8x\n",
addr);fflush (stdout);
}
// Write enough to align us
int bytes_to_write = bytes_per_word - (addr&0x3);
if (bytes_to_write > len) bytes_to_write = len; // case of writing 1 byte to adr 0x1
if (DEBUG_GDB) {
printf("rsp_write_mem_bin: writing %d bytes of len (%d)\n",
bytes_to_write, len);fflush (stdout);
}
for (i=0;i<bytes_to_write;i++)
err = gdb_write_byte(addr+i, (uint8_t) bindat_ptr[i]);
addr += bytes_to_write; bindat_ptr += bytes_to_write;
len -= bytes_to_write;
if (DEBUG_GDB){
printf("rsp_write_mem_bin: address should now be word aligned: 0x%.8x\n", addr);
fflush (stdout);
}
 
/* Write the bytes to memory */
if (len) {
//swap_buf(bindat, len);
if (DEBUG_GDB_BLOCK_DATA) {
uint32_t temp_uint32;
for (off = 0; off < len; off++) {
temp_uint32 =
(temp_uint32 << 8) | (0x000000ff &
bindat[off]);
if ((off % 4) == 3) {
//temp_uint32 = htonl(temp_uint32);
}
switch (off % 16) {
case 3:
printf("Add 0x%08x Data 0x%08x ",
addr + off - 3, temp_uint32);
break;
case 7:
case 11:
printf("0x%08x ", temp_uint32);
break;
case 15:
printf("0x%08x\n", temp_uint32);
break;
default:
break;
}
if ((len - off == 1) && (off % 16) < 15)
printf("\n");
}
}
 
bindat_ptr = bindat; // Copy pointer so we don't trash the original.
if (addr & 0x3) // not perfectly aligned at beginning - fix
{
if (DEBUG_GDB) {
printf
("rsp_write_mem_bin: address not word aligned: 0x%.8x\n",
addr);
fflush(stdout);
}
// Write enough to align us
int bytes_to_write = bytes_per_word - (addr & 0x3);
if (bytes_to_write > len)
bytes_to_write = len; // case of writing 1 byte to adr 0x1
if (DEBUG_GDB) {
printf
("rsp_write_mem_bin: writing %d bytes of len (%d)\n",
bytes_to_write, len);
fflush(stdout);
}
 
for (i = 0; i < bytes_to_write; i++)
err =
gdb_write_byte(addr + i,
(uint8_t) bindat_ptr[i]);
 
addr += bytes_to_write;
bindat_ptr += bytes_to_write;
len -= bytes_to_write;
if (DEBUG_GDB) {
printf
("rsp_write_mem_bin: address should now be word aligned: 0x%.8x\n",
addr);
fflush(stdout);
}
}
if ((len > 3) && !err) // now write full words, if we can
{
int words_to_write = len / bytes_per_word;
if (DEBUG_GDB)
printf
("rsp_write_mem_bin: writing %d words from 0x%x, len %d bytes\n",
words_to_write, addr, len);
fflush(stdout);
 
err = gdb_write_block(addr, (uint32_t *) bindat_ptr,
(words_to_write *
bytes_per_word));
 
addr += (words_to_write * bytes_per_word);
bindat_ptr += (words_to_write * bytes_per_word);
len -= (words_to_write * bytes_per_word);
}
if (len && !err) // leftover words. Write them out
{
if (DEBUG_GDB)
printf
("rsp_write_mem_bin: writing remainder %d bytes to 0x%.8x\n",
len, addr);
fflush(stdout);
 
for (i = 0; i < len; i++)
err =
gdb_write_byte(addr + i,
(uint8_t) bindat_ptr[i]);
}
 
if (err) {
put_str_packet("E01");
return;
}
 
if (DEBUG_GDB)
printf("Error %x\n", err);
fflush(stdout);
}
if ((len > 3) && !err) // now write full words, if we can
{
int words_to_write = len/bytes_per_word;
if (DEBUG_GDB)
printf("rsp_write_mem_bin: writing %d words from 0x%x, len %d bytes\n",
words_to_write, addr, len);fflush (stdout);
err = gdb_write_block(addr, (uint32_t*)bindat_ptr,
(words_to_write*bytes_per_word));
addr+=(words_to_write*bytes_per_word);
bindat_ptr+=(words_to_write*bytes_per_word);
len-=(words_to_write*bytes_per_word);
}
if (len && !err) // leftover words. Write them out
{
if (DEBUG_GDB)
printf("rsp_write_mem_bin: writing remainder %d bytes to 0x%.8x\n",
len, addr);fflush (stdout);
for (i=0;i<len;i++)
err = gdb_write_byte(addr+i, (uint8_t) bindat_ptr[i]);
}
if(err){
put_str_packet ("E01");
return;
}
if (DEBUG_GDB) printf("Error %x\n", err);fflush (stdout);
}
put_str_packet ("OK");
} /* rsp_write_mem_bin () */
put_str_packet("OK");
 
} /* rsp_write_mem_bin () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP remove breakpoint or matchpoint request
 
3302,89 → 3228,84
 
@param[in] p_buf The command received */
/*---------------------------------------------------------------------------*/
static void
rsp_remove_matchpoint (struct rsp_buf *p_buf)
static void rsp_remove_matchpoint(struct rsp_buf *p_buf)
{
enum mp_type type; /* What sort of matchpoint */
uint32_t addr; /* Address specified */
int len; /* Matchpoint length (not used) */
struct mp_entry *mpe; /* Info about the replaced instr */
enum mp_type type; /* What sort of matchpoint */
uint32_t addr; /* Address specified */
int len; /* Matchpoint length (not used) */
struct mp_entry *mpe; /* Info about the replaced instr */
 
/* Break out the instruction */
if (3 != sscanf (p_buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len))
{
fprintf (stderr, "Warning: RSP matchpoint deletion request not "
"recognized: ignored\n");
put_str_packet ("E01");
return;
}
/* Break out the instruction */
if (3 != sscanf(p_buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len)) {
fprintf(stderr, "Warning: RSP matchpoint deletion request not "
"recognized: ignored\n");
put_str_packet("E01");
return;
}
 
/* Sanity check that the length is 4 */
if (4 != len)
{
fprintf (stderr, "Warning: RSP matchpoint deletion length %d not "
"valid: 4 assumed\n", len);
len = 4;
}
/* Sanity check that the length is 4 */
if (4 != len) {
fprintf(stderr,
"Warning: RSP matchpoint deletion length %d not "
"valid: 4 assumed\n", len);
len = 4;
}
 
/* Sort out the type of matchpoint */
switch (type)
{
case BP_MEMORY:
/* Memory breakpoint - replace the original instruction. */
mpe = mp_hash_delete (type, addr);
/* Sort out the type of matchpoint */
switch (type) {
case BP_MEMORY:
/* Memory breakpoint - replace the original instruction. */
mpe = mp_hash_delete(type, addr);
 
/* If the BP hasn't yet been deleted, put the original instruction
back. Don't forget to free the hash table entry afterwards. */
if (NULL != mpe)
{
// Arc Sim Code --> set_program32 (addr, mpe->instr);
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
/* If the BP hasn't yet been deleted, put the original instruction
back. Don't forget to free the hash table entry afterwards. */
if (NULL != mpe) {
// Arc Sim Code --> set_program32 (addr, mpe->instr);
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if(err){
put_str_packet ("E01");
return;
}
err = gdb_write_block(addr, &mpe->instr, 4);
if(err){
put_str_packet ("E01");
return;
}
free (mpe);
}
// Set chain 5 --> Wishbone Memory chain
err = gdb_set_chain(SC_WISHBONE);
if (err) {
put_str_packet("E01");
return;
}
err = gdb_write_block(addr, &mpe->instr, 4);
if (err) {
put_str_packet("E01");
return;
}
free(mpe);
}
 
put_str_packet ("OK");
return;
case BP_HARDWARE:
put_str_packet (""); /* Not supported */
return;
put_str_packet("OK");
return;
 
case WP_WRITE:
put_str_packet (""); /* Not supported */
return;
case BP_HARDWARE:
put_str_packet(""); /* Not supported */
return;
 
case WP_READ:
put_str_packet (""); /* Not supported */
return;
case WP_WRITE:
put_str_packet(""); /* Not supported */
return;
 
case WP_ACCESS:
put_str_packet (""); /* Not supported */
return;
case WP_READ:
put_str_packet(""); /* Not supported */
return;
 
default:
fprintf (stderr, "Warning: RSP matchpoint type %d not "
"recognized: ignored\n", type);
put_str_packet ("E01");
return;
case WP_ACCESS:
put_str_packet(""); /* Not supported */
return;
 
}
} /* rsp_remove_matchpoint () */
default:
fprintf(stderr, "Warning: RSP matchpoint type %d not "
"recognized: ignored\n", type);
put_str_packet("E01");
return;
 
}
} /* rsp_remove_matchpoint () */
 
/*---------------------------------------------------------------------------*/
/*!Handle a RSP insert breakpoint or matchpoint request
 
3396,83 → 3317,79
 
@param[in] p_buf The command received */
/*---------------------------------------------------------------------------*/
static void
rsp_insert_matchpoint (struct rsp_buf *p_buf)
static void rsp_insert_matchpoint(struct rsp_buf *p_buf)
{
enum mp_type type; /* What sort of matchpoint */
uint32_t addr; /* Address specified */
int len; /* Matchpoint length (not used) */
uint32_t instr;
enum mp_type type; /* What sort of matchpoint */
uint32_t addr; /* Address specified */
int len; /* Matchpoint length (not used) */
uint32_t instr;
 
/* Break out the instruction */
if (3 != sscanf (p_buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len))
{
fprintf (stderr, "Warning: RSP matchpoint insertion request not "
"recognized: ignored\n");
put_str_packet ("E01");
return;
}
/* Break out the instruction */
if (3 != sscanf(p_buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len)) {
fprintf(stderr, "Warning: RSP matchpoint insertion request not "
"recognized: ignored\n");
put_str_packet("E01");
return;
}
 
/* Sanity check that the length is 4 */
if (4 != len)
{
fprintf (stderr, "Warning: RSP matchpoint insertion length %d not "
"valid: 4 assumed\n", len);
len = 4;
}
/* Sanity check that the length is 4 */
if (4 != len) {
fprintf(stderr,
"Warning: RSP matchpoint insertion length %d not "
"valid: 4 assumed\n", len);
len = 4;
}
 
/* Sort out the type of matchpoint */
switch (type)
{
case BP_MEMORY: // software-breakpoint Z0 break
/* Memory breakpoint - substitute a TRAP instruction */
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
// Set chain 5 --> Wishbone Memory chain
gdb_set_chain(SC_WISHBONE);
// Read the data from Wishbone Memory chain
// Arc Sim Code --> mp_hash_add (type, addr, eval_direct32 (addr, 0, 0));
gdb_read_block(addr, &instr, 4);
/* Sort out the type of matchpoint */
switch (type) {
case BP_MEMORY: // software-breakpoint Z0 break
/* Memory breakpoint - substitute a TRAP instruction */
// Make sure the processor is stalled
gdb_ensure_or1k_stalled();
 
mp_hash_add (type, addr, instr);
// Set chain 5 --> Wishbone Memory chain
gdb_set_chain(SC_WISHBONE);
 
//instr = OR1K_TRAP_INSTR;
instr = ntohl(OR1K_TRAP_INSTR);// Endianess of this needs to be swapped -jb
err = gdb_write_block(addr, &instr, 4);
if(err){
put_str_packet ("E01");
return;
}
put_str_packet ("OK");
return;
case BP_HARDWARE: // hardware-breakpoint Z1 hbreak
put_str_packet (""); /* Not supported */
return;
case WP_WRITE: // write-watchpoint Z2 watch
put_str_packet (""); /* Not supported */
return;
case WP_READ: // read-watchpoint Z3 rwatch
put_str_packet (""); /* Not supported */
return;
// Read the data from Wishbone Memory chain
// Arc Sim Code --> mp_hash_add (type, addr, eval_direct32 (addr, 0, 0));
gdb_read_block(addr, &instr, 4);
 
case WP_ACCESS: // access-watchpoint Z4 awatch
put_str_packet (""); /* Not supported */
return;
mp_hash_add(type, addr, instr);
 
default:
fprintf (stderr, "Warning: RSP matchpoint type %d not "
"recognized: ignored\n", type);
put_str_packet ("E01");
return;
}
} /* rsp_insert_matchpoint () */
//instr = OR1K_TRAP_INSTR;
instr = ntohl(OR1K_TRAP_INSTR); // Endianess of this needs to be swapped -jb
err = gdb_write_block(addr, &instr, 4);
if (err) {
put_str_packet("E01");
return;
}
put_str_packet("OK");
return;
 
case BP_HARDWARE: // hardware-breakpoint Z1 hbreak
put_str_packet(""); /* Not supported */
return;
 
case WP_WRITE: // write-watchpoint Z2 watch
put_str_packet(""); /* Not supported */
return;
 
case WP_READ: // read-watchpoint Z3 rwatch
put_str_packet(""); /* Not supported */
return;
 
case WP_ACCESS: // access-watchpoint Z4 awatch
put_str_packet(""); /* Not supported */
return;
 
default:
fprintf(stderr, "Warning: RSP matchpoint type %d not "
"recognized: ignored\n", type);
put_str_packet("E01");
return;
}
} /* rsp_insert_matchpoint () */
 
/*---------------------------------------------------------------------------
Setup the or32 to init state
 
3479,26 → 3396,37
---------------------------------------------------------------------------*/
void setup_or32(void)
{
uint32_t temp_uint32;
// First set the chain
err = gdb_set_chain(SC_REGISTER); /* 4 Register Chain */
if(err > 0){
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
}
if(gdb_read_reg(0x04, &temp_uint32)) printf("Error read from register\n");
if (DEBUG_GDB) printf("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n", temp_uint32 );
if(gdb_write_reg(0x04, 0x00000001)) printf("Error write to register\n");
if (DEBUG_GDB) printf("Write to chain 4 SC_REGISTER at add 0x00000004 = 0x00000001\n");
// if(gdb_read_reg(0x04, &temp_uint32)) printf("Error read from register\n");
// if (DEBUG_GDB) printf("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n", temp_uint32 );
// if(gdb_read_reg(0x04, &temp_uint32)) printf("Error read from register\n");
// if (DEBUG_GDB) printf("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n", temp_uint32 );
if(gdb_write_reg(0x00, 0x01000001)) printf("Error write to register\n");
if (DEBUG_GDB) printf("Write to chain 4 SC_REGISTER at add 0x00000000 = 0x01000001\n");
uint32_t temp_uint32;
// First set the chain
err = gdb_set_chain(SC_REGISTER); /* 4 Register Chain */
if (err > 0) {
if (DEBUG_GDB)
printf("Error %d in gdb_set_chain\n", err);
}
if (gdb_read_reg(0x04, &temp_uint32))
printf("Error read from register\n");
if (DEBUG_GDB)
printf
("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n",
temp_uint32);
 
if (gdb_write_reg(0x04, 0x00000001))
printf("Error write to register\n");
if (DEBUG_GDB)
printf
("Write to chain 4 SC_REGISTER at add 0x00000004 = 0x00000001\n");
 
// if(gdb_read_reg(0x04, &temp_uint32)) printf("Error read from register\n");
// if (DEBUG_GDB) printf("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n", temp_uint32 );
 
// if(gdb_read_reg(0x04, &temp_uint32)) printf("Error read from register\n");
// if (DEBUG_GDB) printf("Read from chain 4 SC_REGISTER at add 0x00000004 = 0x%08x\n", temp_uint32 );
 
if (gdb_write_reg(0x00, 0x01000001))
printf("Error write to register\n");
if (DEBUG_GDB)
printf
("Write to chain 4 SC_REGISTER at add 0x00000000 = 0x01000001\n");
}
 
// Function to check if the processor is stalled - if not then stall it.
3506,141 → 3434,175
// been hard reset on the board and is running.
static void gdb_ensure_or1k_stalled()
{
unsigned char stalled;
dbg_cpu0_read_ctrl(0, &stalled);
if ((stalled & 0x1) != 0x1)
{
if (DEBUG_GDB)
printf("Processor not stalled, like we thought\n");
// Set the TAP controller to its OR1k chain
dbg_set_tap_ir(JI_DEBUG);
gdb_chain = -1;
unsigned char stalled;
dbg_cpu0_read_ctrl(0, &stalled);
if ((stalled & 0x1) != 0x1) {
if (DEBUG_GDB)
printf("Processor not stalled, like we thought\n");
 
// Processor isn't stalled, contrary to what we though, so stall it
printf("Stalling or1k\n");
dbg_cpu0_write_ctrl(0, 0x01); // stall or1k
}
// Set the TAP controller to its OR1k chain
dbg_set_tap_ir(JI_DEBUG);
gdb_chain = -1;
 
// Processor isn't stalled, contrary to what we though, so stall it
printf("Stalling or1k\n");
dbg_cpu0_write_ctrl(0, 0x01); // stall or1k
}
}
 
int gdb_write_byte(uint32_t adr, uint8_t data) {
int gdb_write_byte(uint32_t adr, uint8_t data)
{
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
 
if (DEBUG_CMDS) printf("wbyte %d\n", gdb_chain);
switch (gdb_chain) {
case SC_WISHBONE: return dbg_wb_write8(adr, data) ?
ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
if (DEBUG_CMDS)
printf("wbyte %d\n", gdb_chain);
switch (gdb_chain) {
case SC_WISHBONE:
return dbg_wb_write8(adr, data) ? ERR_CRC : ERR_NONE;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
int gdb_read_byte(uint32_t adr, uint8_t *data) {
 
int gdb_read_byte(uint32_t adr, uint8_t * data)
{
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
switch (gdb_chain) {
case SC_WISHBONE: return dbg_wb_read8(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE: *data = 0; return 0;
default: return JTAG_PROXY_INVALID_CHAIN;
}
 
switch (gdb_chain) {
case SC_WISHBONE:
return dbg_wb_read8(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE:
*data = 0;
return 0;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_reg(uint32_t adr, uint32_t data)
{
 
int gdb_write_reg(uint32_t adr, uint32_t data) {
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
 
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */
case SC_RISC_DEBUG: return dbg_cpu0_write(adr, &data, 4) ? ERR_CRC : ERR_NONE;
case SC_REGISTER: return dbg_cpu0_write_ctrl(adr, data) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE: return 0;
default: return JTAG_PROXY_INVALID_CHAIN;
}
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */
case SC_RISC_DEBUG:
return dbg_cpu0_write(adr, &data, 4) ? ERR_CRC : ERR_NONE;
case SC_REGISTER:
return dbg_cpu0_write_ctrl(adr, data) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE:
return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE:
return 0;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
int gdb_read_reg(uint32_t adr, uint32_t *data) {
 
int gdb_read_reg(uint32_t adr, uint32_t * data)
{
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
switch (gdb_chain) {
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data, 4) ? ERR_CRC : ERR_NONE;
case SC_REGISTER: return dbg_cpu0_read_ctrl(adr, (unsigned char*)data) ?
ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE: *data = 0; return 0;
default: return JTAG_PROXY_INVALID_CHAIN;
}
 
switch (gdb_chain) {
case SC_RISC_DEBUG:
return dbg_cpu0_read(adr, data, 4) ? ERR_CRC : ERR_NONE;
case SC_REGISTER:
return dbg_cpu0_read_ctrl(adr, (unsigned char *)data) ?
ERR_CRC : ERR_NONE;
case SC_WISHBONE:
return dbg_wb_read32(adr, data) ? ERR_CRC : ERR_NONE;
case SC_TRACE:
*data = 0;
return 0;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_read_block(uint32_t adr, uint32_t * data, int len)
{
 
int gdb_read_block(uint32_t adr, uint32_t *data, int len) {
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
 
if (DEBUG_CMDS) printf("rb %d\n", gdb_chain);
switch (gdb_chain) {
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data, len) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
if (DEBUG_CMDS)
printf("rb %d\n", gdb_chain);
 
switch (gdb_chain) {
case SC_RISC_DEBUG:
return dbg_cpu0_read(adr, data, len) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE:
return dbg_wb_read_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
 
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_write_block(uint32_t adr, uint32_t *data, int len) {
int gdb_write_block(uint32_t adr, uint32_t * data, int len)
{
 
#ifdef OR32_KERNEL_DBG_COMPAT
if (IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
if (kernel_debug && IS_VM_ADDR(adr))
adr = adr & ~OR32_LINUX_VM_MASK;
#endif
if (DEBUG_CMDS) printf("wb %d\n", gdb_chain);
switch (gdb_chain) {
case SC_RISC_DEBUG: return dbg_cpu0_write(adr, data, (uint32_t) len) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ? ERR_CRC : ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
 
if (DEBUG_CMDS)
printf("wb %d\n", gdb_chain);
switch (gdb_chain) {
case SC_RISC_DEBUG:
return dbg_cpu0_write(adr, data,
(uint32_t) len) ? ERR_CRC : ERR_NONE;
case SC_WISHBONE:
return dbg_wb_write_block32(adr, data,
len) ? ERR_CRC : ERR_NONE;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
 
int gdb_set_chain(int chain) {
switch (chain) {
case SC_RISC_DEBUG:
case SC_REGISTER:
case SC_TRACE:
case SC_WISHBONE: gdb_chain = chain;
return ERR_NONE;
default: return JTAG_PROXY_INVALID_CHAIN;
}
int gdb_set_chain(int chain)
{
switch (chain) {
case SC_RISC_DEBUG:
case SC_REGISTER:
case SC_TRACE:
case SC_WISHBONE:
gdb_chain = chain;
return ERR_NONE;
default:
return JTAG_PROXY_INVALID_CHAIN;
}
}
 
/*****************************************************************************
* Close the connection to the client if it is open
******************************************************************************/
static void client_close (char err)
static void client_close(char err)
{
if(gdb_fd) {
perror("gdb socket - " + err);
close(gdb_fd);
gdb_fd = 0;
}
} /* client_close () */
if (gdb_fd) {
perror("gdb socket - " + err);
close(gdb_fd);
gdb_fd = 0;
}
} /* client_close () */
 
 
/*---------------------------------------------------------------------------*/
/* Swap a buffer of 4-byte from 1234 to 4321
 
3647,71 → 3609,64
parameter[in] p_buf and len
parameter[out] none */
/*---------------------------------------------------------------------------*/
static void swap_buf(char* p_buf, int len)
static void swap_buf(char *p_buf, int len)
{
int temp;
int n = 0;
int temp;
int n = 0;
 
if (len > 2)
{
while(n < len){
// swap 0 and 3
temp = p_buf[n];
p_buf[n] = p_buf[n + 3];
p_buf[n + 3] = temp;
// swap 1 and 2
temp = p_buf[n + 1];
p_buf[n + 1] = p_buf[n + 2];
p_buf[n + 2] = temp;
n += 4;
}
}
if (len > 2) {
while (n < len) {
// swap 0 and 3
temp = p_buf[n];
p_buf[n] = p_buf[n + 3];
p_buf[n + 3] = temp;
// swap 1 and 2
temp = p_buf[n + 1];
p_buf[n + 1] = p_buf[n + 2];
p_buf[n + 2] = temp;
 
n += 4;
}
}
}
 
 
/*---------------------------------------------------------------------------*/
/*!Set the stall state of the processor
 
@param[in] state If non-zero stall the processor. */
/*---------------------------------------------------------------------------*/
static void
set_stall_state (int state)
static void set_stall_state(int state)
{
if(state == 0)
{
err = dbg_cpu0_write_ctrl(0, 0); /* unstall or1k */
stallState = UNSTALLED;
npcIsCached = 0;
rsp.sigval = TARGET_SIGNAL_NONE;
}
else
{
err = dbg_cpu0_write_ctrl(0, 0x01); /* stall or1k */
stallState = STALLED;
}
 
if(err > 0 && DEBUG_GDB)printf("Error %d in set_stall_state Stall state = %d\n", err, state);
if (state == 0) {
err = dbg_cpu0_write_ctrl(0, 0); /* unstall or1k */
stallState = UNSTALLED;
npcIsCached = 0;
rsp.sigval = TARGET_SIGNAL_NONE;
} else {
err = dbg_cpu0_write_ctrl(0, 0x01); /* stall or1k */
stallState = STALLED;
}
 
} /* set_stall_state () */
if (err > 0 && DEBUG_GDB)
printf("Error %d in set_stall_state Stall state = %d\n", err,
state);
 
} /* set_stall_state () */
 
/*---------------------------------------------------------------------------*/
/*!Set the reset bit of the processor's control reg in debug interface
*/
/*---------------------------------------------------------------------------*/
static void
reset_or1k (void)
static void reset_or1k(void)
{
//err = dbg_cpu0_write_ctrl(0, 0x02); /* reset or1k */
//if(err > 0 && DEBUG_GDB)printf("Error %d in reset_or1k()\n", err);
 
} /* reset_or1k () */
//err = dbg_cpu0_write_ctrl(0, 0x02); /* reset or1k */
 
//if(err > 0 && DEBUG_GDB)printf("Error %d in reset_or1k()\n", err);
 
} /* reset_or1k () */
 
/*---------------------------------------------------------------------------*/
/*!Close down the connection with GDB in the event of a kill signal
 
3719,6 → 3674,7
/*---------------------------------------------------------------------------*/
void gdb_close()
{
if (gdb_fd) close(gdb_fd);
// Maybe do other things here!
if (gdb_fd)
close(gdb_fd);
// Maybe do other things here!
}
/README
16,6 → 16,7
0.1.3 090604 jb@orsoc.se
0.1.4 090828 jb@orsoc.se
0.1.5 090903 jb@orsoc.se
0.1.6 110307 jb@orsoc.se
===============================================================================
-- Installation --
===============================================================================
237,30 → 238,29
usage details, run the program with no options specified.
 
user@host:~/or_debug_proxy$ ./or_debug_proxy
Usage: or_debug_proxy <SERVERTYPE> <PORT> <OPTIONS>
OpenRISC GDB Proxy Server
 
Invalid or insufficient arguments
Server Type:
-r Start a server using RSP, connection to hadware target via
USB
-j Start a server using legacy OR remote JTAG protocol, to
hardware target via USB (DEPRECATED)
 
OpenRISC GDB proxy server usage: or_debug_proxy -server_type port
Port:
Any free port within the usable range of 0 - 65535
 
server_type:
-r Start a server using RSP, connection to hadware target via
USB
-j Start a server using legacy OR remote JTAG protocol, to
hardware target via USB
-v Start a server using RSP, connection to RTL sim. VPI server
target via sockets
Options:
-k Accesses to 0xC0000000 map to 0x0. Useful for kernel debugging.
 
port_number:
Any free port within the usable range of 0 - 65535
 
Example:
Start a GDB server on port 5555, using RSP, connecting to
hardware target via USB
or_debug_proxy -r 5555
Start a GDB server on port 50001, using RSP, connecting to
hardware target via USB:
 
./or_debug_proxy -r 50001
 
* Platforms tested, and known to be working, on:
Ubuntu 8.04
Ubuntu 8.04, 9.10, 10.10
Debian
 
-------------------------------------------------------------------------------
318,26 → 318,6
same session.
 
TODO List:
* USB<->JTAG Driver TODO: Increase speed of the proxy
It appears that the current transfer rate of around 20k/s is due to
pauses in the driver. This was determined by profiling the proxy and
noticing that, over a 4-odd megabyte transfer from GDB, taking about 4
minutes, the proxy only executed for 2.5 seconds, and the three most
used functions, accounting for 50% of execution were functions in the
driver. This indicates that either better use of, or better
implementation of, the driver could dramatically increase speed.
SOLVED: It appears increasing the packet size of the GDB transfers can
achieve a significant increase in speed. GDB queries the proxy at when
it connects about its maximum packet size. It was previously 255 bytes
and this meant larger downloads were "slow". Raising this transfer size
to around 4kB (4096 bytes) resulted in a throughput increase of almost
10-times. This is due to the fact that most of the transfer time is
spent on waiting for the driver - the overhead per call is significant
if only transferring 255 bytes, so increasing the amount per transfer
reduces the amount of time waiting for the driver to perform the trans-
action. Sizes greater than 4kB, for some reason, cause the driver to
have issues - resulting in incorrect CRC reading and bad Status returns
from the driver functions. Why this is so should be investigated.
* USB<->JTAG Driver TODO:
Get the latest version of the MPSSE function code (from
http://ftdichip.com/Projects/MPSSE/FTCJTAG/FTCJTAG_Source.zip at last

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.