gdb_server, target: Add target_address_bits()
[fw/openocd] / src / target / target.c
index 9fc9d20fcf5b8921e3526d6ec2b0458c56dff43f..5295dd626815ee86dacb4698218014c0b8303168 100644 (file)
 #include "image.h"
 #include "rtos/rtos.h"
 #include "transport/transport.h"
+#include "arm_cti.h"
 
 /* default halt wait timeout (ms) */
 #define DEFAULT_HALT_TIMEOUT 5000
 
-static int target_read_buffer_default(struct target *target, uint32_t address,
+static int target_read_buffer_default(struct target *target, target_addr_t address,
                uint32_t count, uint8_t *buffer);
-static int target_write_buffer_default(struct target *target, uint32_t address,
+static int target_write_buffer_default(struct target *target, target_addr_t address,
                uint32_t count, const uint8_t *buffer);
 static int target_array2mem(Jim_Interp *interp, struct target *target,
                int argc, Jim_Obj * const *argv);
@@ -88,6 +89,7 @@ extern struct target_type dragonite_target;
 extern struct target_type xscale_target;
 extern struct target_type cortexm_target;
 extern struct target_type cortexa_target;
+extern struct target_type aarch64_target;
 extern struct target_type cortexr4_target;
 extern struct target_type arm11_target;
 extern struct target_type ls1_sap_target;
@@ -104,6 +106,10 @@ extern struct target_type nds32_v3m_target;
 extern struct target_type or1k_target;
 extern struct target_type quark_x10xx_target;
 extern struct target_type quark_d20xx_target;
+extern struct target_type stm8_target;
+extern struct target_type riscv_target;
+extern struct target_type mem_ap_target;
+extern struct target_type esirisc_target;
 
 static struct target_type *target_types[] = {
        &arm7tdmi_target,
@@ -135,6 +141,13 @@ static struct target_type *target_types[] = {
        &or1k_target,
        &quark_x10xx_target,
        &quark_d20xx_target,
+       &stm8_target,
+       &riscv_target,
+       &mem_ap_target,
+       &esirisc_target,
+#if BUILD_TARGET64
+       &aarch64_target,
+#endif
        NULL,
 };
 
@@ -198,10 +211,6 @@ static const Jim_Nvp nvp_target_event[] = {
        { .value = TARGET_EVENT_RESET_ASSERT_POST,   .name = "reset-assert-post" },
        { .value = TARGET_EVENT_RESET_DEASSERT_PRE,  .name = "reset-deassert-pre" },
        { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
-       { .value = TARGET_EVENT_RESET_HALT_PRE,      .name = "reset-halt-pre" },
-       { .value = TARGET_EVENT_RESET_HALT_POST,     .name = "reset-halt-post" },
-       { .value = TARGET_EVENT_RESET_WAIT_PRE,      .name = "reset-wait-pre" },
-       { .value = TARGET_EVENT_RESET_WAIT_POST,     .name = "reset-wait-post" },
        { .value = TARGET_EVENT_RESET_INIT,          .name = "reset-init" },
        { .value = TARGET_EVENT_RESET_END,           .name = "reset-end" },
 
@@ -242,6 +251,7 @@ static const Jim_Nvp nvp_target_debug_reason[] = {
        { .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
        { .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
        { .name = "program-exit"             , .value = DBG_REASON_EXIT },
+       { .name = "exception-catch"          , .value = DBG_REASON_EXC_CATCH },
        { .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
        { .name = NULL, .value = -1 },
 };
@@ -283,6 +293,10 @@ const char *target_state_name(struct target *t)
                LOG_ERROR("Invalid target state: %d", (int)(t->state));
                cp = "(*BUG*unknown*BUG*)";
        }
+
+       if (!target_was_examined(t) && t->defer_examine)
+               cp = "examine deferred";
+
        return cp;
 }
 
@@ -504,7 +518,7 @@ struct target *get_target_by_num(int num)
 
 struct target *get_current_target(struct command_context *cmd_ctx)
 {
-       struct target *target = get_target_by_num(cmd_ctx->current_target);
+       struct target *target = get_current_target_or_null(cmd_ctx);
 
        if (target == NULL) {
                LOG_ERROR("BUG: current_target out of bounds");
@@ -514,6 +528,13 @@ struct target *get_current_target(struct command_context *cmd_ctx)
        return target;
 }
 
+struct target *get_current_target_or_null(struct command_context *cmd_ctx)
+{
+       return cmd_ctx->current_target_override
+               ? cmd_ctx->current_target_override
+               : cmd_ctx->current_target;
+}
+
 int target_poll(struct target *target)
 {
        int retval;
@@ -593,7 +614,8 @@ int target_halt(struct target *target)
  * hand the infrastructure for running such helpers might use this
  * procedure but rely on hardware breakpoint to detect termination.)
  */
-int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+int target_resume(struct target *target, int current, target_addr_t address,
+               int handle_breakpoints, int debug_execution)
 {
        int retval;
 
@@ -664,7 +686,7 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
 }
 
 static int identity_virt2phys(struct target *target,
-               uint32_t virtual, uint32_t *physical)
+               target_addr_t virtual, target_addr_t *physical)
 {
        *physical = virtual;
        return ERROR_OK;
@@ -731,6 +753,9 @@ int target_examine(void)
                        continue;
                }
 
+               if (target->defer_examine)
+                       continue;
+
                retval = target_examine_one(target);
                if (retval != ERROR_OK)
                        return retval;
@@ -798,8 +823,7 @@ done:
 }
 
 /**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
+ * Executes a target-specific native code algorithm and leaves it running.
  *
  * @param target used to run the algorithm
  * @param arch_info target-specific description of the algorithm.
@@ -872,12 +896,45 @@ done:
 }
 
 /**
- * Executes a target-specific native code algorithm in the target.
- * It differs from target_run_algorithm in that the algorithm is asynchronous.
- * Because of this it requires an compliant algorithm:
- * see contrib/loaders/flash/stm32f1x.S for example.
+ * Streams data to a circular buffer on target intended for consumption by code
+ * running asynchronously on target.
+ *
+ * This is intended for applications where target-specific native code runs
+ * on the target, receives data from the circular buffer, does something with
+ * it (most likely writing it to a flash memory), and advances the circular
+ * buffer pointer.
+ *
+ * This assumes that the helper algorithm has already been loaded to the target,
+ * but has not been started yet. Given memory and register parameters are passed
+ * to the algorithm.
+ *
+ * The buffer is defined by (buffer_start, buffer_size) arguments and has the
+ * following format:
+ *
+ *     [buffer_start + 0, buffer_start + 4):
+ *         Write Pointer address (aka head). Written and updated by this
+ *         routine when new data is written to the circular buffer.
+ *     [buffer_start + 4, buffer_start + 8):
+ *         Read Pointer address (aka tail). Updated by code running on the
+ *         target after it consumes data.
+ *     [buffer_start + 8, buffer_start + buffer_size):
+ *         Circular buffer contents.
+ *
+ * See contrib/loaders/flash/stm32f1x.S for an example.
  *
  * @param target used to run the algorithm
+ * @param buffer address on the host where data to be sent is located
+ * @param count number of blocks to send
+ * @param block_size size in bytes of each block
+ * @param num_mem_params count of memory-based params to pass to algorithm
+ * @param mem_params memory-based params to pass to algorithm
+ * @param num_reg_params count of register-based params to pass to algorithm
+ * @param reg_params memory-based params to pass to algorithm
+ * @param buffer_start address on the target of the circular buffer structure
+ * @param buffer_size size of the circular buffer structure
+ * @param entry_point address on the target to execute to start the algorithm
+ * @param exit_point address at which to set a breakpoint to catch the
+ *     end of the algorithm; can be 0 if target triggers a breakpoint itself
  */
 
 int target_run_flash_async_algorithm(struct target *target,
@@ -996,6 +1053,9 @@ int target_run_flash_async_algorithm(struct target *target,
                retval = target_write_u32(target, wp_addr, wp);
                if (retval != ERROR_OK)
                        break;
+
+               /* Avoid GDB timeouts */
+               keep_alive();
        }
 
        if (retval != ERROR_OK) {
@@ -1027,7 +1087,7 @@ int target_run_flash_async_algorithm(struct target *target,
 }
 
 int target_read_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -1041,7 +1101,7 @@ int target_read_memory(struct target *target,
 }
 
 int target_read_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -1055,7 +1115,7 @@ int target_read_phys_memory(struct target *target,
 }
 
 int target_write_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -1069,7 +1129,7 @@ int target_write_memory(struct target *target,
 }
 
 int target_write_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -1086,7 +1146,7 @@ int target_add_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_breakpoint(target, breakpoint);
@@ -1096,7 +1156,7 @@ int target_add_context_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add context breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_context_breakpoint(target, breakpoint);
@@ -1106,7 +1166,7 @@ int target_add_hybrid_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add hybrid breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_hybrid_breakpoint(target, breakpoint);
@@ -1122,7 +1182,7 @@ int target_add_watchpoint(struct target *target,
                struct watchpoint *watchpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_watchpoint(target, watchpoint);
@@ -1136,7 +1196,7 @@ int target_hit_watchpoint(struct target *target,
                struct watchpoint **hit_watchpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1150,14 +1210,31 @@ int target_hit_watchpoint(struct target *target,
        return target->type->hit_watchpoint(target, hit_watchpoint);
 }
 
+const char *target_get_gdb_arch(struct target *target)
+{
+       if (target->type->get_gdb_arch == NULL)
+               return NULL;
+       return target->type->get_gdb_arch(target);
+}
+
 int target_get_gdb_reg_list(struct target *target,
                struct reg **reg_list[], int *reg_list_size,
                enum target_register_class reg_class)
 {
        return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class);
 }
+
+bool target_supports_gdb_connection(struct target *target)
+{
+       /*
+        * based on current code, we can simply exclude all the targets that
+        * don't provide get_gdb_reg_list; this could change with new targets.
+        */
+       return !!target->type->get_gdb_reg_list;
+}
+
 int target_step(struct target *target,
-               int current, uint32_t address, int handle_breakpoints)
+               int current, target_addr_t address, int handle_breakpoints)
 {
        return target->type->step(target, current, address, handle_breakpoints);
 }
@@ -1165,7 +1242,7 @@ int target_step(struct target *target,
 int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (gdb fileio)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->get_gdb_fileio_info(target, fileio_info);
@@ -1174,17 +1251,33 @@ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fi
 int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (gdb fileio end)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c);
 }
 
+target_addr_t target_address_max(struct target *target)
+{
+       unsigned bits = target_address_bits(target);
+       if (sizeof(target_addr_t) * 8 == bits)
+               return (target_addr_t) -1;
+       else
+               return (((target_addr_t) 1) << bits) - 1;
+}
+
+unsigned target_address_bits(struct target *target)
+{
+       if (target->type->address_bits)
+               return target->type->address_bits(target);
+       return 32;
+}
+
 int target_profiling(struct target *target, uint32_t *samples,
                        uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (profiling)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->profiling(target, samples, max_num_samples,
@@ -1281,7 +1374,7 @@ static int target_init(struct command_context *cmd_ctx)
                return retval;
 
        retval = target_register_timer_callback(&handle_target,
-                       polling_interval, 1, cmd_ctx->interp);
+                       polling_interval, TARGET_TIMER_TYPE_PERIODIC, cmd_ctx->interp);
        if (ERROR_OK != retval)
                return retval;
 
@@ -1384,10 +1477,10 @@ int target_register_trace_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+int target_register_timer_callback(int (*callback)(void *priv),
+               unsigned int time_ms, enum target_timer_type type, void *priv)
 {
        struct target_timer_callback **callbacks_p = &target_timer_callbacks;
-       struct timeval now;
 
        if (callback == NULL)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1400,18 +1493,12 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
 
        (*callbacks_p) = malloc(sizeof(struct target_timer_callback));
        (*callbacks_p)->callback = callback;
-       (*callbacks_p)->periodic = periodic;
+       (*callbacks_p)->type = type;
        (*callbacks_p)->time_ms = time_ms;
        (*callbacks_p)->removed = false;
 
-       gettimeofday(&now, NULL);
-       (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
-       time_ms -= (time_ms % 1000);
-       (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
-       if ((*callbacks_p)->when.tv_usec > 1000000) {
-               (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
-               (*callbacks_p)->when.tv_sec += 1;
-       }
+       gettimeofday(&(*callbacks_p)->when, NULL);
+       timeval_add_time(&(*callbacks_p)->when, 0, time_ms * 1000);
 
        (*callbacks_p)->priv = priv;
        (*callbacks_p)->next = NULL;
@@ -1546,14 +1633,8 @@ int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data
 static int target_timer_callback_periodic_restart(
                struct target_timer_callback *cb, struct timeval *now)
 {
-       int time_ms = cb->time_ms;
-       cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000;
-       time_ms -= (time_ms % 1000);
-       cb->when.tv_sec = now->tv_sec + time_ms / 1000;
-       if (cb->when.tv_usec > 1000000) {
-               cb->when.tv_usec = cb->when.tv_usec - 1000000;
-               cb->when.tv_sec += 1;
-       }
+       cb->when = *now;
+       timeval_add_time(&cb->when, 0, cb->time_ms * 1000L);
        return ERROR_OK;
 }
 
@@ -1562,7 +1643,7 @@ static int target_call_timer_callback(struct target_timer_callback *cb,
 {
        cb->callback(cb->priv);
 
-       if (cb->periodic)
+       if (cb->type == TARGET_TIMER_TYPE_PERIODIC)
                return target_timer_callback_periodic_restart(cb, now);
 
        return target_unregister_timer_callback(cb->callback, cb->priv);
@@ -1596,10 +1677,8 @@ static int target_call_timer_callbacks_check_time(int checktime)
                }
 
                bool call_it = (*callback)->callback &&
-                       ((!checktime && (*callback)->periodic) ||
-                        now.tv_sec > (*callback)->when.tv_sec ||
-                        (now.tv_sec == (*callback)->when.tv_sec &&
-                         now.tv_usec >= (*callback)->when.tv_usec));
+                       ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) ||
+                        timeval_compare(&now, &(*callback)->when) >= 0);
 
                if (call_it)
                        target_call_timer_callback(*callback, &now);
@@ -1628,7 +1707,7 @@ static void print_wa_layout(struct target *target)
        struct working_area *c = target->working_areas;
 
        while (c) {
-               LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)",
+               LOG_DEBUG("%c%c " TARGET_ADDR_FMT "-" TARGET_ADDR_FMT " (%" PRIu32 " bytes)",
                        c->backup ? 'b' : ' ', c->free ? ' ' : '*',
                        c->address, c->address + c->size - 1, c->size);
                c = c->next;
@@ -1713,7 +1792,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
                if (!enabled) {
                        if (target->working_area_phys_spec) {
                                LOG_DEBUG("MMU disabled, using physical "
-                                       "address for working memory 0x%08"PRIx32,
+                                       "address for working memory " TARGET_ADDR_FMT,
                                        target->working_area_phys);
                                target->working_area = target->working_area_phys;
                        } else {
@@ -1724,7 +1803,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
                } else {
                        if (target->working_area_virt_spec) {
                                LOG_DEBUG("MMU enabled, using virtual "
-                                       "address for working memory 0x%08"PRIx32,
+                                       "address for working memory " TARGET_ADDR_FMT,
                                        target->working_area_virt);
                                target->working_area = target->working_area_virt;
                        } else {
@@ -1767,7 +1846,8 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
        /* Split the working area into the requested size */
        target_split_working_area(c, size);
 
-       LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address);
+       LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT,
+                         size, c->address);
 
        if (target->backup_working_area) {
                if (c->backup == NULL) {
@@ -1811,7 +1891,7 @@ static int target_restore_working_area(struct target *target, struct working_are
        if (target->backup_working_area && area->backup != NULL) {
                retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup);
                if (retval != ERROR_OK)
-                       LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32,
+                       LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT,
                                        area->size, area->address);
        }
 
@@ -1835,7 +1915,7 @@ static int target_free_working_area_restore(struct target *target, struct workin
 
        area->free = true;
 
-       LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32,
+       LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT,
                        area->size, area->address);
 
        /* mark user pointer invalid */
@@ -1857,31 +1937,6 @@ int target_free_working_area(struct target *target, struct working_area *area)
        return target_free_working_area_restore(target, area, 1);
 }
 
-void target_quit(void)
-{
-       struct target_event_callback *pe = target_event_callbacks;
-       while (pe) {
-               struct target_event_callback *t = pe->next;
-               free(pe);
-               pe = t;
-       }
-       target_event_callbacks = NULL;
-
-       struct target_timer_callback *pt = target_timer_callbacks;
-       while (pt) {
-               struct target_timer_callback *t = pt->next;
-               free(pt);
-               pt = t;
-       }
-       target_timer_callbacks = NULL;
-
-       for (struct target *target = all_targets;
-            target; target = target->next) {
-               if (target->type->deinit_target)
-                       target->type->deinit_target(target);
-       }
-}
-
 /* free resources and restore memory, if restoring memory fails,
  * free up resources anyway
  */
@@ -1912,6 +1967,14 @@ static void target_free_all_working_areas_restore(struct target *target, int res
 void target_free_all_working_areas(struct target *target)
 {
        target_free_all_working_areas_restore(target, 1);
+
+       /* Now we have none or only one working area marked as free */
+       if (target->working_areas) {
+               /* Free the last one to allow on-the-fly moving and resizing */
+               free(target->working_areas->backup);
+               free(target->working_areas);
+               target->working_areas = NULL;
+       }
 }
 
 /* Find the largest number of bytes that can be allocated */
@@ -1933,17 +1996,83 @@ uint32_t target_get_working_area_avail(struct target *target)
        return max_size;
 }
 
+static void target_destroy(struct target *target)
+{
+       if (target->type->deinit_target)
+               target->type->deinit_target(target);
+
+       if (target->semihosting)
+               free(target->semihosting);
+
+       jtag_unregister_event_callback(jtag_enable_callback, target);
+
+       struct target_event_action *teap = target->event_action;
+       while (teap) {
+               struct target_event_action *next = teap->next;
+               Jim_DecrRefCount(teap->interp, teap->body);
+               free(teap);
+               teap = next;
+       }
+
+       target_free_all_working_areas(target);
+
+       /* release the targets SMP list */
+       if (target->smp) {
+               struct target_list *head = target->head;
+               while (head != NULL) {
+                       struct target_list *pos = head->next;
+                       head->target->smp = 0;
+                       free(head);
+                       head = pos;
+               }
+               target->smp = 0;
+       }
+
+       free(target->gdb_port_override);
+       free(target->type);
+       free(target->trace_info);
+       free(target->fileio_info);
+       free(target->cmd_name);
+       free(target);
+}
+
+void target_quit(void)
+{
+       struct target_event_callback *pe = target_event_callbacks;
+       while (pe) {
+               struct target_event_callback *t = pe->next;
+               free(pe);
+               pe = t;
+       }
+       target_event_callbacks = NULL;
+
+       struct target_timer_callback *pt = target_timer_callbacks;
+       while (pt) {
+               struct target_timer_callback *t = pt->next;
+               free(pt);
+               pt = t;
+       }
+       target_timer_callbacks = NULL;
+
+       for (struct target *target = all_targets; target;) {
+               struct target *tmp;
+
+               tmp = target->next;
+               target_destroy(target);
+               target = tmp;
+       }
+
+       all_targets = NULL;
+}
+
 int target_arch_state(struct target *target)
 {
        int retval;
        if (target == NULL) {
-               LOG_USER("No target has been configured");
+               LOG_WARNING("No target has been configured");
                return ERROR_OK;
        }
 
-       LOG_USER("%s: target state: %s", target_name(target),
-                target_state_name(target));
-
        if (target->state != TARGET_HALTED)
                return ERROR_OK;
 
@@ -2005,8 +2134,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
                        break;
 
                gettimeofday(&now, NULL);
-               if ((sample_count >= max_num_samples) ||
-                       ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) {
+               if ((sample_count >= max_num_samples) || timeval_compare(&now, &timeout) >= 0) {
                        LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
                        break;
                }
@@ -2020,9 +2148,9 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
+int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
 {
-       LOG_DEBUG("writing buffer of %" PRIi32 " byte at 0x%8.8" PRIx32,
+       LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
                          size, address);
 
        if (!target_was_examined(target)) {
@@ -2035,7 +2163,7 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
 
        if ((address + size - 1) < address) {
                /* GDB can request this when e.g. PC is 0xfffffffc */
-               LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")",
+               LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")",
                                  address,
                                  size);
                return ERROR_FAIL;
@@ -2044,7 +2172,8 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
        return target->type->write_buffer(target, address, size, buffer);
 }
 
-static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer)
+static int target_write_buffer_default(struct target *target,
+       target_addr_t address, uint32_t count, const uint8_t *buffer)
 {
        uint32_t size;
 
@@ -2081,9 +2210,9 @@ static int target_write_buffer_default(struct target *target, uint32_t address,
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
 {
-       LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32,
+       LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
                          size, address);
 
        if (!target_was_examined(target)) {
@@ -2096,7 +2225,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
 
        if ((address + size - 1) < address) {
                /* GDB can request this when e.g. PC is 0xfffffffc */
-               LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")",
+               LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")",
                                  address,
                                  size);
                return ERROR_FAIL;
@@ -2105,7 +2234,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
        return target->type->read_buffer(target, address, size, buffer);
 }
 
-static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer)
+static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
 {
        uint32_t size;
 
@@ -2138,7 +2267,7 @@ static int target_read_buffer_default(struct target *target, uint32_t address, u
        return ERROR_OK;
 }
 
-int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc)
+int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc)
 {
        uint8_t *buffer;
        int retval;
@@ -2178,24 +2307,22 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
        return retval;
 }
 
-int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank,
+int target_blank_check_memory(struct target *target,
+       struct target_memory_check_block *blocks, int num_blocks,
        uint8_t erased_value)
 {
-       int retval;
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (target->type->blank_check_memory == 0)
+       if (target->type->blank_check_memory == NULL)
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-       retval = target->type->blank_check_memory(target, address, size, blank, erased_value);
-
-       return retval;
+       return target->type->blank_check_memory(target, blocks, num_blocks, erased_value);
 }
 
-int target_read_u64(struct target *target, uint64_t address, uint64_t *value)
+int target_read_u64(struct target *target, target_addr_t address, uint64_t *value)
 {
        uint8_t value_buf[8];
        if (!target_was_examined(target)) {
@@ -2207,19 +2334,19 @@ int target_read_u64(struct target *target, uint64_t address, uint64_t *value)
 
        if (retval == ERROR_OK) {
                *value = target_buffer_get_u64(target, value_buf);
-               LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "",
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%" PRIx64 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_read_u32(struct target *target, uint32_t address, uint32_t *value)
+int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
 {
        uint8_t value_buf[4];
        if (!target_was_examined(target)) {
@@ -2231,19 +2358,19 @@ int target_read_u32(struct target *target, uint32_t address, uint32_t *value)
 
        if (retval == ERROR_OK) {
                *value = target_buffer_get_u32(target, value_buf);
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_read_u16(struct target *target, uint32_t address, uint16_t *value)
+int target_read_u16(struct target *target, target_addr_t address, uint16_t *value)
 {
        uint8_t value_buf[2];
        if (!target_was_examined(target)) {
@@ -2255,19 +2382,19 @@ int target_read_u16(struct target *target, uint32_t address, uint16_t *value)
 
        if (retval == ERROR_OK) {
                *value = target_buffer_get_u16(target, value_buf);
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4" PRIx16,
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16,
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_read_u8(struct target *target, uint32_t address, uint8_t *value)
+int target_read_u8(struct target *target, target_addr_t address, uint8_t *value)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -2277,19 +2404,19 @@ int target_read_u8(struct target *target, uint32_t address, uint8_t *value)
        int retval = target_read_memory(target, address, 1, 1, value);
 
        if (retval == ERROR_OK) {
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8,
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_write_u64(struct target *target, uint64_t address, uint64_t value)
+int target_write_u64(struct target *target, target_addr_t address, uint64_t value)
 {
        int retval;
        uint8_t value_buf[8];
@@ -2298,7 +2425,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "",
                          address,
                          value);
 
@@ -2310,7 +2437,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value)
        return retval;
 }
 
-int target_write_u32(struct target *target, uint32_t address, uint32_t value)
+int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
 {
        int retval;
        uint8_t value_buf[4];
@@ -2319,7 +2446,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
                          address,
                          value);
 
@@ -2331,7 +2458,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value)
        return retval;
 }
 
-int target_write_u16(struct target *target, uint32_t address, uint16_t value)
+int target_write_u16(struct target *target, target_addr_t address, uint16_t value)
 {
        int retval;
        uint8_t value_buf[2];
@@ -2340,7 +2467,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx16,
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16,
                          address,
                          value);
 
@@ -2352,7 +2479,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value)
        return retval;
 }
 
-int target_write_u8(struct target *target, uint32_t address, uint8_t value)
+int target_write_u8(struct target *target, target_addr_t address, uint8_t value)
 {
        int retval;
        if (!target_was_examined(target)) {
@@ -2360,7 +2487,7 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8,
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                          address, value);
 
        retval = target_write_memory(target, address, 1, 1, &value);
@@ -2370,6 +2497,87 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value)
        return retval;
 }
 
+int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value)
+{
+       int retval;
+       uint8_t value_buf[8];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "",
+                         address,
+                         value);
+
+       target_buffer_set_u64(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 8, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value)
+{
+       int retval;
+       uint8_t value_buf[4];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
+                         address,
+                         value);
+
+       target_buffer_set_u32(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 4, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value)
+{
+       int retval;
+       uint8_t value_buf[2];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16,
+                         address,
+                         value);
+
+       target_buffer_set_u16(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 2, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value)
+{
+       int retval;
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
+                         address, value);
+
+       retval = target_write_phys_memory(target, address, 1, 1, &value);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
 static int find_target(struct command_context *cmd_ctx, const char *name)
 {
        struct target *target = get_target(name);
@@ -2384,7 +2592,10 @@ static int find_target(struct command_context *cmd_ctx, const char *name)
                return ERROR_FAIL;
        }
 
-       cmd_ctx->current_target = target->target_number;
+       cmd_ctx->current_target = target;
+       if (cmd_ctx->current_target_override)
+               cmd_ctx->current_target_override = target;
+
        return ERROR_OK;
 }
 
@@ -2412,7 +2623,7 @@ COMMAND_HANDLER(handle_targets_command)
                else
                        state = "tap-disabled";
 
-               if (CMD_CTX->current_target == target->target_number)
+               if (CMD_CTX->current_target == target)
                        marker = '*';
 
                /* keep columns lined up to match the headers above */
@@ -2631,6 +2842,8 @@ COMMAND_HANDLER(handle_reg_command)
                        for (i = 0, reg = cache->reg_list;
                                        i < cache->num_regs;
                                        i++, reg++, count++) {
+                               if (reg->exist == false)
+                                       continue;
                                /* only print cached values if they are valid */
                                if (reg->valid) {
                                        value = buf_to_str(reg->value,
@@ -2684,14 +2897,15 @@ COMMAND_HANDLER(handle_reg_command)
                /* access a single register by its name */
                reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1);
 
-               if (!reg) {
-                       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
-                       return ERROR_OK;
-               }
+               if (!reg)
+                       goto not_found;
        }
 
        assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */
 
+       if (!reg->exist)
+               goto not_found;
+
        /* display a register */
        if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
                        && (CMD_ARGV[1][0] <= '9')))) {
@@ -2725,6 +2939,10 @@ COMMAND_HANDLER(handle_reg_command)
        }
 
        return ERROR_COMMAND_SYNTAX_ERROR;
+
+not_found:
+       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_poll_command)
@@ -2816,6 +3034,9 @@ COMMAND_HANDLER(handle_halt_command)
        LOG_DEBUG("-");
 
        struct target *target = get_current_target(CMD_CTX);
+
+       target->verbose_halt_msg = true;
+
        int retval = target_halt(target);
        if (ERROR_OK != retval)
                return retval;
@@ -2873,9 +3094,9 @@ COMMAND_HANDLER(handle_resume_command)
        /* with no CMD_ARGV, resume from current pc, addr = 0,
         * with one arguments, addr = CMD_ARGV[0],
         * handle breakpoints, not debugging */
-       uint32_t addr = 0;
+       target_addr_t addr = 0;
        if (CMD_ARGC == 1) {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current = 0;
        }
 
@@ -2892,10 +3113,10 @@ COMMAND_HANDLER(handle_step_command)
        /* with no CMD_ARGV, step from current pc, addr = 0,
         * with one argument addr = CMD_ARGV[0],
         * handle breakpoints, debugging */
-       uint32_t addr = 0;
+       target_addr_t addr = 0;
        int current_pc = 1;
        if (CMD_ARGC == 1) {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current_pc = 0;
        }
 
@@ -2905,7 +3126,7 @@ COMMAND_HANDLER(handle_step_command)
 }
 
 static void handle_md_output(struct command_context *cmd_ctx,
-               struct target *target, uint32_t address, unsigned size,
+               struct target *target, target_addr_t address, unsigned size,
                unsigned count, const uint8_t *buffer)
 {
        const unsigned line_bytecnt = 32;
@@ -2916,14 +3137,17 @@ static void handle_md_output(struct command_context *cmd_ctx,
 
        const char *value_fmt;
        switch (size) {
+       case 8:
+               value_fmt = "%16.16"PRIx64" ";
+               break;
        case 4:
-               value_fmt = "%8.8x ";
+               value_fmt = "%8.8"PRIx64" ";
                break;
        case 2:
-               value_fmt = "%4.4x ";
+               value_fmt = "%4.4"PRIx64" ";
                break;
        case 1:
-               value_fmt = "%2.2x ";
+               value_fmt = "%2.2"PRIx64" ";
                break;
        default:
                /* "can't happen", caller checked */
@@ -2935,13 +3159,16 @@ static void handle_md_output(struct command_context *cmd_ctx,
                if (i % line_modulo == 0) {
                        output_len += snprintf(output + output_len,
                                        sizeof(output) - output_len,
-                                       "0x%8.8x: ",
-                                       (unsigned)(address + (i*size)));
+                                       TARGET_ADDR_FMT ": ",
+                                       (address + (i * size)));
                }
 
-               uint32_t value = 0;
+               uint64_t value = 0;
                const uint8_t *value_ptr = buffer + i * size;
                switch (size) {
+               case 8:
+                       value = target_buffer_get_u64(target, value_ptr);
+                       break;
                case 4:
                        value = target_buffer_get_u32(target, value_ptr);
                        break;
@@ -2969,6 +3196,9 @@ COMMAND_HANDLER(handle_md_command)
 
        unsigned size = 0;
        switch (CMD_NAME[2]) {
+       case 'd':
+               size = 8;
+               break;
        case 'w':
                size = 4;
                break;
@@ -2984,7 +3214,7 @@ COMMAND_HANDLER(handle_md_command)
 
        bool physical = strcmp(CMD_ARGV[0], "phys") == 0;
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
+                       target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
        if (physical) {
                CMD_ARGC--;
                CMD_ARGV++;
@@ -2994,14 +3224,18 @@ COMMAND_HANDLER(handle_md_command)
        if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t address;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       target_addr_t address;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
 
        unsigned count = 1;
        if (CMD_ARGC == 2)
                COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
 
        uint8_t *buffer = calloc(count, size);
+       if (buffer == NULL) {
+               LOG_ERROR("Failed to allocate md read buffer");
+               return ERROR_FAIL;
+       }
 
        struct target *target = get_current_target(CMD_CTX);
        int retval = fn(target, address, size, count, buffer);
@@ -3014,14 +3248,14 @@ COMMAND_HANDLER(handle_md_command)
 }
 
 typedef int (*target_write_fn)(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
 
 static int target_fill_mem(struct target *target,
-               uint32_t address,
+               target_addr_t address,
                target_write_fn fn,
                unsigned data_size,
                /* value */
-               uint32_t b,
+               uint64_t b,
                /* count */
                unsigned c)
 {
@@ -3036,6 +3270,9 @@ static int target_fill_mem(struct target *target,
 
        for (unsigned i = 0; i < chunk_size; i++) {
                switch (data_size) {
+               case 8:
+                       target_buffer_set_u64(target, target_buf + i * data_size, b);
+                       break;
                case 4:
                        target_buffer_set_u32(target, target_buf + i * data_size, b);
                        break;
@@ -3084,11 +3321,11 @@ COMMAND_HANDLER(handle_mw_command)
        if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t address;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       target_addr_t address;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
 
-       uint32_t value;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+       target_addr_t value;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value);
 
        unsigned count = 1;
        if (CMD_ARGC == 3)
@@ -3097,6 +3334,9 @@ COMMAND_HANDLER(handle_mw_command)
        struct target *target = get_current_target(CMD_CTX);
        unsigned wordsize;
        switch (CMD_NAME[2]) {
+               case 'd':
+                       wordsize = 8;
+                       break;
                case 'w':
                        wordsize = 4;
                        break;
@@ -3114,7 +3354,7 @@ COMMAND_HANDLER(handle_mw_command)
 }
 
 static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
-               uint32_t *min_address, uint32_t *max_address)
+               target_addr_t *min_address, target_addr_t *max_address)
 {
        if (CMD_ARGC < 1 || CMD_ARGC > 5)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -3122,8 +3362,8 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
        /* a base address isn't always necessary,
         * default to 0x0 (i.e. don't relocate) */
        if (CMD_ARGC >= 2) {
-               uint32_t addr;
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image->base_address = addr;
                image->base_address_set = 1;
        } else
@@ -3132,9 +3372,9 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
        image->start_address_set = 0;
 
        if (CMD_ARGC >= 4)
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address);
        if (CMD_ARGC == 5) {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address);
                /* use size (given) to find max (required) */
                *max_address += *min_address;
        }
@@ -3150,8 +3390,8 @@ COMMAND_HANDLER(handle_load_image_command)
        uint8_t *buffer;
        size_t buf_cnt;
        uint32_t image_size;
-       uint32_t min_address = 0;
-       uint32_t max_address = 0xffffffff;
+       target_addr_t min_address = 0;
+       target_addr_t max_address = -1;
        int i;
        struct image image;
 
@@ -3166,7 +3406,7 @@ COMMAND_HANDLER(handle_load_image_command)
        duration_start(&bench);
 
        if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
-               return ERROR_OK;
+               return ERROR_FAIL;
 
        image_size = 0x0;
        retval = ERROR_OK;
@@ -3176,6 +3416,7 @@ COMMAND_HANDLER(handle_load_image_command)
                        command_print(CMD_CTX,
                                                  "error allocating buffer for section (%d bytes)",
                                                  (int)(image.sections[i].size));
+                       retval = ERROR_FAIL;
                        break;
                }
 
@@ -3209,7 +3450,7 @@ COMMAND_HANDLER(handle_load_image_command)
                                break;
                        }
                        image_size += length;
-                       command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
+                       command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "",
                                        (unsigned int)length,
                                        image.sections[i].base_address + offset);
                }
@@ -3234,15 +3475,15 @@ COMMAND_HANDLER(handle_dump_image_command)
        struct fileio *fileio;
        uint8_t *buffer;
        int retval, retvaltemp;
-       uint32_t address, size;
+       target_addr_t address, size;
        struct duration bench;
        struct target *target = get_current_target(CMD_CTX);
 
        if (CMD_ARGC != 3)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address);
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size);
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[1], address);
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[2], size);
 
        uint32_t buf_size = (size > 4096) ? 4096 : size;
        buffer = malloc(buf_size);
@@ -3291,7 +3532,13 @@ COMMAND_HANDLER(handle_dump_image_command)
        return retval;
 }
 
-static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
+enum verify_mode {
+       IMAGE_TEST = 0,
+       IMAGE_VERIFY = 1,
+       IMAGE_CHECKSUM_ONLY = 2
+};
+
+static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode verify)
 {
        uint8_t *buffer;
        size_t buf_cnt;
@@ -3317,8 +3564,8 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
        duration_start(&bench);
 
        if (CMD_ARGC >= 2) {
-               uint32_t addr;
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image.base_address = addr;
                image.base_address_set = 1;
        } else {
@@ -3349,7 +3596,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                        break;
                }
 
-               if (verify) {
+               if (verify >= IMAGE_VERIFY) {
                        /* calculate checksum of image */
                        retval = image_calculate_checksum(buffer, buf_cnt, &checksum);
                        if (retval != ERROR_OK) {
@@ -3362,7 +3609,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                free(buffer);
                                break;
                        }
-
+                       if ((checksum != mem_checksum) && (verify == IMAGE_CHECKSUM_ONLY)) {
+                               LOG_ERROR("checksum mismatch");
+                               free(buffer);
+                               retval = ERROR_FAIL;
+                               goto done;
+                       }
                        if (checksum != mem_checksum) {
                                /* failed crc checksum, fall back to a binary compare */
                                uint8_t *data;
@@ -3403,7 +3655,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                free(data);
                        }
                } else {
-                       command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
+                       command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx",
                                                  image.sections[i].base_address,
                                                  buf_cnt);
                }
@@ -3427,14 +3679,19 @@ done:
        return retval;
 }
 
+COMMAND_HANDLER(handle_verify_image_checksum_command)
+{
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_CHECKSUM_ONLY);
+}
+
 COMMAND_HANDLER(handle_verify_image_command)
 {
-       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1);
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_VERIFY);
 }
 
 COMMAND_HANDLER(handle_test_image_command)
 {
-       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0);
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST);
 }
 
 static int handle_bp_command_list(struct command_context *cmd_ctx)
@@ -3445,7 +3702,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
                if (breakpoint->type == BKPT_SOFT) {
                        char *buf = buf_to_str(breakpoint->orig_instr,
                                        breakpoint->length, 16);
-                       command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
+                       command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s",
                                        breakpoint->address,
                                        breakpoint->length,
                                        breakpoint->set, buf);
@@ -3456,13 +3713,13 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
                                                        breakpoint->asid,
                                                        breakpoint->length, breakpoint->set);
                        else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                               command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+                               command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
                                                        breakpoint->address,
                                                        breakpoint->length, breakpoint->set);
                                command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
                                                        breakpoint->asid);
                        } else
