+done:
+ return retval;
+}
+
+static int arm_dpm_write_dirty_registers_64(struct arm_dpm *dpm)
+{
+ struct arm *arm = dpm->arm;
+ struct reg_cache *cache = arm->core_cache;
+ int retval;
+
+ /* Scan the registers until we find one that's both dirty and
+ * eligible for flushing. Flush that and everything else that
+ * shares the same core mode setting. Typically this won't
+ * actually find anything to do...
+ */
+
+ /* check everything except our scratch register R0 */
+ for (unsigned i = 1; i <= 32; i++) {
+ struct arm_reg *r;
+ unsigned regnum;
+
+ if (!cache->reg_list[i].dirty)
+ continue;
+
+ r = cache->reg_list[i].arch_info;
+ regnum = r->num;
+ retval = dpm_write_reg(dpm,
+ &cache->reg_list[i],
+ regnum);
+ if (retval != ERROR_OK)
+ goto done;
+ }
+
+ /* flush R0 -- it's *very* dirty by now */
+ retval = dpm_write_reg(dpm, &cache->reg_list[0], 0);
+ if (retval != ERROR_OK)
+ goto done;
+ cache->reg_list[0].dirty = false;
+
+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);
+