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/src
- from Rev 431 to Rev 497
- ↔ Reverse comparison
Rev 431 → Rev 497
/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); |
} |
/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, ¤t_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, ¤t_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", ®num)) |
{ |
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", ®num)) { |
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", ®num, 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", ®num, 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", ®no)) |
{ |
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", ®no)) { |
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", ®no, &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", ®no, &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! |
} |