-                               command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+                               command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
                                                        breakpoint->address,
                                                        breakpoint->length, breakpoint->set);
                }
@@ -3473,50 +3730,43 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
 }
 
 static int handle_bp_command_set(struct command_context *cmd_ctx,
-               uint32_t addr, uint32_t asid, uint32_t length, int hw)
+               target_addr_t addr, uint32_t asid, uint32_t length, int hw)
 {
        struct target *target = get_current_target(cmd_ctx);
        int retval;
 
        if (asid == 0) {
                retval = breakpoint_add(target, addr, length, hw);
+               /* error is always logged in breakpoint_add(), do not print it again */
                if (ERROR_OK == retval)
-                       command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used");
-                       return retval;
-               }
+                       command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr);
+
        } else if (addr == 0) {
                if (target->type->add_context_breakpoint == NULL) {
-                       LOG_WARNING("Context breakpoint not available");
-                       return ERROR_OK;
+                       LOG_ERROR("Context breakpoint not available");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                retval = context_breakpoint_add(target, asid, length, hw);
+               /* error is always logged in context_breakpoint_add(), do not print it again */
                if (ERROR_OK == retval)
                        command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used");
-                       return retval;
-               }
+
        } else {
                if (target->type->add_hybrid_breakpoint == NULL) {
-                       LOG_WARNING("Hybrid breakpoint not available");
-                       return ERROR_OK;
+                       LOG_ERROR("Hybrid breakpoint not available");
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+               /* error is always logged in hybrid_breakpoint_add(), do not print it again */
                if (ERROR_OK == retval)
                        command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address is already used");
-                       return retval;
-               }
        }
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_bp_command)
 {
-       uint32_t addr;
+       target_addr_t addr;
        uint32_t asid;
        uint32_t length;
        int hw = BKPT_SOFT;
@@ -3527,17 +3777,15 @@ COMMAND_HANDLER(handle_bp_command)
 
                case 2:
                        asid = 0;
-                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
                        return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
 
                case 3:
                        if (strcmp(CMD_ARGV[2], "hw") == 0) {
                                hw = BKPT_HARD;
-                               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
+                               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
                                asid = 0;
                                return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
                        } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) {
@@ -3547,10 +3795,10 @@ COMMAND_HANDLER(handle_bp_command)
                                addr = 0;
                                return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
                        }
