Add support for read and write watchpoints.
This commit is contained in:
parent
7413531715
commit
09ca20c91c
|
@ -53,7 +53,9 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
DEVICE_BPTYPE_BREAK,
|
||||
DEVICE_BPTYPE_WATCH
|
||||
DEVICE_BPTYPE_WATCH,
|
||||
DEVICE_BPTYPE_READ,
|
||||
DEVICE_BPTYPE_WRITE
|
||||
} device_bptype_t;
|
||||
|
||||
struct device_breakpoint {
|
||||
|
|
|
@ -226,6 +226,14 @@ static int bp_send(struct gdb_data *gdb, int c, address_t addr,
|
|||
type_code = 1;
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WRITE:
|
||||
type_code = 2;
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_READ:
|
||||
type_code = 3;
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WATCH:
|
||||
type_code = 4;
|
||||
break;
|
||||
|
|
|
@ -53,7 +53,8 @@ struct sim_device {
|
|||
(dev)->memory[offset | 1] = (value) >> 8; \
|
||||
} while (0);
|
||||
|
||||
static void watchpoint_check(struct sim_device *dev, uint16_t addr)
|
||||
static void watchpoint_check(struct sim_device *dev, uint16_t addr,
|
||||
int is_write)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -62,8 +63,10 @@ static void watchpoint_check(struct sim_device *dev, uint16_t addr)
|
|||
&dev->base.breakpoints[i];
|
||||
|
||||
if ((bp->flags & DEVICE_BP_ENABLED) &&
|
||||
bp->type == DEVICE_BPTYPE_WATCH &&
|
||||
bp->addr == addr) {
|
||||
(bp->addr == addr) &&
|
||||
((bp->type == DEVICE_BPTYPE_WATCH ||
|
||||
(bp->type == DEVICE_BPTYPE_READ && !is_write) ||
|
||||
(bp->type == DEVICE_BPTYPE_WRITE && is_write)))) {
|
||||
dev->watchpoint_hit = 1;
|
||||
return;
|
||||
}
|
||||
|
@ -133,12 +136,12 @@ static int fetch_operand(struct sim_device *dev,
|
|||
break;
|
||||
}
|
||||
|
||||
watchpoint_check(dev, addr);
|
||||
|
||||
if (addr_ret)
|
||||
*addr_ret = addr;
|
||||
|
||||
if (data_ret) {
|
||||
watchpoint_check(dev, addr, 0);
|
||||
|
||||
*data_ret = MEM_GETW(dev, addr) & mask;
|
||||
|
||||
if (addr < MEM_IO_END) {
|
||||
|
@ -172,7 +175,7 @@ static int store_operand(struct sim_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
watchpoint_check(dev, addr);
|
||||
watchpoint_check(dev, addr, 1);
|
||||
|
||||
if (is_byte)
|
||||
MEM_SETB(dev, addr, data);
|
||||
|
|
|
@ -324,13 +324,14 @@ static void load_break(BpParameter_t *param, address_t addr)
|
|||
param->wExtCombine = 0; /* not used? */
|
||||
}
|
||||
|
||||
static void load_watch(BpParameter_t *param, address_t addr)
|
||||
static void load_complex(BpParameter_t *param, address_t addr,
|
||||
BpAccess_t acc)
|
||||
{
|
||||
param->bpMode = BP_COMPLEX;
|
||||
param->lAddrVal = addr;
|
||||
param->bpType = BP_MAB;
|
||||
param->lReg = 0; /* not used (only for register-write) */
|
||||
param->bpAccess = BP_NO_FETCH;
|
||||
param->bpAccess = acc;
|
||||
param->bpAction = BP_BRK;
|
||||
param->bpOperat = BP_EQUAL;
|
||||
param->lMask = 0xffffff;
|
||||
|
@ -338,7 +339,7 @@ static void load_watch(BpParameter_t *param, address_t addr)
|
|||
param->bpRangeAction = 0; /* not used */
|
||||
param->bpCondition = BP_NO_COND;
|
||||
param->lCondMdbVal = 0;
|
||||
param->bpCondAccess = BP_NO_FETCH;
|
||||
param->bpCondAccess = acc;
|
||||
param->lCondMask = 0; /* what's this? */
|
||||
param->bpCondOperat = BP_EQUAL;
|
||||
param->wExtCombine = 0; /* not used? */
|
||||
|
@ -362,7 +363,17 @@ static int refresh_bps(struct tilib_device *dev)
|
|||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WATCH:
|
||||
load_watch(¶m, bp->addr);
|
||||
load_complex(¶m, bp->addr, BP_NO_FETCH);
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_READ:
|
||||
load_complex(¶m, bp->addr,
|
||||
BP_READ_DMA);
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WRITE:
|
||||
load_complex(¶m, bp->addr,
|
||||
BP_WRITE_DMA);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -408,6 +408,10 @@ Add a new watchpoint. The watchpoint location is an address expression, and
|
|||
an optional index may be specified. Watchpoints are considered to be a type
|
||||
of breakpoint and can be inspected or removed using the \fBbreak\fR and
|
||||
\fBdelbreak\fR commands. Note that not all drivers support watchpoints.
|
||||
.IP "\fBsetwatch_r\fR \fIaddress\fR [\fIindex\fR]"
|
||||
Add a watchpoint which is triggered only on read access.
|
||||
.IP "\fBsetwatch_w\fR \fIaddress\fR [\fIindex\fR]"
|
||||
Add a watchpoint which is triggered only on write access.
|
||||
.IP "\fBsimio add\fR \fIclass\fR \fIname\fR [\fIargs ...\fR]"
|
||||
Add a new peripheral to the IO simulator. The \fIclass\fR parameter may be
|
||||
any of the peripheral types named in the output of the \fBsimio classes\fR
|
||||
|
|
14
ui/cmddb.c
14
ui/cmddb.c
|
@ -68,6 +68,20 @@ const struct cmddb_record commands[] = {
|
|||
"setwatch <addr> [index]\n"
|
||||
" Set a watchpoint. If no index is specified. the first available\n"
|
||||
" slot will be used.\n"
|
||||
},
|
||||
{
|
||||
.name = "setwatch_r",
|
||||
.func = cmd_setwatch_r,
|
||||
.help =
|
||||
"setwatch_r <addr> [index]\n"
|
||||
" Set a read-only watchpoint.\n"
|
||||
},
|
||||
{
|
||||
.name = "setwatch_w",
|
||||
.func = cmd_setwatch_w,
|
||||
.help =
|
||||
"setwatch_w <addr> [index]\n"
|
||||
" Set a write-only watchpoint.\n"
|
||||
},
|
||||
{
|
||||
.name = "delbreak",
|
||||
|
|
26
ui/devcmd.c
26
ui/devcmd.c
|
@ -615,6 +615,16 @@ int cmd_setwatch(char **arg)
|
|||
return do_setbreak(DEVICE_BPTYPE_WATCH, arg);
|
||||
}
|
||||
|
||||
int cmd_setwatch_w(char **arg)
|
||||
{
|
||||
return do_setbreak(DEVICE_BPTYPE_WRITE, arg);
|
||||
}
|
||||
|
||||
int cmd_setwatch_r(char **arg)
|
||||
{
|
||||
return do_setbreak(DEVICE_BPTYPE_READ, arg);
|
||||
}
|
||||
|
||||
int cmd_delbreak(char **arg)
|
||||
{
|
||||
char *index_text = get_arg(arg);
|
||||
|
@ -661,10 +671,22 @@ int cmd_break(char **arg)
|
|||
print_address(bp->addr, name, sizeof(name));
|
||||
printc(" %d. %s", i, name);
|
||||
|
||||
if (bp->type == DEVICE_BPTYPE_WATCH) {
|
||||
switch (bp->type) {
|
||||
case DEVICE_BPTYPE_WATCH:
|
||||
printc(" [watchpoint]\n");
|
||||
} else {
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_READ:
|
||||
printc(" [read watchpoint]\n");
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_WRITE:
|
||||
printc(" [write watchpoint]\n");
|
||||
break;
|
||||
|
||||
case DEVICE_BPTYPE_BREAK:
|
||||
printc("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ int cmd_prog(char **arg);
|
|||
int cmd_load(char **arg);
|
||||
int cmd_setbreak(char **arg);
|
||||
int cmd_setwatch(char **arg);
|
||||
int cmd_setwatch_r(char **arg);
|
||||
int cmd_setwatch_w(char **arg);
|
||||
int cmd_delbreak(char **arg);
|
||||
int cmd_break(char **arg);
|
||||
int cmd_locka(char **arg);
|
||||
|
|
Loading…
Reference in New Issue