Line 50... |
Line 50... |
int in_reset = 0;
|
int in_reset = 0;
|
|
|
/* Current watchpoint state */
|
/* Current watchpoint state */
|
unsigned long watchpoints = 0;
|
unsigned long watchpoints = 0;
|
|
|
static int calculate_watchpoints ();
|
static int calculate_watchpoints(DebugUnitAction action, unsigned long udata);
|
|
|
static int watchpoint[10];
|
|
|
|
void set_stall_state(int state)
|
void set_stall_state(int state)
|
{
|
{
|
development.riscop &= ~RISCOP_STALL;
|
development.riscop &= ~RISCOP_STALL;
|
development.riscop |= state ? RISCOP_STALL : 0;
|
development.riscop |= state ? RISCOP_STALL : 0;
|
Line 69... |
Line 67... |
{
|
{
|
development.riscop = 0;
|
development.riscop = 0;
|
set_stall_state (0);
|
set_stall_state (0);
|
}
|
}
|
|
|
|
void du_clock()
|
|
{
|
|
watchpoints=0;
|
|
};
|
|
|
inline int CheckDebugUnit(DebugUnitAction action, unsigned long udata)
|
inline int CheckDebugUnit(DebugUnitAction action, unsigned long udata)
|
{
|
{
|
/* Do not stop, if we have debug module disabled or during reset */
|
/* Do not stop, if we have debug module disabled or during reset */
|
if(!config.debug.enabled || in_reset)
|
if(!config.debug.enabled || in_reset)
|
return 0;
|
return 0;
|
|
|
/* If we're single stepping, always stop */
|
/* If we're single stepping, always stop */
|
if(action == DebugInstructionFetch && testsprbits (SPR_DMR1, SPR_DMR1_ST))
|
if(action == DebugInstructionFetch && testsprbits (SPR_DMR1, SPR_DMR1_ST))
|
return 1;
|
return 1;
|
|
|
return 0;
|
// is any watchpoint enabled to generate a break or count? If not, ignore
|
/* TODO: Enable matchpoints
|
if(mfspr(SPR_DMR2) & (SPR_DMR2_WGB|SPR_DMR2_AWTC))
|
switch(action)
|
return calculate_watchpoints(action, udata);
|
{
|
|
case DebugInstructionFetch: condition = DCR_CT_InsnAddress; break;
|
|
case DebugLoadAddress: condition = DCR_CT_LoadAddress; break;
|
|
case DebugStoreAddress: condition = DCR_CT_StoreAddress; break;
|
|
case DebugLoadData: condition = DCR_CT_LoadData; break;
|
|
case DebugStoreData: condition = DCR_CT_StoreData; break;
|
|
}
|
|
|
|
return calculate_watchpoints(); */
|
return 0;
|
}
|
}
|
|
|
/* Checks whether we should stall the RISC or cause an exception */
|
/* Checks whether we should stall the RISC or cause an exception */
|
static int calculate_watchpoints()
|
static int calculate_watchpoints(DebugUnitAction action, unsigned long udata)
|
{
|
{
|
int breakpoint = 0;
|
int breakpoint = 0;
|
int i, bit;
|
int i, bit;
|
|
|
/* Hopefully this loop would be unrolled run at max. speed */
|
/* Hopefully this loop would be unrolled run at max. speed */
|
Line 108... |
Line 104... |
int DCR_hit = 0;
|
int DCR_hit = 0;
|
|
|
/* Calculate first 8 matchpoints, result is put into DCR_hit */
|
/* Calculate first 8 matchpoints, result is put into DCR_hit */
|
if (i < 8) {
|
if (i < 8) {
|
unsigned long dcr = mfspr (SPR_DCR(i));
|
unsigned long dcr = mfspr (SPR_DCR(i));
|
/* Whether this matchpoint is enabled, calculate conditions */
|
unsigned long dcr_ct=dcr&SPR_DCR_CT; // the CT field alone
|
if ((dcr & SPR_DCR_DP) && (dcr & SPR_DCR_CT != SPR_DCR_CT_DISABLED)) {
|
/* Is this matchpoint a propos for the current action? */
|
/* Get one operand */
|
if ( ((dcr & SPR_DCR_DP) && dcr_ct) &&// DVR/DCP pair present
|
unsigned long op1;
|
(((action==DebugInstructionFetch) && (dcr_ct == SPR_DCR_CT_IFEA))
|
|
|| ((action==DebugLoadAddress) && ((dcr_ct == SPR_DCR_CT_LEA) || (dcr_ct == SPR_DCR_CT_LSEA)))
|
|
|| ((action==DebugStoreAddress) && ((dcr_ct == SPR_DCR_CT_SEA) || (dcr_ct == SPR_DCR_CT_LSEA)))
|
|
|| ((action==DebugLoadData) && ((dcr_ct == SPR_DCR_CT_LD) || (dcr_ct == SPR_DCR_CT_LSD)))
|
|
|| ((action==DebugStoreData) && ((dcr_ct == SPR_DCR_CT_SD) || (dcr_ct == SPR_DCR_CT_LSD)))) )
|
|
{
|
|
unsigned long op1=udata;
|
unsigned long op2 = mfspr (SPR_DVR(i));
|
unsigned long op2 = mfspr (SPR_DVR(i));
|
switch (dcr & SPR_DCR_CT) {
|
|
case SPR_DCR_CT_IFEA: op1 = runtime.cpu.ifea; break;
|
|
case SPR_DCR_CT_LEA: op1 = runtime.cpu.lea; break;
|
|
case SPR_DCR_CT_SEA: op1 = runtime.cpu.sea; break;
|
|
case SPR_DCR_CT_LD: op1 = runtime.cpu.ld; break;
|
|
case SPR_DCR_CT_SD: op1 = runtime.cpu.sd; break;
|
|
case SPR_DCR_CT_LSEA: op1 = runtime.cpu.lsea; break;
|
|
}
|
|
/* Perform signed comparison? */
|
/* Perform signed comparison? */
|
if (dcr & SPR_DCR_SC) {
|
if (dcr & SPR_DCR_SC) {
|
long sop1 = op1, sop2 = op2; /* Convert to signed */
|
long sop1 = op1, sop2 = op2; /* Convert to signed */
|
switch(dcr & SPR_DCR_CC) {
|
switch(dcr & SPR_DCR_CC) {
|
case SPR_DCR_CC_MASKED: DCR_hit = sop1 & sop2; break;
|
case SPR_DCR_CC_MASKED: DCR_hit = sop1 & sop2; break;
|
Line 148... |
Line 142... |
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Chain matchpoints */
|
/* Chain matchpoints */
|
switch(i) {
|
switch(i)
|
|
{
|
case 0:
|
case 0:
|
chain1 = chain2 = DCR_hit;
|
chain1 = chain2 = DCR_hit;
|
break;
|
break;
|
case 8:
|
case 8:
|
chain1 = getsprbits (SPR_DWCR0, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR0, SPR_DWCR_MATCH);
|
chain1 = getsprbits (SPR_DWCR0, SPR_DWCR_COUNT) == getsprbits (SPR_DWCR0, SPR_DWCR_MATCH);
|
Line 183... |
Line 178... |
case 2: match = chain1 || chain2; break;
|
case 2: match = chain1 || chain2; break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
|
|
if(match & !(watchpoints & bit)) {
|
// Increment counters & generate counter break
|
|
if(match)
|
|
{
|
|
if(!(watchpoints & bit)) // watchpoint did not appear before in this clock cycle
|
|
{
|
int counter = (getsprbits (SPR_DMR2, SPR_DMR2_AWTC) & bit) ? 1 : 0;
|
int counter = (getsprbits (SPR_DMR2, SPR_DMR2_AWTC) & bit) ? 1 : 0;
|
int enabled = counter ? getsprbits (SPR_DMR2, SPR_DMR2_WCE1) : getsprbits (SPR_DMR2, SPR_DMR2_WCE0);
|
int enabled = counter ? getsprbits (SPR_DMR2, SPR_DMR2_WCE1) : getsprbits (SPR_DMR2, SPR_DMR2_WCE0);
|
|
|
if(enabled)
|
if(enabled)
|
setsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT, getsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT) + 1);
|
setsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT, getsprbits (SPR_DWCR0 + counter, SPR_DWCR_COUNT) + 1);
|
|
|
if(getsprbits (SPR_DMR2, SPR_DMR2_WGB) & bit)
|
|
breakpoint = 1;
|
|
}
|
|
|
|
watchpoints &= ~bit;
|
|
watchpoints |= bit;
|
watchpoints |= bit;
|
}
|
}
|
|
|
|
// should this watchpoint generate a breakpoint?
|
|
if(getsprbits (SPR_DMR2, SPR_DMR2_WGB) & bit) breakpoint = 1;
|
|
}
|
|
}
|
return breakpoint;
|
return breakpoint;
|
}
|
}
|
|
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
static DebugScanChainIDs current_scan_chain = JTAG_CHAIN_GLOBAL;
|
|
|
int DebugGetRegister(unsigned int address, unsigned long* data)
|
int DebugGetRegister(unsigned int address, unsigned long* data)
|
{
|
{
|
int err;
|
int err=0;
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
PRINTF("Debug get register %x\n",address);
|
PRINTF("Debug get register %x\n",address);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
switch(current_scan_chain)
|
switch(current_scan_chain)
|
Line 221... |
Line 217... |
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", address, *data);
|
fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", address, *data);
|
}
|
}
|
break;
|
break;
|
case JTAG_CHAIN_TRACE:
|
case JTAG_CHAIN_TRACE:
|
*data = 0; /* Scan chain not yet implemented */
|
*data = 0; /* Scan chain not yet implemented */
|
err = 0;
|
|
break;
|
break;
|
case JTAG_CHAIN_DEVELOPMENT:
|
case JTAG_CHAIN_DEVELOPMENT:
|
err = get_devint_reg(address,data);
|
err = get_devint_reg(address,data);
|
break;
|
break;
|
case JTAG_CHAIN_WISHBONE:
|
case JTAG_CHAIN_WISHBONE:
|
err = GetWishboneMemory(address,data);
|
err = debug_get_mem(address,data);
|
break;
|
break;
|
}
|
}
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
PRINTF("!get reg %x\n", *data);
|
PRINTF("!get reg %x\n", *data);
|
fflush(stdout);
|
fflush(stdout);
|
Line 239... |
Line 234... |
return err;
|
return err;
|
}
|
}
|
|
|
int DebugSetRegister(unsigned int address,unsigned long data)
|
int DebugSetRegister(unsigned int address,unsigned long data)
|
{
|
{
|
int err;
|
int err=0;
|
#ifdef DEBUG_JTAG
|
#ifdef DEBUG_JTAG
|
PRINTF("Debug set register %x <- %x\n", address, data);
|
PRINTF("Debug set register %x <- %x\n", address, data);
|
fflush(stdout);
|
fflush(stdout);
|
#endif
|
#endif
|
switch(current_scan_chain)
|
switch(current_scan_chain)
|
Line 385... |
Line 380... |
|
|
|
|
if(!verify_memoryarea(address))
|
if(!verify_memoryarea(address))
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
else {
|
else {
|
unsigned char t_data[4];
|
// circumvent the read-only check usually done for mem accesses
|
int *tmp = (int*)t_data;
|
// data is in host order, because that's what simmem_write_word needs
|
extern char null_str[1]; /* From cpu/common/parse.c */
|
simmem_write_word(address, data);
|
int i;
|
|
|
|
*tmp = htonl(data); /* We have already converted to host order */
|
|
|
|
setsim_mem8(address++, t_data[0]); /* Back to network byte order */
|
|
setsim_mem8(address++, t_data[1]);
|
|
setsim_mem8(address++, t_data[2]);
|
|
setsim_mem8(address++, t_data[3]);
|
|
}
|
}
|
return err;
|
return err;
|
}
|
}
|
|
|
int GetWishboneMemory(unsigned int address,unsigned long *data)
|
int debug_get_mem(unsigned int address,unsigned long *data)
|
{
|
{
|
int err = 0;
|
int err = 0;
|
if(!verify_memoryarea(address))
|
if(!verify_memoryarea(address))
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
err = JTAG_PROXY_INVALID_ADDRESS;
|
else
|
else
|
{
|
{
|
unsigned char t_data[4];
|
*data=simmem_read_word(address);
|
int *tmp = (int*)t_data;
|
|
int bp;
|
|
|
|
t_data[0] = evalsim_mem8(address++);
|
|
t_data[1] = evalsim_mem8(address++);
|
|
t_data[2] = evalsim_mem8(address++);
|
|
t_data[3] = evalsim_mem8(address++); /* Already in network byte order */
|
|
|
|
*data = ntohl(*tmp); /* But we assume it is in host order later */
|
|
}
|
}
|
debug (2, "MEMREAD (%08x) = %08x\n", address, *data);
|
debug (2, "MEMREAD (%08x) = %08x\n", address, *data);
|
return err;
|
return err;
|
}
|
}
|
|
|