-
+                       /* fallthrough */
                case 4:
                        hw = BKPT_HARD;
-                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length);
                        return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
@@ -3565,8 +3813,8 @@ COMMAND_HANDLER(handle_rbp_command)
        if (CMD_ARGC != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t addr;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+       target_addr_t addr;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
 
        struct target *target = get_current_target(CMD_CTX);
        breakpoint_remove(target, addr);
@@ -3582,7 +3830,7 @@ COMMAND_HANDLER(handle_wp_command)
                struct watchpoint *watchpoint = target->watchpoints;
 
                while (watchpoint) {
-                       command_print(CMD_CTX, "address: 0x%8.8" PRIx32
+                       command_print(CMD_CTX, "address: " TARGET_ADDR_FMT
                                        ", len: 0x%8.8" PRIx32
                                        ", r/w/a: %i, value: 0x%8.8" PRIx32
                                        ", mask: 0x%8.8" PRIx32,
@@ -3667,14 +3915,14 @@ COMMAND_HANDLER(handle_virt2phys_command)
        if (CMD_ARGC != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t va;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va);
-       uint32_t pa;
+       target_addr_t va;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], va);
+       target_addr_t pa;
 
        struct target *target = get_current_target(CMD_CTX);
        int retval = target->type->virt2phys(target, va, &pa);
        if (retval == ERROR_OK)
-               command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa);
+               command_print(CMD_CTX, "Physical address " TARGET_ADDR_FMT "", pa);
 
        return retval;
 }
