+ struct mips32_common *mips32 = target_to_mips32(target);
+ struct mips32_comparator *comparator_list = mips32->data_break_list;
+ int wp_num = 0;
+ /*
+ * watchpoint enabled, ignore all byte lanes in value register
+ * and exclude both load and store accesses from watchpoint
+ * condition evaluation
+ */
+ int enable = EJTAG_DBCn_NOSB | EJTAG_DBCn_NOLB | EJTAG_DBCn_BE |
+ (0xff << EJTAG_DBCn_BLM_SHIFT);
+
+ if (watchpoint->set)
+ {
+ LOG_WARNING("watchpoint already set");
+ return ERROR_OK;
+ }
+
+ while(comparator_list[wp_num].used && (wp_num < mips32->num_data_bpoints))
+ wp_num++;
+ if (wp_num >= mips32->num_data_bpoints)
+ {
+ LOG_ERROR("Can not find free FP Comparator");
+ return ERROR_FAIL;
+ }
+
+ if (watchpoint->length != 4)
+ {
+ LOG_ERROR("Only watchpoints of length 4 are supported");
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+ }
+
+ if (watchpoint->address % 4)
+ {
+ LOG_ERROR("Watchpoints address should be word aligned");
+ return ERROR_TARGET_UNALIGNED_ACCESS;
+ }
+
+ switch (watchpoint->rw)
+ {
+ case WPT_READ:
+ enable &= ~EJTAG_DBCn_NOLB;
+ break;
+ case WPT_WRITE:
+ enable &= ~EJTAG_DBCn_NOSB;
+ break;
+ case WPT_ACCESS:
+ enable &= ~(EJTAG_DBCn_NOLB | EJTAG_DBCn_NOSB);
+ break;
+ default:
+ LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
+ }
+
+ watchpoint->set = wp_num + 1;
+ comparator_list[wp_num].used = 1;
+ comparator_list[wp_num].bp_value = watchpoint->address;
+ target_write_u32(target, comparator_list[wp_num].reg_address, comparator_list[wp_num].bp_value);
+ target_write_u32(target, comparator_list[wp_num].reg_address + 0x08, 0x00000000);
+ target_write_u32(target, comparator_list[wp_num].reg_address + 0x10, 0x00000000);
+ target_write_u32(target, comparator_list[wp_num].reg_address + 0x18, enable);
+ target_write_u32(target, comparator_list[wp_num].reg_address + 0x20, 0);
+ LOG_DEBUG("wp_num %i bp_value 0x%" PRIx32 "", wp_num, comparator_list[wp_num].bp_value);
+