+done:
+ return retval;
+}
+
+/**
+ * Writes all modified core registers for all processor modes. In normal
+ * operation this is called on exit from halting debug state.
+ *
+ * @param dpm: represents the processor
+ * @param bpwp: true ensures breakpoints and watchpoints are set,
+ * false ensures they are cleared
+ */
+int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
+{
+ struct arm *arm = dpm->arm;
+ struct reg_cache *cache = arm->core_cache;
+ int retval;
+
+ retval = dpm->prepare(dpm);
+ if (retval != ERROR_OK)
+ goto done;
+
+ /* If we're managing hardware breakpoints for this core, enable
+ * or disable them as requested.
+ *
+ * REVISIT We don't yet manage them for ANY cores. Eventually
+ * we should be able to assume we handle them; but until then,
+ * cope with the hand-crafted breakpoint code.
+ */
+ if (arm->target->type->add_breakpoint == dpm_add_breakpoint) {
+ for (unsigned i = 0; i < dpm->nbp; i++) {
+ struct dpm_bp *dbp = dpm->dbp + i;
+ struct breakpoint *bp = dbp->bp;
+
+ retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
+ bp ? &bp->set : NULL);
+ if (retval != ERROR_OK)
+ goto done;
+ }
+ }
+
+ /* enable/disable watchpoints */
+ for (unsigned i = 0; i < dpm->nwp; i++) {
+ struct dpm_wp *dwp = dpm->dwp + i;
+ struct watchpoint *wp = dwp->wp;
+
+ retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
+ wp ? &wp->set : NULL);
+ if (retval != ERROR_OK)
+ goto done;
+ }
+
+ /* NOTE: writes to breakpoint and watchpoint registers might
+ * be queued, and need (efficient/batched) flushing later.
+ */
+
+ if (cache->reg_list[0].size == 64)
+ retval = arm_dpm_write_dirty_registers_64(dpm);
+ else
+ retval = arm_dpm_write_dirty_registers_32(dpm);
+