Line 142... |
Line 142... |
registers, and (in our implementation) an end-of-string (0)
|
registers, and (in our implementation) an end-of-string (0)
|
character. Adding the EOS allows us to print out the packet as a
|
character. Adding the EOS allows us to print out the packet as a
|
string. So at least NUMREGBYTES*2 + 1 (for the 'G' or the EOS) are needed
|
string. So at least NUMREGBYTES*2 + 1 (for the 'G' or the EOS) are needed
|
for register packets */
|
for register packets */
|
#define GDB_BUF_MAX ((NUM_REGS) * 8 + 1)
|
#define GDB_BUF_MAX ((NUM_REGS) * 8 + 1)
|
|
//#define GDB_BUF_MAX 1500
|
|
|
/*! Size of the matchpoint hash table. Largest prime < 2^10 */
|
/*! Size of the matchpoint hash table. Largest prime < 2^10 */
|
#define MP_HASH_SIZE 1021
|
#define MP_HASH_SIZE 1021
|
|
|
/* Definition of special-purpose registers (SPRs). */
|
/* Definition of special-purpose registers (SPRs). */
|
Line 189... |
Line 190... |
#define SPR_DRR_RE 0x00000400 //!< Range fault
|
#define SPR_DRR_RE 0x00000400 //!< Range fault
|
#define SPR_DRR_SCE 0x00000800 //!< System call
|
#define SPR_DRR_SCE 0x00000800 //!< System call
|
#define SPR_DRR_FPE 0x00001000 //!< Floating point
|
#define SPR_DRR_FPE 0x00001000 //!< Floating point
|
#define SPR_DRR_TE 0x00002000 //!< Trap
|
#define SPR_DRR_TE 0x00002000 //!< Trap
|
|
|
|
/* Defines for Debug Mode Register 1 bits. */
|
|
#define SPR_DMR1_CW 0x00000003 /* Mask for CW bits */
|
|
#define SPR_DMR1_CW_AND 0x00000001 /* Chain watchpoint 0 AND */
|
|
#define SPR_DMR1_CW_OR 0x00000002 /* Chain watchpoint 0 OR */
|
|
#define SPR_DMR1_CW_SZ 2 /* Number of bits for each WP */
|
|
#define SPR_DMR1_ST 0x00400000 /* Single-step trace */
|
|
#define SPR_DMR1_BT 0x00800000 /* Branch trace */
|
|
|
|
/* Defines for Debug Mode Register 2 bits. */
|
|
#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter enable 0 */
|
|
#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter enable 1 */
|
|
#define SPR_DMR2_AWTC_MASK 0x00000ffc /* Assign watchpoints to ctr mask */
|
|
#define SPR_DMR2_WGB_MASK 0x003ff000 /* Watchpoints generaing brk mask */
|
|
#define SPR_DMR2_WBS_MASK 0xffc00000 /* Watchpoint brkpt status mask */
|
|
#define SPR_DMR2_AWTC_OFF 2 /* Assign watchpoints to ctr offset */
|
|
#define SPR_DMR2_WGB_OFF 12 /* Watchpoints generating brk offset */
|
|
#define SPR_DMR2_WBS_OFF 22 /* Watchpoint brkpt status offset */
|
|
|
/*! Definition of GDB target signals. Data taken from the GDB 6.8
|
/*! Definition of GDB target signals. Data taken from the GDB 6.8
|
source. Only those we use defined here. The exact meaning of
|
source. Only those we use defined here. The exact meaning of
|
signal number is defined by the header `include/gdb/signals.h'
|
signal number is defined by the header `include/gdb/signals.h'
|
in the GDB source code. For an explanation of what each signal
|
in the GDB source code. For an explanation of what each signal
|
Line 229... |
Line 247... |
} stallState;
|
} stallState;
|
|
|
int npcIsCached; //!< Is the NPC cached - should be bool
|
int npcIsCached; //!< Is the NPC cached - should be bool
|
uint32_t npcCachedValue; //!< Cached value of the NPC
|
uint32_t npcCachedValue; //!< Cached value of the NPC
|
|
|
|
/* Debug registers cache */
|
|
#define OR1K_MAX_MATCHPOINTS 8
|
|
|
|
enum dcr_cc {
|
|
OR1K_CC_MASKED = 0,
|
|
OR1K_CC_EQ = 1,
|
|
OR1K_CC_LT = 2,
|
|
OR1K_CC_LE = 3,
|
|
OR1K_CC_GT = 4,
|
|
OR1K_CC_GE = 5,
|
|
OR1K_CC_NE = 6,
|
|
OR1K_CC_RESERVED = 7
|
|
}; /* Compare operation */
|
|
|
|
enum dcr_ct {
|
|
OR1K_CT_DISABLED = 0, /* Disabled */
|
|
OR1K_CT_FETCH = 1, /* Compare to fetch EA */
|
|
OR1K_CT_LEA = 2, /* Compare to load EA */
|
|
OR1K_CT_SEA = 3, /* Compare to store EA */
|
|
OR1K_CT_LDATA = 4, /* Compare to load data */
|
|
OR1K_CT_SDATA = 5, /* Compare to store data */
|
|
OR1K_CT_AEA = 6, /* Compare to load/store EA */
|
|
OR1K_CT_ADATA = 7 /* Compare to load/store data */
|
|
}; /* Compare to what? */
|
|
|
|
/*! Cached OR1K debug register values (ignores counters for now). */
|
|
static struct {
|
|
uint32_t dvr[OR1K_MAX_MATCHPOINTS];
|
|
struct {
|
|
uint32_t dp : 1; /* DVR/DCP present - Read Only */
|
|
enum dcr_cc cc : 3; /* Compare condition */
|
|
uint32_t sc : 1; /* Signed comparison? */
|
|
enum dcr_ct ct : 3; /* Compare to */
|
|
uint32_t dcr_reserved : 24;
|
|
} dcr[OR1K_MAX_MATCHPOINTS];
|
|
uint32_t dmr1;
|
|
uint32_t dmr2;
|
|
uint32_t dcrw0;
|
|
uint32_t dcrw1;
|
|
uint32_t dsr;
|
|
uint32_t drr;
|
|
} or1k_dbg_group_regs_cache;
|
|
|
|
// Value to indicate status of the registers
|
|
// Init to -1, meaning we don't have a copy, 0 = clean copy, 1 = dirty copy
|
|
static int dbg_regs_cache_dirty = -1;
|
|
|
|
static uint32_t gpr_regs[MAX_GPRS]; // Static array to block read the GPRs into
|
|
|
static int err = 0;
|
static int err = 0;
|
|
|
|
|
/************************
|
/************************
|
JTAG Server Routines
|
JTAG Server Routines
|
Line 329... |
Line 396... |
static void rsp_write_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_init (void);
|
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);
|
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);
|
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);
|
|
static void get_debug_registers(void);
|
|
static void put_debug_registers(void);
|
|
static int find_free_dcrdvr_pair(void);
|
|
static int count_free_dcrdvr_pairs(void);
|
|
static int find_matching_dcrdvr_pair(uint32_t addr, uint32_t cc);
|
|
static void insert_hw_watchpoint(int wp_num, uint32_t address, uint32_t cc);
|
|
static void remove_hw_watchpoint(int wp_num);
|
|
static void enable_hw_breakpoint(int wp_num);
|
|
static void disable_hw_breakpoint(int wp_num);
|
static void rsp_remove_matchpoint (struct rsp_buf *p_buf);
|
static void rsp_remove_matchpoint (struct rsp_buf *p_buf);
|
static void rsp_insert_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_command (struct rsp_buf *p_buf);
|
static void rsp_set (struct rsp_buf *p_buf);
|
static void rsp_set (struct rsp_buf *p_buf);
|
static void rsp_restart (void);
|
static void rsp_restart (void);
|
Line 386... |
Line 462... |
rsp.client_waiting = 0; /* GDB client is not waiting for us */
|
rsp.client_waiting = 0; /* GDB client is not waiting for us */
|
rsp.client_fd = -1; /* i.e. invalid */
|
rsp.client_fd = -1; /* i.e. invalid */
|
rsp.sigval = 0; /* No exception */
|
rsp.sigval = 0; /* No exception */
|
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
|
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
|
|
|
|
/* Clear the debug registers cache */
|
|
bzero((char*) &or1k_dbg_group_regs_cache, sizeof(or1k_dbg_group_regs_cache));
|
|
|
/* Set up the matchpoint hash table */
|
/* Set up the matchpoint hash table */
|
mp_hash_init ();
|
mp_hash_init ();
|
|
|
/* RSP always starts stalled as though we have just reset the processor. */
|
/* RSP always starts stalled as though we have just reset the processor. */
|
rsp_exception (EXCEPT_TRAP);
|
rsp_exception (EXCEPT_TRAP);
|
Line 518... |
Line 597... |
stallState = STALLED;
|
stallState = STALLED;
|
npcIsCached = 0;
|
npcIsCached = 0;
|
|
|
gdb_set_chain(SC_RISC_DEBUG);
|
gdb_set_chain(SC_RISC_DEBUG);
|
|
|
// Now read the DRR (Debug Reason Register)
|
get_debug_registers();
|
gdb_read_reg(DRR_CPU_REG_ADD, &drr);
|
|
|
// Now check the DRR (Debug Reason Register)
|
|
//gdb_read_reg(DRR_CPU_REG_ADD, &drr);
|
|
drr = or1k_dbg_group_regs_cache.drr;
|
|
|
if (DEBUG_GDB) printf("DRR: 0x%08x\n", drr);
|
if (DEBUG_GDB) printf("DRR: 0x%08x\n", drr);
|
|
|
switch ((int)(drr&0xffffffff))
|
switch (drr)
|
{
|
{
|
case SPR_DRR_RSTE: rsp.sigval = TARGET_SIGNAL_PWR; break;
|
case SPR_DRR_RSTE: rsp.sigval = TARGET_SIGNAL_PWR; break;
|
case SPR_DRR_BUSEE: rsp.sigval = TARGET_SIGNAL_BUS; break;
|
case SPR_DRR_BUSEE: rsp.sigval = TARGET_SIGNAL_BUS; break;
|
case SPR_DRR_DPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
|
case SPR_DRR_DPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
|
case SPR_DRR_IPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
|
case SPR_DRR_IPFE: rsp.sigval = TARGET_SIGNAL_SEGV; break;
|
Line 775... |
Line 857... |
/* Socket is no longer needed */
|
/* Socket is no longer needed */
|
close (tmp_fd); /* No longer need this */
|
close (tmp_fd); /* No longer need this */
|
signal (SIGPIPE, SIG_IGN); /* So we don't exit if client dies */
|
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));
|
printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr));
|
|
|
} /* rsp_get_client () */
|
} /* rsp_get_client () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Deal with a request from the GDB client session
|
/*!Deal with a request from the GDB client session
|
Line 1945... |
Line 2028... |
uint32_t temp_uint32;
|
uint32_t temp_uint32;
|
|
|
/* Set the address as the value of the next program counter */
|
/* Set the address as the value of the next program counter */
|
set_npc (addr);
|
set_npc (addr);
|
|
|
/* Clear Debug Reason Register (DRR) 0x3015 */
|
or1k_dbg_group_regs_cache.drr = 0; // Clear DRR
|
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
|
or1k_dbg_group_regs_cache.dmr1 &= ~SPR_DMR1_ST; // Continuing, so disable step if it's enabled
|
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n");
|
or1k_dbg_group_regs_cache.dsr |= SPR_DSR_TE; // If breakpoints-cause-traps is not enabled
|
|
dbg_regs_cache_dirty = 1; // Always write the cache back
|
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
|
|
// Arc sim --> cpu_state.sprs[SPR_DMR2] &= ~SPR_DMR2_WGB;
|
/* Commit all debug registers */
|
if(gdb_read_reg(DMR2_CPU_REG_ADD, &temp_uint32)) printf("Error read from DMR2 register\n");
|
if (dbg_regs_cache_dirty == 1)
|
temp_uint32 &= ~SPR_DMR2_WGB;
|
put_debug_registers();
|
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 */
|
/* Unstall the processor */
|
set_stall_state (0);
|
set_stall_state (0);
|
|
|
|
/* Debug regs cache is now invalid */
|
|
dbg_regs_cache_dirty = -1;
|
|
|
/* Note the GDB client is now waiting for a reply. */
|
/* Note the GDB client is now waiting for a reply. */
|
rsp.client_waiting = 1;
|
rsp.client_waiting = 1;
|
|
|
} /* rsp_continue_generic () */
|
} /* rsp_continue_generic () */
|
|
|
Line 2000... |
Line 2073... |
// First set the chain
|
// First set the chain
|
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
|
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
|
|
|
|
|
// Read all GPRs
|
// Read all GPRs
|
|
gdb_read_block(0x400, (uint32_t *) &gpr_regs, MAX_GPRS*4);
|
|
|
for (r = 0; r < MAX_GPRS; r++){
|
for (r = 0; r < MAX_GPRS; r++){
|
|
|
err = gdb_read_reg(0x400 + r, &temp_uint32);
|
/*err = gdb_read_reg(0x400 + r, &temp_uint32);
|
if(err > 0){
|
if(err > 0){
|
if (DEBUG_GDB) printf("Error %d in gdb_read_reg at reg. %d\n", err, r);
|
if (DEBUG_GDB) printf("Error %d in gdb_read_reg at reg. %d\n", err, r);
|
put_str_packet ("E01");
|
put_str_packet ("E01");
|
return;
|
return;
|
}
|
}
|
reg2hex (temp_uint32, &(buffer.data[r * 8]));
|
*/
|
|
reg2hex (gpr_regs[r], &(buffer.data[r * 8]));
|
|
|
if (DEBUG_GDB_DUMP_DATA){
|
if (DEBUG_GDB_DUMP_DATA){
|
switch(r % 4)
|
switch(r % 4)
|
{
|
{
|
case 0:
|
case 0:
|
Line 2027... |
Line 2103... |
break;
|
break;
|
default:
|
default:
|
break;
|
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);
|
/* Read NPC,PPC and SR regs, they are consecutive in CPU, at adr. 16, 17 and 18 */
|
|
uint32_t pcs_and_sr[3];
|
|
gdb_read_block(NPC_CPU_REG_ADD, (uint32_t *)pcs_and_sr, 3 * 4);
|
|
|
|
reg2hex (pcs_and_sr[0], &(buffer.data[NPC_REGNUM * 8]));
|
|
reg2hex (pcs_and_sr[1], &(buffer.data[SR_REGNUM * 8]));
|
|
reg2hex (pcs_and_sr[2], &(buffer.data[PPC_REGNUM * 8]));
|
|
|
|
if (DEBUG_GDB_DUMP_DATA) printf("PPC 0x%08x\n", pcs_and_sr[2]);
|
|
if (DEBUG_GDB_DUMP_DATA) printf("NPC 0x%08x\n", pcs_and_sr[0]);
|
|
if (DEBUG_GDB_DUMP_DATA) printf("SR 0x%08x\n", pcs_and_sr[1]);
|
|
|
/* Finalize the packet and send it */
|
/* Finalize the packet and send it */
|
buffer.data[NUM_REGS * 8] = 0;
|
buffer.data[NUM_REGS * 8] = 0;
|
buffer.len = NUM_REGS * 8;
|
buffer.len = NUM_REGS * 8;
|
|
|
Line 2088... |
Line 2145... |
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
rsp_write_all_regs (struct rsp_buf *p_buf)
|
rsp_write_all_regs (struct rsp_buf *p_buf)
|
{
|
{
|
uint32_t regnum; /* Register index */
|
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
|
// Make sure the processor is stalled
|
gdb_ensure_or1k_stalled();
|
gdb_ensure_or1k_stalled();
|
|
|
// First set the chain
|
// First set the chain
|
Line 2112... |
Line 2159... |
return;
|
return;
|
}
|
}
|
|
|
/* ---------- GPRS ---------- */
|
/* ---------- GPRS ---------- */
|
for (regnum = 0; regnum < MAX_GPRS; regnum++)
|
for (regnum = 0; regnum < MAX_GPRS; regnum++)
|
{
|
gpr_regs[regnum] = hex2reg (&p_buf->data[regnum * 8 + 1]);
|
err = gdb_write_reg(0x400 + regnum, hex2reg (&p_buf->data[regnum * 8 + 1]));
|
|
if(err > 0){
|
/* Do a block write */
|
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> GPRS\n", err);
|
gdb_write_block(0x400, (uint32_t *) gpr_regs, MAX_GPRS*32);
|
put_str_packet ("E01");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* ---------- PPC ---------- */
|
/* ---------- 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 ---------- */
|
/* ---------- SR ---------- */
|
err = gdb_write_reg(SR_CPU_REG_ADD, hex2reg (&p_buf->data[SR_REGNUM * 8 + 1]));
|
/* Write PPC and SR regs, they are consecutive in CPU, at adr. 17 and 18 */
|
if(err > 0){
|
/* We handle NPC specially */
|
if (DEBUG_GDB) printf("Error %d in rsp_write_reg write --> SR\n", err);
|
uint32_t pcs_and_sr[2];
|
put_str_packet ("E01");
|
pcs_and_sr[0] = hex2reg (&p_buf->data[SR_REGNUM * 8 + 1]);
|
return;
|
pcs_and_sr[1] = hex2reg (&p_buf->data[PPC_REGNUM * 8 + 1]);
|
}
|
|
|
gdb_write_block(SR_CPU_REG_ADD, (uint32_t *)pcs_and_sr, 2 * 4);
|
|
|
/* ---------- NPC ---------- */
|
/* ---------- NPC ---------- */
|
set_npc(hex2reg (&p_buf->data[NPC_REGNUM * 8 + 1]));
|
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
|
/* Acknowledge. TODO: We always succeed at present, even if the data was
|
defective. */
|
defective. */
|
|
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|
} /* rsp_write_all_regs () */
|
} /* rsp_write_all_regs () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
Line 2761... |
Line 2794... |
gdb_ensure_or1k_stalled();
|
gdb_ensure_or1k_stalled();
|
|
|
// First set the chain
|
// First set the chain
|
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
|
gdb_set_chain(SC_RISC_DEBUG); /* 1 RISC Debug Interface chain */
|
|
|
// special case for NPC
|
/* special case for NPC */
|
if(regno == NPC_CPU_REG_ADD)
|
if(regno == NPC_CPU_REG_ADD)
|
temp_uint32 = get_npc();
|
temp_uint32 = get_npc();
|
|
/* Also special case for debug group (group 6) registers */
|
|
else if (((regno >> OR1K_SPG_SIZE_BITS) & 0xff) == OR1K_SPG_DEBUG)
|
|
{
|
|
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them
|
|
get_debug_registers();
|
|
|
|
uint32_t * dbg_reg_array = (uint32_t *) &or1k_dbg_group_regs_cache;
|
|
temp_uint32 = dbg_reg_array[(regno & 0xff)];
|
|
dbg_regs_cache_dirty = 0;
|
|
}
|
else
|
else
|
{
|
{
|
err = gdb_read_reg(regno, &temp_uint32);
|
err = gdb_read_reg(regno, &temp_uint32);
|
if(err > 0){
|
if(err > 0){
|
if (DEBUG_GDB) printf("Error %d in rsp_command at reg. %x \n", err, regno);
|
if (DEBUG_GDB) printf("Error %d in rsp_command at reg. %x \n", err, regno);
|
Line 2815... |
Line 2858... |
|
|
/* set the relevant register */
|
/* set the relevant register */
|
// special case for NPC
|
// special case for NPC
|
if(regno == NPC_CPU_REG_ADD)
|
if(regno == NPC_CPU_REG_ADD)
|
set_npc(val);
|
set_npc(val);
|
|
/* Also special case for debug group (group 6) registers */
|
|
else if (((regno >> OR1K_SPG_SIZE_BITS) & 0xff) == OR1K_SPG_DEBUG)
|
|
{
|
|
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them
|
|
get_debug_registers();
|
|
|
|
uint32_t * dbg_reg_array = (uint32_t *) &or1k_dbg_group_regs_cache;
|
|
dbg_reg_array[(regno & 0xff)] = val;
|
|
dbg_regs_cache_dirty = 1;
|
|
}
|
else
|
else
|
{
|
{
|
|
|
err = gdb_write_reg(regno, val);
|
err = gdb_write_reg(regno, val);
|
if(err > 0){
|
if(err > 0){
|
Line 2885... |
Line 2938... |
if(err > 0){
|
if(err > 0){
|
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
|
if (DEBUG_GDB) printf("Error %d in gdb_set_chain\n", err);
|
put_str_packet ("E01");
|
put_str_packet ("E01");
|
return;
|
return;
|
}
|
}
|
// OR32 Arc sim equivalent --> set_npc (rsp.start_addr);
|
|
/* Set NPC to reset vector 0x100 */
|
/* Set NPC to reset vector 0x100 */
|
set_npc(rsp.start_addr);
|
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 () */
|
} /* rsp_restart () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Handle a RSP step request
|
/*!Handle a RSP step request
|
Line 2929... |
Line 2971... |
return;
|
return;
|
}
|
}
|
|
|
if (0 == strcmp ("s", p_buf->data))
|
if (0 == strcmp ("s", p_buf->data))
|
{
|
{
|
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
|
|
/* ---------- Npc ---------- */
|
/* ---------- Npc ---------- */
|
addr = get_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))
|
else if (1 != sscanf (p_buf->data, "s%x", &addr))
|
{
|
{
|
fprintf (stderr,
|
fprintf (stderr,
|
"Warning: RSP step address %s not recognized: ignored\n",
|
"Warning: RSP step address %s not recognized: ignored\n",
|
p_buf->data);
|
p_buf->data);
|
|
|
// Arc Sim Code --> addr = cpu_state.pc; /* Default uses current NPC */
|
|
/* ---------- NPC ---------- */
|
/* ---------- NPC ---------- */
|
addr = get_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);
|
rsp_step_generic (addr, EXCEPT_NONE);
|
|
|
} /* rsp_step () */
|
} /* rsp_step () */
|
|
|
|
|
Line 3003... |
Line 3026... |
|
|
/* Set the address as the value of the next program counter */
|
/* Set the address as the value of the next program counter */
|
|
|
set_npc (addr);
|
set_npc (addr);
|
|
|
/* Clear Debug Reason Register (DRR) 0x3015 */
|
or1k_dbg_group_regs_cache.drr = 0; // Clear DRR
|
// Arc sim --> cpu_state.sprs[SPR_DRR] = 0;
|
or1k_dbg_group_regs_cache.dmr1 |= SPR_DMR1_ST; // Stepping, so enable step in DMR1
|
if(gdb_write_reg(DRR_CPU_REG_ADD, 0)) printf("Error write to DRR register\n");
|
or1k_dbg_group_regs_cache.dsr |= SPR_DSR_TE; // Enable trap handled by DU
|
|
or1k_dbg_group_regs_cache.dmr2 &= ~SPR_DMR2_WGB; // Stepping, so disable breakpoints from watchpoints
|
/* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) 0x3011 */
|
dbg_regs_cache_dirty = 1; // Always write the cache back
|
// 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");
|
/* Commit all debug registers */
|
temp_uint32 &= ~SPR_DMR2_WGB;
|
if (dbg_regs_cache_dirty == 1)
|
if(gdb_write_reg(DMR2_CPU_REG_ADD, temp_uint32)) printf("Error write to DMR2 register\n");
|
put_debug_registers();
|
|
|
/* 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 */
|
/* Unstall the processor */
|
set_stall_state (0);
|
set_stall_state (0);
|
|
|
|
/* Debug regs cache now in invalid state */
|
|
dbg_regs_cache_dirty = -1;
|
|
|
/* Note the GDB client is now waiting for a reply. */
|
/* Note the GDB client is now waiting for a reply. */
|
rsp.client_waiting = 1;
|
rsp.client_waiting = 1;
|
|
|
} /* rsp_step_generic () */
|
} /* rsp_step_generic () */
|
|
|
Line 3262... |
Line 3276... |
}
|
}
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|
|
|
} /* rsp_write_mem_bin () */
|
} /* rsp_write_mem_bin () */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Copy the debug group registers from the processor into our cache struct
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
get_debug_registers(void)
|
|
{
|
|
|
|
if (dbg_regs_cache_dirty != -1) return; // Don't need to update them
|
|
|
|
if (DEBUG_GDB)
|
|
printf("gdb - get_debug_registers() - reading %d bytes for debug regs\n",sizeof(or1k_dbg_group_regs_cache));
|
|
|
|
|
|
err = gdb_set_chain(SC_RISC_DEBUG); /* Register Chain */
|
|
/* Fill our debug group registers struct */
|
|
gdb_read_block((OR1K_SPG_DEBUG << OR1K_SPG_SIZE_BITS),
|
|
(uint32_t *) &or1k_dbg_group_regs_cache,
|
|
(uint32_t) sizeof(or1k_dbg_group_regs_cache));
|
|
dbg_regs_cache_dirty = 0; // Just updated it so not dirty
|
|
|
|
if (DEBUG_GDB)
|
|
{
|
|
printf("gdb - get_debug_registers() - registers:\n\t");
|
|
uint32_t * regs_ptr = (uint32_t*) &or1k_dbg_group_regs_cache;
|
|
int i;
|
|
for(i=0;i<(sizeof(or1k_dbg_group_regs_cache)/4);i++)
|
|
{ if (i%4==0)printf("\n\t");
|
|
if (i<8)
|
|
printf("DVR%.2d %.8x ",i,regs_ptr[i]);
|
|
else if (i<16)
|
|
printf("DCR%.2d %.8x ",i-8,regs_ptr[i]);
|
|
else if (i<17)
|
|
printf("DMR1 %.8x ",regs_ptr[i]);
|
|
else if (i<18)
|
|
printf("DMR2 %.8x ",regs_ptr[i]);
|
|
else if (i<19)
|
|
printf("DCWR0 %.8x ",regs_ptr[i]);
|
|
else if (i<20)
|
|
printf("DCWR1 %.8x ",regs_ptr[i]);
|
|
else if (i<21)
|
|
printf("DSR %.8x ",regs_ptr[i]);
|
|
else if (i<22)
|
|
printf("DRR %.8x ",regs_ptr[i]);
|
|
|
|
}
|
|
printf("\n");
|
|
}
|
|
return;
|
|
} /* get_debug_registers() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Copy the debug group registers from our cache to the processor
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
put_debug_registers(void)
|
|
{
|
|
/* TODO: Block CPU registers write functionality */
|
|
if (DEBUG_GDB) printf("gdb - put_debug_registers()\n");
|
|
int i;
|
|
uint32_t *dbg_regs_ptr = (uint32_t *) &or1k_dbg_group_regs_cache;
|
|
|
|
if (DEBUG_GDB)
|
|
{
|
|
printf("gdb - put_debug_registers() - registers:\n\t");
|
|
uint32_t * regs_ptr = (uint32_t*) &or1k_dbg_group_regs_cache;
|
|
int i;
|
|
for(i=0;i<(sizeof(or1k_dbg_group_regs_cache)/4);i++)
|
|
{ if (i%4==0)printf("\n\t");
|
|
if (i<8)
|
|
printf("DVR%.2d %.8x ",i,regs_ptr[i]);
|
|
else if (i<16)
|
|
printf("DCR%.2d %.8x ",i-8,regs_ptr[i]);
|
|
else if (i<17)
|
|
printf("DMR1 %.8x ",regs_ptr[i]);
|
|
else if (i<18)
|
|
printf("DMR2 %.8x ",regs_ptr[i]);
|
|
else if (i<19)
|
|
printf("DCWR0 %.8x ",regs_ptr[i]);
|
|
else if (i<20)
|
|
printf("DCWR1 %.8x ",regs_ptr[i]);
|
|
else if (i<21)
|
|
printf("DSR %.8x ",regs_ptr[i]);
|
|
else if (i<22)
|
|
printf("DRR %.8x ",regs_ptr[i]);
|
|
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
err = gdb_set_chain(SC_RISC_DEBUG); /* Register Chain */
|
|
|
|
gdb_write_block((OR1K_SPG_DEBUG << OR1K_SPG_SIZE_BITS),
|
|
(uint32_t *) &or1k_dbg_group_regs_cache,
|
|
sizeof(or1k_dbg_group_regs_cache));
|
|
|
|
return;
|
|
|
|
} /* put_debug_registers() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Find the DVR/DCR pair corresponding to the address
|
|
|
|
@return the number, 0-7 of the DCR/DVR pair, if possible, -1 else. */
|
|
/*---------------------------------------------------------------------------*/
|
|
static int
|
|
find_matching_dcrdvr_pair(uint32_t addr, uint32_t cc)
|
|
{
|
|
int i;
|
|
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++)
|
|
{
|
|
// Find the one matching according to address, and in use
|
|
if ((or1k_dbg_group_regs_cache.dvr[i] == addr) &&
|
|
(or1k_dbg_group_regs_cache.dcr[i].cc == cc))
|
|
{
|
|
/*
|
|
if (DEBUG_GDB) printf("gdb - find_matching_dcrdvr_pair(%.8x, %d)\n",addr, cc);
|
|
if (DEBUG_GDB) printf("gdb - find_matching_dcrdvr_pair match in %d: dvr[%d] = %.8x dcr[%d].cc=%d\n",
|
|
i,i,or1k_dbg_group_regs_cache.dvr[i],i,or1k_dbg_group_regs_cache.dcr[i].cc);
|
|
*/
|
|
return i;
|
|
}
|
|
}
|
|
|
|
// If the loop finished, no appropriate matchpoints
|
|
return -1;
|
|
} /* find_matching_dcrdvr_pair() */
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Count number of free DCR/DVR pairs
|
|
|
|
@return the number, 0-7 */
|
|
/*---------------------------------------------------------------------------*/
|
|
static int
|
|
count_free_dcrdvr_pairs(void)
|
|
{
|
|
int i, free=0;
|
|
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++)
|
|
{
|
|
if ((or1k_dbg_group_regs_cache.dcr[i].cc == OR1K_CC_MASKED) // If compare condition is masked, it's not used
|
|
&& or1k_dbg_group_regs_cache.dcr[i].dp ) // and the debug point is present
|
|
free++;
|
|
}
|
|
|
|
|
|
return free;
|
|
} /* count_free_dcrdvr_pairs() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Find a free hardware breakpoint register, DCR/DVR pair
|
|
|
|
@return the number, 0-7 of the DCR/DVR pair, if possible, -1 else. */
|
|
/*---------------------------------------------------------------------------*/
|
|
static int
|
|
find_free_dcrdvr_pair(void)
|
|
{
|
|
int i;
|
|
for (i=0;i<OR1K_MAX_MATCHPOINTS; i++)
|
|
{
|
|
if ((or1k_dbg_group_regs_cache.dcr[i].cc == OR1K_CC_MASKED) // If compare condition is masked, it's not used
|
|
&& or1k_dbg_group_regs_cache.dcr[i].dp ) // and the debug point is present
|
|
return i;
|
|
}
|
|
|
|
// If the loop finished, no free matchpoints
|
|
return -1;
|
|
} /* find_free_dcrdvr_pair() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Setup a DCR/DVR pair for our watchpoint.
|
|
@param[in] wp_num The watchpoint number
|
|
@param[in] address The address for watchpoint
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
insert_hw_watchpoint(int wp_num, uint32_t address, uint32_t cc)
|
|
{
|
|
if (DEBUG_GDB) printf("gdb - insert_hw_watchpoint(%d, 0x%.8x)\n",wp_num, address);
|
|
or1k_dbg_group_regs_cache.dvr[wp_num] = address;
|
|
|
|
or1k_dbg_group_regs_cache.dcr[wp_num].cc = cc;
|
|
or1k_dbg_group_regs_cache.dcr[wp_num].sc = 0;
|
|
or1k_dbg_group_regs_cache.dcr[wp_num].ct = OR1K_CT_FETCH; // Instruction fetch address
|
|
|
|
// Mark the debug reg cache as dirty
|
|
dbg_regs_cache_dirty = 1;
|
|
return;
|
|
|
|
} /* insert_hw_watchpoint() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Remove/free a DCR/DVR watchpoint pair
|
|
@param[in] wp_num The watchpoint number
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
remove_hw_watchpoint(int wp_num)
|
|
{
|
|
or1k_dbg_group_regs_cache.dvr[wp_num] = 0;
|
|
|
|
or1k_dbg_group_regs_cache.dcr[wp_num].cc = OR1K_CC_MASKED; // We only do equals for now
|
|
or1k_dbg_group_regs_cache.dcr[wp_num].sc = 0;
|
|
|
|
/* Auto-disable it as generating a breakpoint, too, although maybe gets done after
|
|
this call anyway. Best to ensure. */
|
|
disable_hw_breakpoint(wp_num);
|
|
|
|
// Mark the debug reg cache as dirty
|
|
dbg_regs_cache_dirty = 1;
|
|
return;
|
|
|
|
} /* remove_hw_watchpoint() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Enable a DCR/DVR watchpoint to generate a breakpoint
|
|
@param[in] wp_num The watchpoint number
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
enable_hw_breakpoint(int wp_num)
|
|
{
|
|
// Set the corresponding bit in DMR2 to enable matchpoint 'num' to trigger a breakpoint
|
|
or1k_dbg_group_regs_cache.dmr2 |= (uint32_t) (1 << (SPR_DMR2_WGB_OFF + wp_num));
|
|
// Mark the debug reg cache as dirty
|
|
dbg_regs_cache_dirty = 1;
|
|
return;
|
|
} /* enable_hw_breakpoint() */
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Disable a DCR/DVR watchpoint from generating a breakpoint
|
|
@param[in] wp_num The watchpoint number
|
|
*/
|
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
disable_hw_breakpoint(int wp_num)
|
|
{
|
|
// Set the corresponding bit in DMR2 to enable matchpoint 'num' to trigger a breakpoint
|
|
or1k_dbg_group_regs_cache.dmr2 &= (uint32_t) ~(1 << (SPR_DMR2_WGB_OFF + wp_num));
|
|
// Mark the debug reg cache as dirty
|
|
dbg_regs_cache_dirty = 1;
|
|
return;
|
|
} /* disable_hw_breakpoint() */
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Handle a RSP remove breakpoint or matchpoint request
|
/*!Handle a RSP remove breakpoint or matchpoint request
|
|
|
For now only memory breakpoints are implemented, which are implemented by
|
For now only memory breakpoints are implemented, which are implemented by
|
Line 3281... |
Line 3537... |
{
|
{
|
enum mp_type type; /* What sort of matchpoint */
|
enum mp_type type; /* What sort of matchpoint */
|
uint32_t addr; /* Address specified */
|
uint32_t addr; /* Address specified */
|
int len; /* Matchpoint length (not used) */
|
int len; /* Matchpoint length (not used) */
|
struct mp_entry *mpe; /* Info about the replaced instr */
|
struct mp_entry *mpe; /* Info about the replaced instr */
|
|
int wp_num;
|
|
|
/* Break out the instruction */
|
/* Break out the instruction */
|
if (3 != sscanf (p_buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len))
|
if (3 != sscanf (p_buf->data, "z%1d,%x,%1d", (int *)&type, &addr, &len))
|
{
|
{
|
fprintf (stderr, "Warning: RSP matchpoint deletion request not "
|
fprintf (stderr, "Warning: RSP matchpoint deletion request not "
|
Line 3332... |
Line 3589... |
|
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|
return;
|
return;
|
|
|
case BP_HARDWARE:
|
case BP_HARDWARE:
|
put_str_packet (""); /* Not supported */
|
/* Adding support -- jb 090901 */
|
|
if (dbg_regs_cache_dirty == -1) // Regs invalid, get them
|
|
get_debug_registers();
|
|
|
|
if (DEBUG_GDB) printf("gdb - rsp_remove_matchpoint() - hardware mp remove at addr %.8x\n",addr);
|
|
#ifdef HWBP_BTWN
|
|
// Find the first of the pair of dcr/dvr registers
|
|
wp_num = find_matching_dcrdvr_pair(addr-4,OR1K_CC_GE);
|
|
#else
|
|
wp_num = find_matching_dcrdvr_pair(addr,OR1K_CC_EQ);
|
|
remove_hw_watchpoint(wp_num);
|
|
#endif
|
|
if ( wp_num < 0 )
|
|
{
|
|
printf("gdb - rsp_remove_matchpoint() failed to remove hardware breakpoint at addr %.8x\n",
|
|
addr);
|
|
put_str_packet ("E01"); /* Cannot remove */
|
|
return;
|
|
}
|
|
|
|
if (DEBUG_GDB) printf("gdb - rsp_remove_matchpoint() - mp to remove in DCR/DVR pair %d \n",wp_num);
|
|
remove_hw_watchpoint(wp_num);
|
|
|
|
#ifdef HWBP_BTWN
|
|
wp_num++;
|
|
/* Should probably check here that this is correct. Oh well. */
|
|
remove_hw_watchpoint(wp_num);
|
|
// Unchain these
|
|
or1k_dbg_group_regs_cache.dmr1 &= ~(SPR_DMR1_CW << (wp_num * SPR_DMR1_CW_SZ));
|
|
#endif
|
|
|
|
// Disable breakpoint generation
|
|
disable_hw_breakpoint(wp_num);
|
|
|
|
|
|
put_str_packet ("OK");
|
return;
|
return;
|
|
|
case WP_WRITE:
|
case WP_WRITE:
|
put_str_packet (""); /* Not supported */
|
put_str_packet (""); /* Not supported */
|
return;
|
return;
|
Line 3356... |
Line 3648... |
return;
|
return;
|
|
|
}
|
}
|
} /* rsp_remove_matchpoint () */
|
} /* rsp_remove_matchpoint () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Handle a RSP insert breakpoint or matchpoint request
|
/*!Handle a RSP insert breakpoint or matchpoint request
|
|
|
For now only memory breakpoints are implemented, which are implemented by
|
For now only memory breakpoints are implemented, which are implemented by
|
substituting a breakpoint at the specified address. The implementation must
|
substituting a breakpoint at the specified address. The implementation must
|
Line 3375... |
Line 3666... |
{
|
{
|
enum mp_type type; /* What sort of matchpoint */
|
enum mp_type type; /* What sort of matchpoint */
|
uint32_t addr; /* Address specified */
|
uint32_t addr; /* Address specified */
|
int len; /* Matchpoint length (not used) */
|
int len; /* Matchpoint length (not used) */
|
uint32_t instr;
|
uint32_t instr;
|
|
int wp_num;
|
|
|
/* Break out the instruction */
|
/* Break out the instruction */
|
if (3 != sscanf (p_buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len))
|
if (3 != sscanf (p_buf->data, "Z%1d,%x,%1d", (int *)&type, &addr, &len))
|
{
|
{
|
fprintf (stderr, "Warning: RSP matchpoint insertion request not "
|
fprintf (stderr, "Warning: RSP matchpoint insertion request not "
|
Line 3421... |
Line 3713... |
}
|
}
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|
return;
|
return;
|
|
|
case BP_HARDWARE: // hardware-breakpoint Z1 hbreak
|
case BP_HARDWARE: // hardware-breakpoint Z1 hbreak
|
put_str_packet (""); /* Not supported */
|
/* Adding support -- jb 090901 */
|
|
get_debug_registers(); // First update our copy of the debug registers
|
|
|
|
#ifdef HWBP_BTWN
|
|
if (count_free_dcrdvr_pairs() < 2) /* Need at least two spare watchpoints free */
|
|
put_str_packet (""); /* Cannot add */
|
|
#endif
|
|
|
|
wp_num = find_free_dcrdvr_pair();
|
|
|
|
if (wp_num == -1)
|
|
{
|
|
put_str_packet (""); /* Could not find a place to put the breakpoint */
|
|
|
|
}
|
|
|
|
#ifdef HWBP_BTWN
|
|
if ((wp_num >= OR1K_MAX_MATCHPOINTS-1)
|
|
|| (wp_num %2 != 0)) /* Should have gotten either, 0,2,4,6 */
|
|
{
|
|
/* Something is wrong - can't do it */
|
|
put_str_packet ("");
|
|
return;
|
|
}
|
|
|
|
// First watchpoint to watch for address greater than the address
|
|
insert_hw_watchpoint(wp_num, addr-4, OR1K_CC_GE);
|
|
|
|
wp_num++; // The watchpoints should be next to each other.
|
|
|
|
// Second watchpoint to watch for address less than the address
|
|
insert_hw_watchpoint(wp_num, addr+4, OR1K_CC_LE);
|
|
|
|
// Chain these two together
|
|
// First clear the chain settings for this wp (2 bits per)
|
|
or1k_dbg_group_regs_cache.dmr1 &= ~(SPR_DMR1_CW << (wp_num * SPR_DMR1_CW_SZ));
|
|
// We will trigger a match when wp-1 {_-*{>AND<}*-_} wp go off.
|
|
or1k_dbg_group_regs_cache.dmr1 |= (SPR_DMR1_CW_AND << (wp_num * SPR_DMR1_CW_SZ));
|
|
// Now enable this send wp (the higher of the two) to trigger a matchpoint
|
|
#else
|
|
/* Simply insert a watchpoint at the address */
|
|
insert_hw_watchpoint(wp_num, addr, OR1K_CC_EQ);
|
|
|
|
#endif
|
|
|
|
enable_hw_breakpoint(wp_num);
|
|
put_str_packet ("OK");
|
return;
|
return;
|
|
|
case WP_WRITE: // write-watchpoint Z2 watch
|
case WP_WRITE: // write-watchpoint Z2 watch
|
put_str_packet (""); /* Not supported */
|
put_str_packet (""); /* Not supported */
|
return;
|
return;
|
Line 3503... |
Line 3841... |
|
|
|
|
int gdb_read_reg(uint32_t adr, uint32_t *data) {
|
int gdb_read_reg(uint32_t adr, uint32_t *data) {
|
if (DEBUG_CMDS) printf("rreg %d\n", gdb_chain);
|
if (DEBUG_CMDS) printf("rreg %d\n", gdb_chain);
|
switch (gdb_chain) {
|
switch (gdb_chain) {
|
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data) ? ERR_CRC : ERR_NONE;
|
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) ?
|
case SC_REGISTER: return dbg_cpu0_read_ctrl(adr, (unsigned char*)data) ?
|
ERR_CRC : ERR_NONE;
|
ERR_CRC : ERR_NONE;
|
case SC_WISHBONE: return dbg_wb_read32(adr, 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;
|
case SC_TRACE: *data = 0; return 0;
|
default: return JTAG_PROXY_INVALID_CHAIN;
|
default: return JTAG_PROXY_INVALID_CHAIN;
|
Line 3534... |
Line 3872... |
|
|
int gdb_write_reg(uint32_t adr, uint32_t data) {
|
int gdb_write_reg(uint32_t adr, uint32_t data) {
|
if (DEBUG_CMDS) printf("wreg %d\n", gdb_chain); fflush (stdout);
|
if (DEBUG_CMDS) printf("wreg %d\n", gdb_chain); fflush (stdout);
|
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */
|
switch (gdb_chain) { /* remap registers, to be compatible with jp1 */
|
case SC_RISC_DEBUG: if (adr == JTAG_RISCOP) adr = 0x00;
|
case SC_RISC_DEBUG: if (adr == JTAG_RISCOP) adr = 0x00;
|
return dbg_cpu0_write(adr, data) ? ERR_CRC : ERR_NONE;
|
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_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_WISHBONE: return dbg_wb_write32(adr, data) ? ERR_CRC : ERR_NONE;
|
case SC_TRACE: return 0;
|
case SC_TRACE: return 0;
|
default: return JTAG_PROXY_INVALID_CHAIN;
|
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) {
|
if (DEBUG_CMDS) printf("rb %d\n", gdb_chain); fflush (stdout);
|
if (DEBUG_CMDS) printf("rb %d len %d\n", gdb_chain, len); fflush (stdout);
|
switch (gdb_chain) {
|
switch (gdb_chain) {
|
case SC_WISHBONE: return dbg_wb_read_block32(adr, data, len) ?
|
case SC_RISC_DEBUG: return dbg_cpu0_read(adr, data, len) ? ERR_CRC : ERR_NONE;
|
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;
|
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) {
|
if (DEBUG_CMDS) printf("wb %d\n", gdb_chain); fflush (stdout);
|
if (DEBUG_CMDS) printf("wb %d\n", gdb_chain); fflush (stdout);
|
switch (gdb_chain) {
|
switch (gdb_chain) {
|
|
case SC_RISC_DEBUG: return dbg_cpu0_write(adr, data, len) ? ERR_CRC : ERR_NONE;
|
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ?
|
case SC_WISHBONE: return dbg_wb_write_block32(adr, data, len) ?
|
ERR_CRC : ERR_NONE;
|
ERR_CRC : ERR_NONE;
|
default: return JTAG_PROXY_INVALID_CHAIN;
|
default: return JTAG_PROXY_INVALID_CHAIN;
|
}
|
}
|
}
|
}
|