comparator_list[bp_num].used = 1;
comparator_list[bp_num].bp_value = breakpoint->address;
+ if (breakpoint->length != 4) /* make sure isa bit set */
+ comparator_list[bp_num].bp_value |= 1;
+ else /* make sure isa bit cleared */
+ comparator_list[bp_num].bp_value &= ~1;
+
/* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved.
* Warning: there is no IB ASID registers in 2.0.
* Do not set it! :) */
bp_num, comparator_list[bp_num].bp_value);
} else if (breakpoint->type == BKPT_SOFT) {
LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
- if (breakpoint->length == 4) {
+
+ uint32_t isa_req = breakpoint->length & 1; /* micro mips request bit */
+ uint32_t bplength = breakpoint->length & ~1; /* drop micro mips request bit for length */
+ uint32_t bpaddr = breakpoint->address & ~1; /* drop isa bit from address, if set */
+
+ if (bplength == 4) {
uint32_t verify = 0xffffffff;
+ uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req);
+ if (ejtag_info->endianness && isa_req)
+ sdbbp32_instr = SWAP16(sdbbp32_instr);
- retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr);
- if (retval != ERROR_OK)
- return retval;
- retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa));
- if (retval != ERROR_OK)
- return retval;
+ if ((breakpoint->address & 3) == 0) { /* word alligned */
- retval = target_read_u32(target, breakpoint->address, &verify);
- if (retval != ERROR_OK)
- return retval;
- if (verify != MIPS32_SDBBP(ejtag_info->isa)) {
- LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT
- " - check that memory is read/writable", breakpoint->address);
+ retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, bpaddr, sdbbp32_instr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_u32(target, bpaddr, &verify);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (verify != sdbbp32_instr)
+ verify = 0;
+
+ } else { /* 16 bit aligned */
+ retval = target_read_memory(target, bpaddr, 2, 2, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint8_t sdbbp_buf[4];
+ target_buffer_set_u32(target, sdbbp_buf, sdbbp32_instr);
+
+ retval = target_write_memory(target, bpaddr, 2, 2, sdbbp_buf);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_read_memory(target, bpaddr, 2, 2, sdbbp_buf);
+ if (retval != ERROR_OK)
+ return retval;
+
+ if (target_buffer_get_u32(target, sdbbp_buf) != sdbbp32_instr)
+ verify = 0;
+ }
+
+ if (verify == 0) {
+ LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx64
+ " - check that memory is read/writable", breakpoint->address);
return ERROR_OK;
}
+
} else {
uint16_t verify = 0xffff;
- retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
- breakpoint->orig_instr);
+ retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
- retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa));
+
+ retval = target_write_u16(target, bpaddr, MIPS16_SDBBP(isa_req));
if (retval != ERROR_OK)
return retval;
- retval = target_read_u16(target, breakpoint->address, &verify);
+ retval = target_read_u16(target, bpaddr, &verify);
if (retval != ERROR_OK)
return retval;
- if (verify != MIPS16_SDBBP(ejtag_info->isa)) {
- LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT
+
+ if (verify != MIPS16_SDBBP(isa_req)) {
+ LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx64
" - check that memory is read/writable", breakpoint->address);
return ERROR_OK;
}
} else {
/* restore original instruction (kept in target endianness) */
+ uint32_t isa_req = breakpoint->length & 1;
+ uint32_t bplength = breakpoint->length & ~1;
+ uint8_t current_instr[4];
LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
- if (breakpoint->length == 4) {
- uint32_t current_instr;
-
- /* check that user program has not modified breakpoint instruction */
- retval = target_read_memory(target, breakpoint->address, 4, 1,
- (uint8_t *)¤t_instr);
- if (retval != ERROR_OK)
- return retval;
-
- /**
- * target_read_memory() gets us data in _target_ endianess.
- * If we want to use this data on the host for comparisons with some macros
- * we must first transform it to _host_ endianess using target_buffer_get_u32().
- */
- current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr);
-
- if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) {
- retval = target_write_memory(target, breakpoint->address, 4, 1,
- breakpoint->orig_instr);
+ if (bplength == 4) {
+ uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req);
+ if (ejtag_info->endianness && isa_req)
+ sdbbp32_instr = SWAP16(sdbbp32_instr);
+
+ if ((breakpoint->address & 3) == 0) { /* 32bit aligned */
+ /* check that user program has not modified breakpoint instruction */
+ retval = target_read_memory(target, breakpoint->address, 4, 1, current_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ /**
+ * target_read_memory() gets us data in _target_ endianess.
+ * If we want to use this data on the host for comparisons with some macros
+ * we must first transform it to _host_ endianess using target_buffer_get_u16().
+ */
+ if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) {
+ retval = target_write_memory(target, breakpoint->address, 4, 1,
+ breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+ } else { /* 16bit alligned */
+ retval = target_read_memory(target, breakpoint->address, 2, 2, current_instr);
if (retval != ERROR_OK)
return retval;
+
+ if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) {
+ retval = target_write_memory(target, breakpoint->address, 2, 2,
+ breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ }
}
} else {
- uint16_t current_instr;
-
/* check that user program has not modified breakpoint instruction */
- retval = target_read_memory(target, breakpoint->address, 2, 1,
- (uint8_t *)¤t_instr);
+ retval = target_read_memory(target, breakpoint->address, 2, 1, current_instr);
if (retval != ERROR_OK)
return retval;
- current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr);
- if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) {
+
+ if (target_buffer_get_u16(target, current_instr) == MIPS16_SDBBP(isa_req)) {
retval = target_write_memory(target, breakpoint->address, 2, 1,
- breakpoint->orig_instr);
+ breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
}
}
}
+
breakpoint->set = 0;
return ERROR_OK;
{
struct mips32_common *mips32 = target_to_mips32(target);
+ if ((breakpoint->length > 5 || breakpoint->length < 2) || /* out of range */
+ (breakpoint->length == 4 && (breakpoint->address & 2)) || /* mips32 unaligned */
+ (mips32->isa_imp == MIPS32_ONLY && breakpoint->length != 4) || /* misp32 specific */
+ ((mips32->isa_imp & 1) != (breakpoint->length & 1))) /* isa not implemented */
+ return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+
if (breakpoint->type == BKPT_HARD) {
if (mips32->num_inst_bpoints_avail < 1) {
LOG_INFO("no hardware breakpoint available");