@@ -3703,7 +3951,7 @@ typedef unsigned char UNIT[2];  /* unit of profiling */
 
 /* Dump a gmon.out histogram file. */
 static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range,
-                       uint32_t start_address, uint32_t end_address, struct target *target)
+                       uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms)
 {
        uint32_t i;
        FILE *f = fopen(filename, "w");
@@ -3771,7 +4019,8 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena
        writeLong(f, min, target);                      /* low_pc */
        writeLong(f, max, target);                      /* high_pc */
        writeLong(f, numBuckets, target);       /* # of buckets */
-       writeLong(f, 100, target);                      /* KLUDGE! We lie, ca. 100Hz best case. */
+       float sample_rate = sampleNum / (duration_ms / 1000.0);
+       writeLong(f, sample_rate, target);
        writeString(f, "seconds");
        for (i = 0; i < (15-strlen("seconds")); i++)
                writeData(f, &zero, 1);
@@ -3820,6 +4069,7 @@ COMMAND_HANDLER(handle_profile_command)
                return ERROR_FAIL;
        }
 
+       uint64_t timestart_ms = timeval_ms();
        /**
         * Some cores let us sample the PC without the
         * annoying halt/resume step; for example, ARMv7 PCSR.
@@ -3831,6 +4081,7 @@ COMMAND_HANDLER(handle_profile_command)
                free(samples);
                return retval;
        }
+       uint32_t duration_ms = timeval_ms() - timestart_ms;
 
        assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM);
 
@@ -3863,7 +4114,7 @@ COMMAND_HANDLER(handle_profile_command)
        }
 
        write_gmon(samples, num_of_samples, CMD_ARGV[1],
-                  with_range, start_address, end_address, target);
+                  with_range, start_address, end_address, target, duration_ms);
        command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
 
        free(samples);
@@ -3933,8 +4184,9 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
         * argv[3] = memory address
         * argv[4] = count of times to read
         */
