Commit b702b16d authored by Salvador Arroyo's avatar Salvador Arroyo Committed by Freddie Chopin
Browse files

mips32: add micromips breakpoints support



Breakpoint setting based on length (kind) only.
Added 16bit aligned 32bit software breakpoints
support and same filtering before setting
breakpoint.
Set the required isa bit in hardware breakpoints.
Drop the isa bit in software breakpoints.

Change-Id: I7020f27be16015194b76f385d9b8e5af496d0dfc
Signed-off-by: default avatarSalvador Arroyo <sarroyofdez@yahoo.es>
Reviewed-on: http://openocd.zylin.com/4124


Tested-by: jenkins
Reviewed-by: default avatarFreddie Chopin <freddie.chopin@gmail.com>
parent 4831ce44
......@@ -631,6 +631,11 @@ static int mips_m4k_set_breakpoint(struct target *target,
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! :) */
......@@ -648,41 +653,77 @@ static int mips_m4k_set_breakpoint(struct target *target,
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;
}
......@@ -725,46 +766,58 @@ static int mips_m4k_unset_breakpoint(struct target *target,
} 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 *)&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_u32().
*/
current_instr = target_buffer_get_u32(target, (uint8_t *)&current_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 *)&current_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 *)&current_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;
......@@ -774,6 +827,12 @@ static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *bre
{
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");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment