*/
+static int arc_remove_watchpoint(struct target *target,
+ struct watchpoint *watchpoint);
void arc_reg_data_type_add(struct target *target,
struct arc_reg_data_type *data_type)
arc->num_regs += 1;
LOG_DEBUG(
- "added register {name=%s, num=0x%x, type=%s%s%s%s}",
+ "added register {name=%s, num=0x%" PRIx32 ", type=%s%s%s%s}",
arc_reg->name, arc_reg->arch_num, arc_reg->data_type->id,
arc_reg->is_core ? ", core" : "", arc_reg->is_bcr ? ", bcr" : "",
arc_reg->is_general ? ", general" : ""
if (desc->is_core) {
/* Accessing to R61/R62 registers causes Jtag hang */
- if (desc->arch_num == CORE_R61_NUM || desc->arch_num == CORE_R62_NUM) {
+ if (desc->arch_num == ARC_R61 || desc->arch_num == ARC_R62) {
LOG_ERROR("It is forbidden to read core registers 61 and 62.");
return ERROR_FAIL;
}
return ERROR_TARGET_NOT_HALTED;
/* Accessing to R61/R62 registers causes Jtag hang */
- if (desc->is_core && (desc->arch_num == CORE_R61_NUM ||
- desc->arch_num == CORE_R62_NUM)) {
+ if (desc->is_core && (desc->arch_num == ARC_R61 ||
+ desc->arch_num == ARC_R62)) {
LOG_ERROR("It is forbidden to write core registers 61 and 62.");
return ERROR_FAIL;
}
/* Initialize struct reg */
reg->name = reg_desc->name;
reg->size = 32; /* All register in ARC are 32-bit */
- reg->value = ®_desc->reg_value;
+ reg->value = reg_desc->reg_value;
reg->type = &arc_reg_type;
reg->arch_info = reg_desc;
reg->caller_save = true; /* @todo should be configurable. */
/* Read data from target. */
if (core_cnt > 0) {
retval = arc_jtag_read_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values);
- if (ERROR_OK != retval) {
+ if (retval != ERROR_OK) {
LOG_ERROR("Attempt to read core registers failed.");
retval = ERROR_FAIL;
goto exit;
}
if (aux_cnt > 0) {
retval = arc_jtag_read_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values);
- if (ERROR_OK != retval) {
+ if (retval != ERROR_OK) {
LOG_ERROR("Attempt to read aux registers failed.");
retval = ERROR_FAIL;
goto exit;
core_cnt += 1;
reg->valid = true;
reg->dirty = false;
- LOG_DEBUG("Get core register regnum=%" PRIu32 ", name=%s, value=0x%08" PRIx32,
+ LOG_DEBUG("Get core register regnum=%u, name=%s, value=0x%08" PRIx32,
i, arc_reg->name, core_values[core_cnt]);
}
}
aux_cnt += 1;
reg->valid = true;
reg->dirty = false;
- LOG_DEBUG("Get aux register regnum=%" PRIu32 ", name=%s, value=0x%08" PRIx32,
+ LOG_DEBUG("Get aux register regnum=%u, name=%s, value=0x%08" PRIx32,
i, arc_reg->name, aux_values[aux_cnt]);
}
}
* Finds an actionpoint that triggered last actionpoint event, as specified by
* DEBUG.ASR.
*
+ * @param target
* @param actionpoint Pointer to be set to last active actionpoint. Pointer
* will be set to NULL if DEBUG.AH is 0.
*/
static int get_current_actionpoint(struct target *target,
struct arc_actionpoint **actionpoint)
{
- assert(target != NULL);
- assert(actionpoint != NULL);
+ assert(target);
+ assert(actionpoint);
uint32_t debug_ah;
/* Check if actionpoint caused halt */
struct arc_actionpoint *actionpoint = NULL;
CHECK_RETVAL(get_current_actionpoint(target, &actionpoint));
- if (actionpoint != NULL) {
+ if (actionpoint) {
if (!actionpoint->used)
LOG_WARNING("Target halted by an unused actionpoint.");
* Check before write, if aux and core count is greater than 0. */
if (core_cnt > 0) {
retval = arc_jtag_write_core_reg(&arc->jtag_info, core_addrs, core_cnt, core_values);
- if (ERROR_OK != retval) {
+ if (retval != ERROR_OK) {
LOG_ERROR("Attempt to write to core registers failed.");
retval = ERROR_FAIL;
goto exit;
if (aux_cnt > 0) {
retval = arc_jtag_write_aux_reg(&arc->jtag_info, aux_addrs, aux_cnt, aux_values);
- if (ERROR_OK != retval) {
+ if (retval != ERROR_OK) {
LOG_ERROR("Attempt to write to aux registers failed.");
retval = ERROR_FAIL;
goto exit;
if (control_tt != AP_AC_TT_DISABLE) {
if (arc->actionpoints_num_avail < 1) {
- LOG_ERROR("No free actionpoints, maximim amount is %" PRIu32,
+ LOG_ERROR("No free actionpoints, maximum amount is %u",
arc->actionpoints_num);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
static int arc_set_breakpoint(struct target *target,
struct breakpoint *breakpoint)
{
- if (breakpoint->set) {
+ if (breakpoint->is_set) {
LOG_WARNING("breakpoint already set");
return ERROR_OK;
}
return ERROR_COMMAND_ARGUMENT_INVALID;
}
- breakpoint->set = 64; /* Any nice value but 0 */
+ breakpoint->is_set = true;
} else if (breakpoint->type == BKPT_HARD) {
struct arc_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list;
}
if (bp_num >= arc->actionpoints_num) {
- LOG_ERROR("No free actionpoints, maximum amount is %" PRIu32,
+ LOG_ERROR("No free actionpoints, maximum amount is %u",
arc->actionpoints_num);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
breakpoint->address, AP_AC_TT_READWRITE, AP_AC_AT_INST_ADDR);
if (retval == ERROR_OK) {
- breakpoint->set = bp_num + 1;
+ breakpoint_hw_set(breakpoint, bp_num);
ap_list[bp_num].used = 1;
ap_list[bp_num].bp_value = breakpoint->address;
ap_list[bp_num].type = ARC_AP_BREAKPOINT;
{
int retval = ERROR_OK;
- if (!breakpoint->set) {
+ if (!breakpoint->is_set) {
LOG_WARNING("breakpoint not set");
return ERROR_OK;
}
} else {
LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR
" has been overwritten outside of debugger."
- "Expected: @0x%" PRIx32 ", got: @0x%" PRIx32,
+ "Expected: @0x%x, got: @0x%" PRIx32,
breakpoint->address, ARC_SDBBP_32, current_instr);
}
} else if (breakpoint->length == 2) {
LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
- breakpoint->set = 0;
+ breakpoint->is_set = false;
} else if (breakpoint->type == BKPT_HARD) {
struct arc_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list;
- unsigned int bp_num = breakpoint->set - 1;
+ unsigned int bp_num = breakpoint->number;
- if ((breakpoint->set == 0) || (bp_num >= arc->actionpoints_num)) {
+ if (bp_num >= arc->actionpoints_num) {
LOG_DEBUG("Invalid actionpoint ID: %u in breakpoint: %" PRIu32,
bp_num, breakpoint->unique_id);
return ERROR_OK;
breakpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_INST_ADDR);
if (retval == ERROR_OK) {
- breakpoint->set = 0;
+ breakpoint->is_set = false;
ap_list[bp_num].used = 0;
ap_list[bp_num].bp_value = 0;
- LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %i",
+ LOG_DEBUG("bpid: %" PRIu32 " - released actionpoint ID: %u",
breakpoint->unique_id, bp_num);
}
} else {
struct breakpoint *breakpoint)
{
if (target->state == TARGET_HALTED) {
- if (breakpoint->set)
+ if (breakpoint->is_set)
CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint));
} else {
LOG_WARNING("target not halted");
struct arc_common *arc = target_to_arc(target);
struct arc_actionpoint *ap_list = arc->actionpoints_list;
struct breakpoint *next_b;
+ struct watchpoint *next_w;
while (target->breakpoints) {
next_b = target->breakpoints->next;
free(target->breakpoints);
target->breakpoints = next_b;
}
+ while (target->watchpoints) {
+ next_w = target->watchpoints->next;
+ arc_remove_watchpoint(target, target->watchpoints);
+ free(target->watchpoints);
+ target->watchpoints = next_w;
+ }
for (unsigned int i = 0; i < arc->actionpoints_num; i++) {
if ((ap_list[i].used) && (ap_list[i].reg_address))
arc_remove_auxreg_actionpoint(target, ap_list[i].reg_address);
return retval;
}
+
+static int arc_set_watchpoint(struct target *target,
+ struct watchpoint *watchpoint)
+{
+ unsigned int wp_num;
+ struct arc_common *arc = target_to_arc(target);
+ struct arc_actionpoint *ap_list = arc->actionpoints_list;
+
+ if (watchpoint->is_set) {
+ LOG_WARNING("watchpoint already set");
+ return ERROR_OK;
+ }
+
+ for (wp_num = 0; wp_num < arc->actionpoints_num; wp_num++) {
+ if (!ap_list[wp_num].used)
+ break;
+ }
+
+ if (wp_num >= arc->actionpoints_num) {
+ LOG_ERROR("No free actionpoints, maximum amount is %u",
+ arc->actionpoints_num);
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+ }
+
+ if (watchpoint->length != 4) {
+ LOG_ERROR("Only watchpoints of length 4 are supported");
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+ }
+
+ int enable = AP_AC_TT_DISABLE;
+ switch (watchpoint->rw) {
+ case WPT_READ:
+ enable = AP_AC_TT_READ;
+ break;
+ case WPT_WRITE:
+ enable = AP_AC_TT_WRITE;
+ break;
+ case WPT_ACCESS:
+ enable = AP_AC_TT_READWRITE;
+ break;
+ default:
+ LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
+ return ERROR_FAIL;
+ }
+
+ int retval = arc_configure_actionpoint(target, wp_num,
+ watchpoint->address, enable, AP_AC_AT_MEMORY_ADDR);
+
+ if (retval == ERROR_OK) {
+ watchpoint_set(watchpoint, wp_num);
+ ap_list[wp_num].used = 1;
+ ap_list[wp_num].bp_value = watchpoint->address;
+ ap_list[wp_num].type = ARC_AP_WATCHPOINT;
+
+ LOG_DEBUG("wpid: %" PRIu32 ", wp_num %u wp_value 0x%" PRIx32,
+ watchpoint->unique_id, wp_num, ap_list[wp_num].bp_value);
+ }
+
+ return retval;
+}
+
+static int arc_unset_watchpoint(struct target *target,
+ struct watchpoint *watchpoint)
+{
+ /* get pointers to arch-specific information */
+ struct arc_common *arc = target_to_arc(target);
+ struct arc_actionpoint *ap_list = arc->actionpoints_list;
+
+ if (!watchpoint->is_set) {
+ LOG_WARNING("watchpoint not set");
+ return ERROR_OK;
+ }
+
+ unsigned int wp_num = watchpoint->number;
+ if (wp_num >= arc->actionpoints_num) {
+ LOG_DEBUG("Invalid actionpoint ID: %u in watchpoint: %" PRIu32,
+ wp_num, watchpoint->unique_id);
+ return ERROR_OK;
+ }
+
+ int retval = arc_configure_actionpoint(target, wp_num,
+ watchpoint->address, AP_AC_TT_DISABLE, AP_AC_AT_MEMORY_ADDR);
+
+ if (retval == ERROR_OK) {
+ watchpoint->is_set = false;
+ ap_list[wp_num].used = 0;
+ ap_list[wp_num].bp_value = 0;
+
+ LOG_DEBUG("wpid: %" PRIu32 " - releasing actionpoint ID: %u",
+ watchpoint->unique_id, wp_num);
+ }
+
+ return retval;
+}
+
+static int arc_add_watchpoint(struct target *target,
+ struct watchpoint *watchpoint)
+{
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ CHECK_RETVAL(arc_set_watchpoint(target, watchpoint));
+
+ return ERROR_OK;
+}
+
+static int arc_remove_watchpoint(struct target *target,
+ struct watchpoint *watchpoint)
+{
+ if (target->state != TARGET_HALTED) {
+ LOG_WARNING("target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (watchpoint->is_set)
+ CHECK_RETVAL(arc_unset_watchpoint(target, watchpoint));
+
+ return ERROR_OK;
+}
+
+static int arc_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
+{
+ assert(target);
+ assert(hit_watchpoint);
+
+ struct arc_actionpoint *actionpoint = NULL;
+ CHECK_RETVAL(get_current_actionpoint(target, &actionpoint));
+
+ if (actionpoint) {
+ if (!actionpoint->used)
+ LOG_WARNING("Target halted by unused actionpoint.");
+
+ /* If this check fails - that is some sort of an error in OpenOCD. */
+ if (actionpoint->type != ARC_AP_WATCHPOINT)
+ LOG_WARNING("Target halted by breakpoint, but is treated as a watchpoint.");
+
+ for (struct watchpoint *watchpoint = target->watchpoints;
+ watchpoint;
+ watchpoint = watchpoint->next) {
+ if (actionpoint->bp_value == watchpoint->address) {
+ *hit_watchpoint = watchpoint;
+ LOG_DEBUG("Hit watchpoint, wpid: %" PRIu32 ", watchpoint num: %u",
+ watchpoint->unique_id, watchpoint->number);
+ return ERROR_OK;
+ }
+ }
+ }
+
+ return ERROR_FAIL;
+}
+
/* Helper function which switches core to single_step mode by
* doing aux r/w operations. */
int arc_config_step(struct target *target, int enable_step)
.add_context_breakpoint = NULL,
.add_hybrid_breakpoint = NULL,
.remove_breakpoint = arc_remove_breakpoint,
- .add_watchpoint = NULL,
- .remove_watchpoint = NULL,
- .hit_watchpoint = NULL,
+ .add_watchpoint = arc_add_watchpoint,
+ .remove_watchpoint = arc_remove_watchpoint,
+ .hit_watchpoint = arc_hit_watchpoint,
.run_algorithm = NULL,
.start_algorithm = NULL,