+
        if (argc < 4 || argc > 5) {
-               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]");
+               Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]");
                return JIM_ERR;
        }
        varname = Jim_GetString(argv[0], &len);
@@ -4283,17 +4535,28 @@ void target_handle_event(struct target *target, enum target_event e)
 
        for (teap = target->event_action; teap != NULL; teap = teap->next) {
                if (teap->event == e) {
-                       LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s",
+                       LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s",
                                           target->target_number,
                                           target_name(target),
                                           target_type_name(target),
                                           e,
                                           Jim_Nvp_value2name_simple(nvp_target_event, e)->name,
                                           Jim_GetString(teap->body, NULL));
+
+                       /* Override current target by the target an event
+                        * is issued from (lot of scripts need it).
+                        * Return back to previous override as soon
+                        * as the handler processing is done */
+                       struct command_context *cmd_ctx = current_command_context(teap->interp);
+                       struct target *saved_target_override = cmd_ctx->current_target_override;
+                       cmd_ctx->current_target_override = target;
+
                        if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) {
                                Jim_MakeErrorMessage(teap->interp);
                                command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
                        }
+
+                       cmd_ctx->current_target_override = saved_target_override;
                }
        }
 }
@@ -4324,6 +4587,8 @@ enum target_cfg_param {
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
        TCFG_RTOS,
+       TCFG_DEFER_EXAMINE,
+       TCFG_GDB_PORT,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -4338,6 +4603,8 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
        { .name = "-dbgbase",          .value = TCFG_DBGBASE },
        { .name = "-rtos",             .value = TCFG_RTOS },
+       { .name = "-defer-examine",    .value = TCFG_DEFER_EXAMINE },
+       { .name = "-gdb-port",         .value = TCFG_GDB_PORT },
        { .name = NULL, .value = -1 }
 };
 
@@ -4572,6 +4839,13 @@ no_params:
                        if (goi->isconfigure) {
                                Jim_Obj *o_t;
                                struct jtag_tap *tap;
+
+                               if (target->has_dap) {
+                                       Jim_SetResultString(goi->interp,
+                                               "target requires -dap parameter instead of -chain-position!", -1);
+                                       return JIM_ERR;
+                               }
+
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Obj(goi, &o_t);
                                if (e != JIM_OK)
@@ -4579,8 +4853,8 @@ no_params:
                                tap = jtag_tap_by_jim_obj(goi->interp, o_t);
                                if (tap == NULL)
                                        return JIM_ERR;
-                               /* make this exactly 1 or 0 */
                                target->tap = tap;
+                               target->tap_configured = true;
                        } else {
                                if (goi->argc != 0)
                                        goto no_params;
@@ -4602,7 +4876,6 @@ no_params:
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
                        /* loop for more */
                        break;
-
                case TCFG_RTOS:
                        /* RTOS */
                        {
@@ -4612,6 +4885,27 @@ no_params:
                        }
                        /* loop for more */
                        break;
+
+               case TCFG_DEFER_EXAMINE:
+                       /* DEFER_EXAMINE */
+                       target->defer_examine = true;
+                       /* loop for more */
+                       break;
+
+               case TCFG_GDB_PORT:
+                       if (goi->isconfigure) {
+                               const char *s;
+                               e = Jim_GetOpt_String(goi, &s, NULL);
+                               if (e != JIM_OK)
+                                       return e;
+                               target->gdb_port_override = strdup(s);
+                       } else {
+                               if (goi->argc != 0)
+                                       goto no_params;
+                       }
+                       Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1);
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -4626,12 +4920,9 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a
 
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
        goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure");
-       int need_args = 1 + goi.isconfigure;
-       if (goi.argc < need_args) {
+       if (goi.argc < 1) {
                Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
-                       goi.isconfigure
-                               ? "missing: -option VALUE ..."
-                               : "missing: -option ...");
+                                "missing: -option ...");
                return JIM_ERR;
        }
        struct target *target = Jim_CmdPrivData(goi.interp);
@@ -4744,7 +5035,7 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
 
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+                       target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer);
        fn = target_read_memory;
 
        int e;
@@ -4882,20 +5173,58 @@ static int jim_target_tap_disabled(Jim_Interp *interp)
 
 static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1) {
-               Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
+       bool allow_defer = false;
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+       if (goi.argc > 1) {
+               const char *cmd_name = Jim_GetString(argv[0], NULL);
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s ['allow-defer']", cmd_name);
                return JIM_ERR;
        }
+       if (goi.argc > 0 &&
+           strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) {
+               /* consume it */
+               struct Jim_Obj *obj;
+               int e = Jim_GetOpt_Obj(&goi, &obj);
+               if (e != JIM_OK)
+                       return e;
+               allow_defer = true;
+       }
+
        struct target *target = Jim_CmdPrivData(interp);
        if (!target->tap->enabled)
                return jim_target_tap_disabled(interp);
 
+       if (allow_defer && target->defer_examine) {
+               LOG_INFO("Deferring arp_examine of %s", target_name(target));
+               LOG_INFO("Use arp_examine command to examine it manually!");
+               return JIM_OK;
+       }
+
        int e = target->type->examine(target);
        if (e != ERROR_OK)
                return JIM_ERR;
        return JIM_OK;
 }
 
+static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       struct target *target = Jim_CmdPrivData(interp);
+
+       Jim_SetResultBool(interp, target_was_examined(target));
+       return JIM_OK;
+}
+
+static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       struct target *target = Jim_CmdPrivData(interp);
+
+       Jim_SetResultBool(interp, target->defer_examine);
+       return JIM_OK;
+}
+
 static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        if (argc != 1) {
@@ -4963,6 +5292,10 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                                target_name(target));
                return JIM_ERR;
        }
+
+       if (target->defer_examine)
+               target_reset_examined(target);
+
        /* determine if we should halt or not. */
        target->reset_halt = !!a;
        /* When this happens - all workareas are invalid. */
@@ -5173,6 +5506,19 @@ static const struct command_registration target_instance_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .jim_handler = jim_target_examine,
                .help = "used internally for reset processing",
+               .usage = "['allow-defer']",
+       },
+       {
+               .name = "was_examined",
+               .mode = COMMAND_EXEC,
+               .jim_handler = jim_target_was_examined,
+               .help = "used internally for reset processing",
+       },
+       {
+               .name = "examine_deferred",
+               .mode = COMMAND_EXEC,
+               .jim_handler = jim_target_examine_deferred,
+               .help = "used internally for reset processing",
        },
        {
                .name = "arp_halt_gdb",
@@ -5293,7 +5639,7 @@ static int target_create(Jim_GetOptInfo *goi)
        target = calloc(1, sizeof(struct target));
        /* set target number */
        target->target_number = new_target_number();
-       cmd_ctx->current_target = target->target_number;
+       cmd_ctx->current_target = target;
 
        /* allocate memory for each unique target type */
        target->type = calloc(1, sizeof(struct target_type));
@@ -5319,19 +5665,12 @@ static int target_create(Jim_GetOptInfo *goi)
        target->next                = NULL;
        target->arch_info           = NULL;
 
-       target->display             = 1;
+       target->verbose_halt_msg        = true;
 
        target->halt_issued                     = false;
 
        /* initialize trace information */
-       target->trace_info = malloc(sizeof(struct trace));
-       target->trace_info->num_trace_points         = 0;
-       target->trace_info->trace_points_size        = 0;
-       target->trace_info->trace_points             = NULL;
-       target->trace_info->trace_history_size       = 0;
-       target->trace_info->trace_history            = NULL;
-       target->trace_info->trace_history_pos        = 0;
-       target->trace_info->trace_history_overflowed = 0;
+       target->trace_info = calloc(1, sizeof(struct trace));
 
        target->dbgmsg          = NULL;
        target->dbg_msg_enabled = 0;
@@ -5341,16 +5680,31 @@ static int target_create(Jim_GetOptInfo *goi)
        target->rtos = NULL;
        target->rtos_auto_detect = false;
 
+       target->gdb_port_override = NULL;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
 
-       if (target->tap == NULL) {
-               Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
-               e = JIM_ERR;
+       if (e == JIM_OK) {
+               if (target->has_dap) {
+                       if (!target->dap_configured) {
+                               Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               } else {
+                       if (!target->tap_configured) {
+                               Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               }
+               /* tap must be set after target was configured */
+               if (target->tap == NULL)
+                       e = JIM_ERR;
        }
 
        if (e != JIM_OK) {
+               free(target->gdb_port_override);
                free(target->type);
                free(target);
                return e;
@@ -5364,14 +5718,24 @@ static int target_create(Jim_GetOptInfo *goi)
        cp = Jim_GetString(new_cmd, NULL);
        target->cmd_name = strdup(cp);
 
+       if (target->type->target_create) {
+               e = (*(target->type->target_create))(target, goi->interp);
+               if (e != ERROR_OK) {
+                       LOG_DEBUG("target_create failed");
+                       free(target->gdb_port_override);
+                       free(target->type);
+                       free(target->cmd_name);
+                       free(target);
+                       return JIM_ERR;
+               }
+       }
+
        /* create the target specific commands */
        if (target->type->commands) {
                e = register_commands(cmd_ctx, NULL, target->type->commands);
                if (ERROR_OK != e)
                        LOG_ERROR("unable to register '%s' commands", cp);
        }
-       if (target->type->target_create)
-               (*(target->type->target_create))(target, goi->interp);
 
        /* append to end of list */
        {
@@ -5529,8 +5893,7 @@ static const struct command_registration target_subcommand_handlers[] = {
        },
        {
                .name = "create",
-               /* REVISIT this should be COMMAND_CONFIG ... */
-               .mode = COMMAND_ANY,
+               .mode = COMMAND_CONFIG,
                .jim_handler = jim_target_create,
                .usage = "name type '-chain-position' name [options ...]",
                .help = "Creates and selects a new target",
@@ -5566,7 +5929,7 @@ static const struct command_registration target_subcommand_handlers[] = {
 };
 
 struct FastLoad {
-       uint32_t address;
+       target_addr_t address;
        uint8_t *data;
        int length;
 
@@ -5593,8 +5956,8 @@ COMMAND_HANDLER(handle_fast_load_image_command)
        uint8_t *buffer;
        size_t buf_cnt;
        uint32_t image_size;
-       uint32_t min_address = 0;
-       uint32_t max_address = 0xffffffff;
+       target_addr_t min_address = 0;
+       target_addr_t max_address = -1;
        int i;
 
        struct image image;
@@ -6064,6 +6427,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .help = "step one instruction from current PC or address",
                .usage = "[address]",
        },
+       {
+               .name = "mdd",
+               .handler = handle_md_command,
+               .mode = COMMAND_EXEC,
+               .help = "display memory words",
+               .usage = "['phys'] address [count]",
+       },
        {
                .name = "mdw",
                .handler = handle_md_command,
@@ -6085,6 +6455,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .help = "display memory bytes",
                .usage = "['phys'] address [count]",
        },
+       {
+               .name = "mwd",
+               .handler = handle_mw_command,
+               .mode = COMMAND_EXEC,
+               .help = "write memory word",
+               .usage = "['phys'] address value [count]",
+       },
        {
                .name = "mww",
                .handler = handle_mw_command,
@@ -6111,7 +6488,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .handler = handle_bp_command,
                .mode = COMMAND_EXEC,
                .help = "list or set hardware or software breakpoint",
-               .usage = "<address> [<asid>]<length> ['hw'|'hw_ctx']",
+               .usage = "<address> [<asid>] <length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",
@@ -6147,6 +6524,12 @@ static const struct command_registration target_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .usage = "filename address size",
        },
+       {
+               .name = "verify_image_checksum",
+               .handler = handle_verify_image_checksum_command,
+               .mode = COMMAND_EXEC,
+               .usage = "filename [offset [type]]",
+       },
        {
                .name = "verify_image",
                .handler = handle_verify_image_command,